|
|
1.1 root 1: /***********************************************************************\
2: * spyhook.C - Spy Global input hook interface library.
3: *
4: * Created: Microsoft, IBM Corporation 1990
5: *
6: * DISCLAIMER OF WARRANTIES. The following [enclosed] code is
7: * sample code created by Microsoft Corporation and/or IBM
8: * Corporation. This sample code is not part of any standard
9: * Microsoft or IBM product and is provided to you solely for
10: * the purpose of assisting you in the development of your
11: * applications. The code is provided "AS IS", without
12: * warranty of any kind. Neither Microsoft nor IBM shall be
13: * liable for any damages arising out of your use of the sample
14: * code, even if they have been advised of the possibility of
15: * such damages.
16: *
17: * Purpose: This dynlink is needed because global input hooks must
18: * reside in a DLL.
19: *
20: \***********************************************************************/
21: #define INCL_PM
22: #define INCL_DOSPROCESS
23: #define INCL_DOSMODULEMGR
24: #define INCL_DOSSEMAPHORES
25: #define INCL_ERRORS
26: #include <os2.h>
27: #include "spyhk32.h"
28:
29: // Needed to make a dll link properly
30: int _acrtused = 0;
31:
32: HMTX hmtxSpyHook; /* global semaphore for this module */
33: HEV hevSpyMsg; /* global semaphore for this module */
34:
35: HMODULE hmodSpy; /* dynlink module handle */
36: SHORT SpybHooks; /* Whichs Hook do we use */
37:
38: HAB habOwner = (HAB)0; /* Hook owner's anchore block */
39: HMQ hmqOwner = (HMQ)0; /* Hook owner's message queue */
40: BOOL fRecording = FALSE; /* Are we recording now? */
41: BOOL fAnythingToWatch = FALSE; /* Is there anything to watch */
42: BOOL fDispMsgsNotInList = TRUE; /* Disp msgs not in list? */
43:
44: /* Define array of window handles that we are going to process */
45: BOOL fInitialized = FALSE;
46: BOOL fProcessAllFrames = FALSE; /* Are we processing all frame messages */
47: BOOL fProcessAllWindows = FALSE;/* Are we processing all windows */
48: HWND *pahwndSpy = NULL; /* Array of hwnds to spy on, no max here */
49: int chwndSpy = 0; /* Max windows to spy */
50:
51: /* Define array of HMQ's to spy on */
52: HMQ *pahmqSpy = NULL; /* HMQ list to spy on */
53: int chmqSpy = 0; /* Count of hmqs we are spying on */
54:
55:
56: /* Define message filter array */
57: UCHAR rgMessageFilter[MAXMSGFILTERBYTES] = "";
58: UCHAR GMsgEnableAndType(USHORT); /* Is message in message list */
59: VOID GrabMsgDataWords(SHORT, UCHAR); /* Get extra words for message */
60: BOOL CopyStruct(UCHAR *pbSrc, UCHAR *pbDst, SHORT cb); /* Copy bytes */
61: void DebugBreak(void);
62:
63: /* Define an array of messages to pass to whomever calls us */
64:
65: QMSGSPY rgqmsgSpy[MAXMSGCNT]; /* Array of messages to process */
66: SHORT cmsgSpy = 0; /* Count of messages yet to be read */
67: SHORT imsgWrite = 0; /* Index to message to write out */
68: SHORT imsgRead = 0; /* Index to message to read */
69:
70: /* Use the Dos Sub allocate functions to make sure to use shared memory */
71: #define HEAPSIZE 16384 /* 16K should be plenty? */
72: PVOID pheapSpyHook; /* Heap to use for Spy Hook DLL */
73:
74: PBYTE AllocMem(ULONG cb);
75: VOID FreeMem(PBYTE pMem, ULONG cb);
76: BOOL EnterSem(ULONG ulWait);
77: BOOL LeaveSem(VOID);
78: BOOL SignalEvent(VOID);
79:
80:
81:
82: SHORT acbMPTypes[MP_MASK+1] = { /* Number of desired bytes to extract */
83: 0, /* Normal fields, no pointers */
84: sizeof(SWP), /* MPT_SWP */
85: sizeof(RECTL), /* MPT_RECTL */
86: 0, /* MPT_WNDPRMS we dont process yet */
87: sizeof(QMSG) /* MPT_QMSG */
88: };
89:
90:
91: /* Information for geting selector information in diffent PID context */
92: PIT pit = {0xffff, 0, 0L, NULL, 0};
93: USHORT selectorLNSpy = 0; /* Which Selector */
94: VOID SpyCheckPIDForIntercept(VOID);
95: ULONG EXPENTRY Init(ULONG hPDLL, HMODULE hmod);
96:
97: /***********************************************************************\
98: * VOID Init( hmod )
99: *
100: * Effect: Saves the Spy module handle
101: \***********************************************************************/
102: ULONG EXPENTRY Init(hPDLL, hmod)
103: ULONG hPDLL;
104: HMODULE hmod;
105: {
106: /* Save the module handle */
107: hmodSpy = hmod;
108:
109: return (ULONG)hmodSpy;
110:
111: /* Unreferenced formal parameters referenced here to prevent compiler
112: warning */
113: hPDLL;
114: }
115:
116:
117:
118:
119: /***************************** Exported Function ***********************\
120: * BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs)
121: * HAB hab;
122: * PQMSG lpqmsg;
123: * USHORT fs;
124: *
125: * Effect: This is the global input hook procedure. Note that hook
126: * procedures can be chained, so we always return FALSE to pass the
127: * message to the next guy in chain.
128: *
129: * Return value: FALSE to pass message to next hook procedure.
130: \***********************************************************************/
131: BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs )
132: HAB hab;
133: PQMSG lpqmsg;
134: USHORT fs;
135: {
136: UCHAR bMPType;
137:
138: /*
139: * Check first to see if we are looking for a process symbols
140: */
141: if (pit.pid != 0xffff)
142: SpyCheckPIDForIntercept();
143:
144: /*
145: * First check to see if we are processing any hook messages
146: */
147: if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
148: return (FALSE); /* No let the next one have it now */
149:
150: /*
151: * See if we have any messages to process - Recheck to make sure we
152: * Dont overwrite our queue.
153: */
154: if (!EnterSem(100L)) {
155: DebugBreak();
156: return (FALSE);
157: }
158: if (cmsgSpy < MAXMSGCNT) {
159: if (SpyFWindowInList(lpqmsg->hwnd, FALSE) &&
160: (bMPType = GMsgEnableAndType(lpqmsg->msg))) {
161: rgqmsgSpy[imsgWrite].fs = fs; /* Save the flags */
162: rgqmsgSpy[imsgWrite].qmsg = *lpqmsg; /* Save the message */
163:
164: GrabMsgDataWords(imsgWrite, bMPType);
165: imsgWrite++;
166:
167: if (imsgWrite == MAXMSGCNT)
168: imsgWrite = 0; /* Wrap around */
169: cmsgSpy++;
170: SignalEvent();
171: }
172: }
173:
174: LeaveSem();
175: return FALSE; /* Let system take normal action. */
176:
177: /* Unreferenced formal parameters referenced here to prevent compiler
178: warning */
179: hab;
180:
181: }
182:
183:
184: /***************************** Exported Function ***********************\
185: * BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask)
186: * HAB hab;
187: * PQMSG lpqmsg;
188: *
189: * Effect: This is the global input hook procedure. Note that hook
190: * procedures can be chained, so we always return FALSE to pass the
191: * message to the next guy in chain.
192: *
193: * Return value: FALSE to pass message to next hook procedure.
194: \***********************************************************************/
195: BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask )
196: HAB hab;
197: PSMHSTRUCT lpsmh;
198: BOOL fInterTask;
199: {
200: UCHAR bMPType;
201: PPIB ppib;
202: PTIB ptib;
203:
204: /*
205: * Check first to see if we are looking for a process symbols
206: */
207: if (pit.pid != 0xffff)
208: SpyCheckPIDForIntercept();
209:
210: /*
211: * First check to see if we are processing any hook messages
212: */
213: if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
214: return (FALSE); /* No let the next one have it now */
215:
216: /*
217: * See if we have any messages to process
218: */
219: if (!EnterSem(100L)) {
220: DebugBreak();
221: return (FALSE);
222: }
223: /* Make sure no one got in by mistake */
224: if (cmsgSpy < MAXMSGCNT) {
225: if (SpyFWindowInList(lpsmh->hwnd, FALSE) &&
226: (bMPType = GMsgEnableAndType(lpsmh->msg))) {
227: /*
228: * Store out message, must move pieces seperatly
229: */
230: rgqmsgSpy[imsgWrite].fs = fInterTask;
231: rgqmsgSpy[imsgWrite].qmsg.hwnd = lpsmh->hwnd;
232: rgqmsgSpy[imsgWrite].qmsg.msg = lpsmh->msg;
233: rgqmsgSpy[imsgWrite].qmsg.mp1 = lpsmh->mp1;
234: rgqmsgSpy[imsgWrite].qmsg.mp2 = lpsmh->mp2;
235: rgqmsgSpy[imsgWrite].qmsg.time = (ULONG)-1;
236: rgqmsgSpy[imsgWrite].qmsg.ptl.x = 0;
237: rgqmsgSpy[imsgWrite].qmsg.ptl.y = 0;
238:
239: GrabMsgDataWords(imsgWrite, bMPType);
240:
241: /* Now get the PID/TID info, and do the stack backtrace */
242: DosGetThreadInfo(&ptib, &ppib);
243: rgqmsgSpy[imsgWrite].pidSend = ppib->pib_ulpid;
244: rgqmsgSpy[imsgWrite].tidSend = ptib->tib_ultid;
245:
246: imsgWrite++;
247: if (imsgWrite == MAXMSGCNT)
248: imsgWrite = 0; /* Wrap around */
249: cmsgSpy++;
250: SignalEvent();
251: }
252: }
253:
254: LeaveSem();
255: return FALSE; /* Let system take normal action. */
256:
257: /* Unreferenced formal parameters referenced here to prevent compiler
258: warning */
259: hab;
260:
261: }
262:
263:
264: /*************************** Public Function ***************************\
265: * BOOL EXPENTRY SpyInstallHook( hab, hmq, fSendMessage, bHooks)
266: *
267: * Effect: This routine installs a system-wide HK_INPUT hook. The hab
268: * hmq are remembered for message posting. Note that we only allow
269: * one input hook to be installed through this routine, but other
270: * apps may call WinSetHook directly.
271: *
272: * Returns value: TRUE if hook installed successfully, FALSE otherwise.
273: \***********************************************************************/
274: BOOL EXPENTRY SpyInstallHook( hab, hmq, bHooks )
275: HAB hab;
276: HMQ hmq;
277: USHORT bHooks;
278: {
279: BOOL fRet;
280: ULONG ulPostCt;
281:
282: EnterSem(-1L);
283:
284:
285: /*
286: * Look at hook index if == HK_INPUT Install a system-wide input hook.
287: * else set system wide SENDMSG hook
288: */
289: SpybHooks = bHooks;
290: if (SpybHooks & SPYH_INPUT)
291: fRet = WinSetHook( hab, (HMQ)0, HK_INPUT, (PFN)SpyInputHook,
292: hmodSpy );
293:
294: if (SpybHooks & SPYH_SENDMSG)
295: fRet = WinSetHook( hab, (HMQ)0, HK_SENDMSG, (PFN)SpySendMsgHook,
296: hmodSpy );
297: if (fRet) {
298: habOwner = hab;
299: hmqOwner = hmq;
300: }
301:
302: DosResetEventSem(hevSpyMsg, &ulPostCt); /* Init, no messages avail */
303: LeaveSem();
304:
305: return fRet;
306: }
307:
308:
309:
310: /*************************** Public Function ***************************\
311: * BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd)
312: *
313: * Effect: This routine sets the list of window that we are interested
314: * in watching the messages for.
315: *
316: * Returns value: TRUE
317: \***********************************************************************/
318: BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd )
319: SHORT chwnd;
320: HWND *rghwnd;
321: {
322: SHORT i;
323: HWND *phwndT;
324:
325: EnterSem(-1L);
326:
327: if (pahwndSpy) {
328: FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
329: pahwndSpy = NULL;
330: }
331:
332:
333: chwndSpy = chwnd;
334:
335: if (chwndSpy > 0 ) {
336:
337: phwndT = pahwndSpy = (HWND *)AllocMem(sizeof(HWND) * chwndSpy);
338:
339: if (phwndT != NULL) {
340: for (i=0; i < chwnd; i++) {
341: *phwndT++ = *rghwnd++;
342: }
343: } else
344: chwndSpy = 0;
345: }
346:
347: fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
348: fProcessAllWindows || fProcessAllFrames;
349:
350: LeaveSem();
351: return(TRUE);
352: }
353:
354:
355: /*************************** Public Function ***************************\
356: * BOOL EXPENTRY SpyGetWindowList( chwnd, rghwnd)
357: *
358: * Effect: This routine sets the list of window that we are interested
359: * in watching the messages for.
360: *
361: * Returns value: TRUE
362: \***********************************************************************/
363: SHORT EXPENTRY SpyGetWindowList( chwnd, rghwnd )
364: SHORT chwnd;
365: HWND *rghwnd;
366: {
367: SHORT i;
368: HWND *phwndT;
369:
370: EnterSem(-1L);
371:
372: if (chwnd > chwndSpy)
373: chwnd = chwndSpy;
374:
375: phwndT = pahwndSpy;
376: for (i=0; i < chwnd; i++) {
377: *rghwnd++ = *phwndT++;
378: }
379:
380: LeaveSem();
381:
382: return(chwnd);
383: }
384:
385:
386:
387:
388: /*************************** Public Function ***************************\
389: * BOOL EXPENTRY SpySetQueueList( chmq, rghmq)
390: *
391: * Effect: This routine sets the list of Queue that we are interested
392: * in watching the messages for.
393: *
394: * Returns value: TRUE
395: \***********************************************************************/
396: BOOL EXPENTRY SpySetQueueList( chmq, rghmq )
397: SHORT chmq;
398: HMQ *rghmq;
399: {
400: SHORT i;
401: HMQ *phmqT;
402:
403: EnterSem(-1L);
404:
405: /*
406: * If we previously had a list of HMQs to spy on, free the old list
407: * now
408: */
409: if (pahmqSpy != NULL) {
410: FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
411: pahmqSpy = NULL;
412: }
413:
414: chmqSpy = chmq;
415:
416: if (chmqSpy > 0) {
417: phmqT = pahmqSpy = (HMQ *)AllocMem(sizeof(HMQ) * chmqSpy);
418:
419: if (phmqT != NULL) {
420: for (i=0; i < chmq; i++) {
421: *phmqT++ = *rghmq++;
422: }
423: } else
424: chmqSpy = 0;
425: }
426:
427: fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
428: fProcessAllWindows || fProcessAllFrames;
429: LeaveSem();
430:
431: return(TRUE);
432: }
433:
434:
435: /*************************** Public Function ***************************\
436: * BOOL EXPENTRY SpyGetQueueList( chmq, rghmq)
437: *
438: * Effect: This routine sets the list of Queue that we are interested
439: * in watching the messages for.
440: *
441: * Returns value: TRUE
442: \***********************************************************************/
443: SHORT EXPENTRY SpyGetQueueList( chmq, rghmq )
444: SHORT chmq;
445: HMQ *rghmq;
446: {
447: SHORT i;
448: HMQ *phmqT;
449:
450: EnterSem(-1L);
451:
452: if (chmq > chmqSpy)
453: chmq = chmqSpy;
454:
455: phmqT = pahmqSpy;
456:
457: for (i=0; i < chmq; i++) {
458: *rghmq++ = *phmqT++;
459: }
460:
461: LeaveSem();
462:
463: return(chmq);
464: }
465:
466:
467: /*************************** Public Function ***************************\
468: * BOOL EXPENTRY SpySetMessageList(UCHAR *prgNewMsgFilter,
469: * BOOL fNewDispMsgsNotInList)
470: *
471: * Effect: This routine sets the list of window that we are interested
472: * in watching the messages for.
473: *
474: * Returns value: TRUE
475: \***********************************************************************/
476: BOOL EXPENTRY SpySetMessageList(prgNewMsgFilter, fNewDispMsgsNotInList)
477: UCHAR *prgNewMsgFilter;
478: BOOL fNewDispMsgsNotInList;
479: {
480: SHORT i;
481: unsigned char *prgb;
482:
483: EnterSem(-1L);
484:
485: prgb = rgMessageFilter;
486:
487:
488: fDispMsgsNotInList = fNewDispMsgsNotInList;
489:
490: for (i=0; i < MAXMSGFILTERBYTES; i++) {
491: *prgb++ = *prgNewMsgFilter++;
492: }
493:
494: LeaveSem();
495:
496: return(TRUE);
497: }
498:
499:
500: /*************************** Public Function ***************************\
501: * BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
502: *
503: * Effect: This function checks our current list of windows, and returns
504: * TRUE if the window is in the list, else returns FALSE.
505: * Returns value: TRUE if window is in list. Also if We are in the special
506: * state we will pass through all frame windows.
507: \***********************************************************************/
508: BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
509: register HWND hwnd;
510: BOOL fInWindowListOnly;
511: {
512: register int i;
513: char szClassName[10]; /* Class name of window */
514: CLASSINFO classinfo; /* Information about class */
515: HMQ hmqWindow; /* HMQ of window */
516: HMQ *phmqT; /* Temporary pointer in hmq list */
517: HWND *phwndT; /* Temporary pointer to HWND list */
518: PPIB ppib;
519: PTIB ptib;
520: MQINFO mqinfo; /* Queue info */
521:
522:
523:
524: phwndT = pahwndSpy;
525: for (i=0; i < chwndSpy; i++) {
526: if (hwnd == *phwndT++)
527: return (TRUE);
528: }
529:
530: /* See if we are restricting to only windows in list */
531: if (fInWindowListOnly)
532: return (FALSE);
533:
534: if (fProcessAllWindows)
535: return (TRUE); /* All windows pass through */
536:
537: /*
538: * See if we are watching any message queues
539: */
540: if (phmqT = pahmqSpy) {
541: if (hwnd != NULL) {
542: /*
543: * Sent to specific window First see if the user has specified
544: * that the want all messages that are sent to this message
545: * queue
546: */
547: hmqWindow = (HMQ)WinQueryWindowULong(hwnd, QWL_HMQ);
548: for (i=0; i < chmqSpy; i++) {
549: if (*phmqT++ == hmqWindow)
550: return (TRUE);
551: }
552: } else {
553: // For NULL window handle, see if the current process has HMQ
554: /*
555: * Null Window handle, so instead we need to go through the
556: * list of queues we are watching and see if their PID and TID
557: * matches our current thread.
558: */
559: DosGetThreadInfo(&ptib, &ppib);
560: for (i=0; i < chmqSpy; i++) {
561: if (WinQueryQueueInfo(*phmqT, &mqinfo, sizeof(mqinfo))) {
562: if ((mqinfo.pid == ppib->pib_ulpid) &&
563: (mqinfo.tid == ptib->tib_ultid))
564: return (TRUE); // Yes we want this queue!
565:
566: }
567: phmqT++;
568: }
569: }
570: }
571:
572: if (fProcessAllFrames) {
573: /* See if frame class */
574: if (hwnd == NULL)
575: return (TRUE); /* pass queue messages through */
576: WinQueryClassName(hwnd, sizeof(szClassName),
577: (PSZ)szClassName);
578: WinQueryClassInfo((HAB)NULL, (PSZ)szClassName,
579: &classinfo);
580: if (classinfo.flClassStyle & CS_FRAME)
581: return (TRUE);
582: }
583:
584: return (FALSE);
585: }
586:
587:
588: /*************************** Public Function ***************************\
589: * BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
590: *
591: * Effect: This routine releases the input hook, if it is installed.
592: *
593: * Returns value: TRUE if hook is released, FALSE otherwise.
594: \***********************************************************************/
595: BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
596: BOOL fZeroQueue;
597: {
598: BOOL fRet;
599:
600: EnterSem(-1L);
601:
602: if ( habOwner ) {
603: if (SpybHooks & SPYH_INPUT)
604: fRet = WinReleaseHook( habOwner, (HMQ)0, HK_INPUT,
605: (PFN)SpyInputHook, hmodSpy );
606:
607: if (SpybHooks & SPYH_SENDMSG)
608: fRet = WinReleaseHook( habOwner, (HMQ)0, HK_SENDMSG,
609: (PFN)SpySendMsgHook, hmodSpy );
610: if ( fRet ) {
611: habOwner = (HAB)0;
612: hmqOwner = (HMQ)0;
613: }
614: }
615:
616: /*
617: * When the hook is freed, we want to clear message count out,
618: * make sure any process waiting will abort
619: * Only do this if the Zeroqueu flag was passed
620: */
621: if (fZeroQueue) {
622: cmsgSpy = 0;
623: imsgWrite = 0;
624: imsgRead = 0;
625: if (pahwndSpy != NULL)
626: FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
627: pahwndSpy = NULL;
628: chwndSpy = 0; /* Max windows to spy */
629: fRecording = FALSE; /* Set recording to off */
630: if (pahmqSpy != NULL)
631: FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
632:
633: pahmqSpy = NULL;
634: chmqSpy = 0;
635: fAnythingToWatch = FALSE;
636: SignalEvent(); /* Free any process */
637: }
638: LeaveSem();
639:
640: return fRet;
641: }
642:
643:
644: /*************************** Public Function ***************************\
645: * BOOL EXPENTRY SpyHookOnOrOff( fOn)
646: *
647: * Effect: This routine allows the application to turn the hook
648: * processing on or off.
649: *
650: * Returns value:
651: \***********************************************************************/
652: BOOL EXPENTRY SpyHookOnOrOff(fOn)
653: BOOL fOn;
654: {
655: EnterSem(-1L);
656:
657: fRecording = fOn;
658:
659: LeaveSem();
660: return (TRUE);
661: }
662:
663:
664:
665: /*************************** Public Function ***************************\
666: * BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
667: *
668: * Effect: Special state if TRUE will cause the window filter to pass
669: * all frame windows through. This is usefull when debuging
670: * interactions between frame windows, when the windows are
671: * net yet created.
672: *
673: * Returns value:
674: \***********************************************************************/
675: BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
676: BOOL fAllFrames;
677: {
678: fProcessAllFrames = fAllFrames;
679: fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
680: fProcessAllWindows || fProcessAllFrames;
681: return (TRUE);
682: }
683:
684: /*************************** Public Function ***************************\
685: * BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
686: *
687: * Effect: Special state if TRUE will cause the window filter to pass
688: * all windows through. This is usefull when debuging
689: * interactions between all of the windows
690: *
691: * Returns value:
692: \***********************************************************************/
693: BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
694: BOOL fAllWindows;
695: {
696: fProcessAllWindows = fAllWindows;
697: fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
698: fProcessAllWindows || fProcessAllFrames;
699: return (TRUE);
700: }
701:
702:
703: /*************************** Public Function ***************************\
704: * BOOL EXPENTRY SpySetPIDIntercept(PID pid, USHORT usPIT, ULONG ulInfo);
705: *
706: *
707: * Effect: Hack to tell the hook to be on the look out for a specific
708: * PID. If it finds it is running in the context of the specified
709: * process, it will get the selector information for the specified
710: * selector.
711: *
712: * Returns value:
713: \***********************************************************************/
714: BOOL EXPENTRY SpySetPIDIntercept(pid, usPIT, ulInfo)
715: PID pid;
716: USHORT usPIT;
717: ULONG ulInfo;
718: {
719: if (pit.pid == 0xffff) {
720: pit.pid = pid;
721: pit.usPIT = usPIT;
722: pit.ulInfo = ulInfo;
723: return (TRUE);
724: } else
725: return (FALSE);
726: }
727:
728:
729:
730: /***************************** Exported Function ***********************\
731: * VOID SpyCheckPIDForIntercept(VOID)
732: *
733: * Effect: Only called when we are looking for a symbol
734: *
735: \***********************************************************************/
736: VOID SpyCheckPIDForIntercept()
737: {
738: PPIB ppib;
739: PTIB ptib;
740:
741: /*
742: * Get the spy semaphore to serialize access and see if we are the
743: * correct PID;
744: */
745: DosGetThreadInfo(&ptib, &ppib);
746: if (!EnterSem(100L))
747: return;
748:
749: if (ppib->pib_ulpid == pit.pid) {
750: /*
751: * We are the correct process, so continue to try go get the
752: * symbol information.
753: */
754: pit.pid = 0xffff; /* reset to not enter again */
755:
756: switch (pit.usPIT) {
757: break;
758: case PIT_ACCEL:
759: // Allocate memory for the Accel table.
760: pit.cbData = WinCopyAccelTable((HACCEL)pit.ulInfo,
761: (PACCELTABLE)NULL, 0);
762: pit.pvoidData = AllocMem(pit.cbData);
763: if (pit.pvoidData == NULL) {
764: pit.cbData = 0;
765: break;
766: }
767: WinCopyAccelTable((HACCEL)pit.ulInfo,
768: (PACCELTABLE)pit.pvoidData, pit.cbData);
769: break;
770: }
771: }
772:
773: LeaveSem();
774: }
775:
776:
777:
778: /*************************** Public Function ***************************\
779: * int EXPENTRY SpyGetLNSymbolSelector(pwhoinfo)
780: *
781: * Effect: Hack to get the information about the specified selector.
782: * If the specified process has not been executed since the
783: * function SpySetPIDIntercept has been called, it will return -1,
784: * else it will return what was returned from IdentifyCodeSelector.
785: *
786: * Returns value:
787: \***********************************************************************/
788: USHORT EXPENTRY SpyGetPIDInterceptData(pvoidBuffer, cbBuffer, pmresult)
789: PVOID pvoidBuffer;
790: USHORT cbBuffer;
791: PMRESULT pmresult;
792: {
793: if (pvoidBuffer != NULL) {
794: if (pit.pvoidData != NULL) {
795: if (cbBuffer > pit.cbData)
796: cbBuffer = pit.cbData;
797: CopyStruct(pit.pvoidData, pvoidBuffer, cbBuffer);
798: FreeMem(pit.pvoidData, pit.cbData);
799: pit.pvoidData = NULL;
800: }
801: }
802:
803: if (pmresult != NULL)
804: *pmresult = pit.mresult;
805:
806: return (pit.cbData);
807: }
808:
809:
810:
811:
812: /*************************** Public Function **************************\
813: * VOID GrabMsgDataWords (SHORT imsg, UCHAR bMPType)
814: *
815: * Effect:
816: * Get the next message from the list - if timeout != 0 an message
817: * processing threads, you may have problems, - If lpqmsg==NULL, this
818: * function acts like a query or wait function.
819: *
820: * Returns value:
821: \***********************************************************************/
822: VOID GrabMsgDataWords(imsg, bMPType)
823: SHORT imsg;
824: UCHAR bMPType;
825: {
826: UCHAR bMP1Type;
827: UCHAR bMP2Type;
828: SHORT cbMPs;
829: SHORT cbMP1;
830: SHORT cbMP2;
831: UCHAR *rgBuf;
832:
833: /*
834: * This function will use the MPType data to know if MP1 and/or MP2
835: * are pointers to any known data, that we want to extract off
836: * and save for spy to display later
837: */
838: rgqmsgSpy[imsg].bMPType = bMPType;
839: bMP1Type = bMPType & MP_MASK;
840: cbMPs = cbMP1 = rgqmsgSpy[imsg].cbDataMP1 = acbMPTypes[bMP1Type];
841:
842: bMP2Type = (bMPType >> 3) & MP_MASK;
843: cbMPs += (cbMP2 = rgqmsgSpy[imsg].cbDataMP2 = acbMPTypes[bMP2Type]);
844:
845: if (cbMPs > 0) {
846: /* Allocate memory to save the data into */
847: rgBuf = rgqmsgSpy[imsg].rgData = AllocMem(cbMPs);
848:
849: if (rgBuf != NULL) {
850: /* Copy the data down, Note: if count is 0 will NOP */
851: if (cbMP1) {
852: rgqmsgSpy[imsg].fMP1Valid = CopyStruct(
853: (CHAR *)rgqmsgSpy[imsg].qmsg.mp1, rgBuf, cbMP1);
854: rgBuf += cbMP1;
855: }
856:
857: if (cbMP2) {
858: rgqmsgSpy[imsg].fMP2Valid = CopyStruct(
859: (CHAR *)rgqmsgSpy[imsg].qmsg.mp2, rgBuf, cbMP2);
860: }
861: }
862:
863: } else {
864: rgqmsgSpy[imsg].rgData = NULL;
865: }
866: }
867:
868:
869:
870:
871:
872:
873: /*************************** Public Function **************************\
874: * SpyGetNextMessage (lpqmsg, lpBuf, cbBuf, lTimeOut)
875: *
876: * Effect:
877: * Get the next message from the list - if timeout != 0 an message
878: * processing threads, you may have problems, - If lpqmsg==NULL, this
879: * function acts like a query or wait function.
880: *
881: * Returns value:
882: \***********************************************************************/
883: BOOL EXPENTRY SpyGetNextMessage(lpqmsg, lpBuf, cbBuf, lTimeOut)
884: PQMSGSPY lpqmsg; /* Pointer where the user wants the message stored */
885: PSZ lpBuf; /* pointer to buffer */
886: SHORT cbBuf; /* size of buffer in bytes */
887: LONG lTimeOut; /* Timeout value */
888: {
889:
890: SHORT cbMsg; /* Count of bytes associated with message */
891: ULONG ulPostCt; /* Count of posts to semaphore before reset */
892:
893: /* Quick escape hatch */
894: if ((lTimeOut == 0) && (cmsgSpy == 0))
895: return (FALSE); /* Dont Wait */
896:
897: /*
898: * Now lets possibly wait for a message
899: */
900: if (cmsgSpy == 0) {
901: if (DosWaitEventSem(hevSpyMsg, lTimeOut) != 0)
902: return (FALSE); /* No messages after timeout */
903: if (cmsgSpy == 0)
904: return (FALSE); /* Still no messages, return condition */
905: }
906:
907: /*
908: * If the lpqmsg is NULL, the user is simply asking if there is
909: * a message and/or waiting for the message, so dont extract
910: * the message, but simply return the status.
911: */
912: if (lpqmsg != NULL) {
913: if (DosRequestMutexSem(hmtxSpyHook, lTimeOut) == 0) {
914: *lpqmsg = rgqmsgSpy[imsgRead]; /* Extract the message */
915:
916: cbMsg = rgqmsgSpy[imsgRead].cbDataMP1
917: + rgqmsgSpy[imsgRead].cbDataMP2;
918:
919: if ((cbMsg > 0) && (lpBuf != NULL)) {
920: if (cbMsg < cbBuf)
921: cbBuf = cbMsg; /* Number of bytes to copy */
922: CopyStruct(rgqmsgSpy[imsgRead].rgData, lpBuf, cbBuf);
923: }
924:
925: if (cbMsg > 0)
926: FreeMem(rgqmsgSpy[imsgRead].rgData, cbMsg);
927:
928: /* Also give the caller any additional information on message */
929:
930: imsgRead++;
931: if (imsgRead == MAXMSGCNT)
932: imsgRead = 0; /* Wrap around */
933:
934: /*
935: * Decrement count of messages, if we go to zero, set
936: * the semaphore, so that the next read will suspend until
937: * the next message
938: */
939: cmsgSpy--;
940: if (cmsgSpy == 0)
941: DosResetEventSem(hevSpyMsg, &ulPostCt);
942:
943: LeaveSem();
944: }
945: }
946:
947: return (TRUE);
948: }
949:
950:
951:
952:
953: /*************************** Private Function **************************\
954: * VOID SpyInitializeHookt(void)
955: *
956: * Effect:
957: *
958: *
959: * Returns value:
960: \***********************************************************************/
961: BOOL EXPENTRY SpyInitializeHook (VOID)
962: {
963:
964: if (fInitialized) {
965: return (TRUE);
966: }
967:
968: fInitialized = TRUE;
969:
970: /* Make an event semaphore to signal spy program with */
971: DosCreateMutexSem(NULL, &hmtxSpyHook, DC_SEM_SHARED, FALSE);
972: DosCreateEventSem(NULL, &hevSpyMsg, DC_SEM_SHARED, FALSE);
973:
974: /* Initialize our local heap */
975: DosAllocSharedMem(&pheapSpyHook, NULL, HEAPSIZE,
976: PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GETTABLE);
977: DosSubSet((PVOID)pheapSpyHook, 1, HEAPSIZE);
978:
979: /* Get the module handle. */
980: return TRUE;
981:
982: }
983:
984:
985: /*************************** Private Function **************************\
986: * VOID SpyTerminateHook( )
987: *
988: * Effect:
989: *
990: *
991: * Returns value:
992: \***********************************************************************/
993: BOOL EXPENTRY SpyTerminateHook (VOID)
994: {
995:
996:
997: if (!fInitialized) {
998: return (FALSE);
999: }
1000:
1001: fInitialized = FALSE;
1002:
1003: /* Close the semaphore off now */
1004: DosCloseMutexSem(hmtxSpyHook);
1005: DosCloseEventSem(hevSpyMsg);
1006:
1007: /* Also need to free memory */
1008:
1009:
1010: }
1011:
1012:
1013: /*************************** Private Function **************************\
1014: * UCHAR GMsgEnableAndType (USHORT msg)
1015: *
1016: * Effect:
1017: * Should the message be processed. If the message is out of range,
1018: * or bit is set in message bitmask return TRUE
1019: *
1020: * Returns value:
1021: * BOOL
1022: \***********************************************************************/
1023: UCHAR GMsgEnableAndType(msg)
1024: USHORT msg;
1025: {
1026: if (msg > MAXMSGFILTER)
1027: return ((UCHAR)(fDispMsgsNotInList? MP_ENABLED : 0));
1028:
1029: return (rgMessageFilter[msg]); /* One byte per message */
1030: }
1031:
1032:
1033: /*************************** Private Function **************************\
1034: * PBYTE AllocMem (ULONG cb)
1035: *
1036: * Effect:
1037: * Allocates memory from our local heap, and hides that we are no longer
1038: * calling WinAllocMem.
1039: *
1040: * Returns value:
1041: * PBYTE
1042: \***********************************************************************/
1043: PBYTE AllocMem(ULONG cb)
1044: {
1045: PVOID pbT;
1046: ULONG ulCb;
1047: ULONG ulFlag;
1048:
1049: if (DosQueryMem(pheapSpyHook, &ulCb, &ulFlag)) {
1050: if (DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE)) {
1051: DebugBreak;
1052: return (NULL);
1053: }
1054: }
1055:
1056: if (DosSubAlloc((PVOID)pheapSpyHook, (PPVOID)&pbT, cb))
1057: return(NULL);
1058:
1059: return(pbT);
1060: }
1061:
1062:
1063: /*************************** Private Function **************************\
1064: * UCHAR FreeMem (PBYTE pMem, ULONG cb)
1065: *
1066: * Effect:
1067: * Frees any memory previously allocated by Allocmem
1068: *
1069: * Returns value:
1070: * NULL
1071: \***********************************************************************/
1072:
1073: VOID FreeMem(PBYTE pMem, ULONG cb)
1074: {
1075: DosSubFree((PVOID)pheapSpyHook, (PVOID)pMem, cb);
1076: }
1077:
1078:
1079: /*************************** Private Function **************************\
1080: * BOOL EnterSem
1081: *
1082: * Effect:
1083: * Enters the Main spy Mutex semaphore
1084: *
1085: * Returns value:
1086: * BOOL;
1087: \***********************************************************************/
1088:
1089: BOOL EnterSem(ULONG ulWait)
1090: {
1091: ULONG rc;
1092: HMTX hmtx;
1093:
1094: if ((rc = DosRequestMutexSem(hmtxSpyHook, ulWait)) == 0)
1095: return (TRUE);
1096:
1097: if (rc != ERROR_INVALID_HANDLE)
1098: return (FALSE);
1099: #ifdef LATER
1100: * We should Close semaphore when we are done???
1101: #endif
1102:
1103: hmtx = hmtxSpyHook;
1104: if (DosOpenMutexSem(NULL, &hmtx) != 0)
1105: return (FALSE);
1106:
1107: DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE);
1108:
1109: return (DosRequestMutexSem(hmtxSpyHook, 100L) == 0);
1110:
1111: }
1112:
1113: /*************************** Private Function **************************\
1114: * BOOL LeaveSem
1115: *
1116: * Effect:
1117: * Enters the Main spy Mutex semaphore
1118: *
1119: * Returns value:
1120: * BOOL;
1121: \***********************************************************************/
1122:
1123: BOOL LeaveSem()
1124: {
1125: return (DosReleaseMutexSem(hmtxSpyHook) == 0);
1126:
1127: }
1128:
1129:
1130:
1131: /*************************** Private Function **************************\
1132: * BOOL SignalEvent
1133: *
1134: * Effect:
1135: * Signal an event to spy to let him know something is available.
1136: *
1137: * Returns value:
1138: * BOOL;
1139: \***********************************************************************/
1140:
1141: BOOL SignalEvent()
1142: {
1143: ULONG rc;
1144: HEV hev;
1145:
1146: if ((rc = DosPostEventSem(hevSpyMsg)) == 0)
1147: return (TRUE);
1148:
1149: if (rc != ERROR_INVALID_HANDLE)
1150: return (FALSE);
1151: #ifdef LATER
1152: * We should Close semaphore when we are done???
1153: #endif
1154:
1155: hev = hevSpyMsg;
1156: if (DosOpenEventSem(NULL, &hev) != 0)
1157: return (FALSE);
1158:
1159: return (DosPostEventSem(hevSpyMsg) == 0);
1160:
1161: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.