|
|
1.1 ! root 1: /****************************** Module Header ******************************\ ! 2: * Module Name: spy.c - Spy application ! 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: \***************************************************************************/ ! 18: ! 19: #define INCL_WIN ! 20: #define INCL_WINSYS ! 21: #define INCL_DOSPROCESS ! 22: #define INCL_DOSSEMAPHORES ! 23: #define INCL_DOSMODULEMGR ! 24: #define INCL_DOSRESOURCES ! 25: #define INCL_HELP ! 26: #include <os2.h> ! 27: #include <stdio.h> ! 28: #include <string.h> ! 29: #include "spy.h" ! 30: #include "spyhk32.h" ! 31: #include "help.h" ! 32: #include <time.h> ! 33: #include <stdlib.h> ! 34: ! 35: ! 36: /************* GLOBAL VARIABLES */ ! 37: ! 38: /************************** IN SPY.H *********************************** */ ! 39: HAB hab; ! 40: HMQ hmqSpy; ! 41: HWND hwndSpy; ! 42: HWND hwndSpyFrame; ! 43: HWND hwndSpyList = NULL; ! 44: HWND hwndWindowLB; ! 45: HWND hwndMessageLB; ! 46: HWND hwndHelpInstance = NULL; ! 47: HHEAP hHeap; ! 48: SHORT cxBorder; ! 49: SHORT cyBorder; ! 50: ULONG uVersion; ! 51: BOOL fV11 = TRUE; // Are we version 1.1? ! 52: ! 53: HPOINTER hptrArrow; ! 54: HPOINTER hptrSelWin; ! 55: HPOINTER hptrIcon11 = NULL; /* 1.1 Spy Icon */ ! 56: ! 57: BOOL fDebug = FALSE; ! 58: USHORT iCurItemFocus; /* Index to item that has the focus */ ! 59: BOOL fSpyActive = MIA_CHECKED; /* Any non-zero is true */ ! 60: BOOL fTrackingListBox = FALSE; /* Tracking windows active ? */ ! 61: BOOL fAllFrames = 0; /* Are we processing all frames ? */ ! 62: BOOL fAllWindows = 0; /* Are we processing all windows ? */ ! 63: ! 64: ! 65: HWND hwndWinDlgDisp = NULL; /* hwnds info in Window Dialog */ ! 66: ! 67: SHORT wDumpCount = 0; /* Count of which window is being dumped */ ! 68: SPWD *pspwd = NULL; ! 69: /*********************************************************************** */ ! 70: ! 71: /* Define memory semaphore to have second thread sleep on */ ! 72: HEV hevThread; /* Event semaphore to wait on */ ! 73: UCHAR rgMsgData[MAXMSGBYTES]; /* Max bytes to extract per message */ ! 74: ! 75: ! 76: char szSpyClass[] = "Spy"; ! 77: char szTitle[] = "32-bit spy sample"; ! 78: ! 79: /************* PROCEDURE DECLARATIONS */ ! 80: ! 81: ! 82: ! 83: void ProcHookThread(void); /* will process the hook messages */ ! 84: ! 85: void ProcessQueueMsg(QMSGSPY *); ! 86: void UpdateMsgBoxCurMsgText(HWND); ! 87: void InitializeOptions(int, char **); /* initialize Spy initial state */ ! 88: void InitializeMenus(void); ! 89: void InitializeHelp(void); ! 90: void DebugBreak(void); ! 91: ! 92: PSZ DumpParam(PSZ prgData, SHORT cb, BOOL fValidData, ! 93: UCHAR bMPType); ! 94: ! 95: /* Define some variables needed for help processing */ ! 96: ! 97: ! 98: /**************************** Public Function ******************************\ ! 99: * int cdecl main (argc, argv) ! 100: * ! 101: * Effects: Spy Main function ! 102: * ! 103: * Return value: ! 104: \***************************************************************************/ ! 105: int main(argc, argv) ! 106: int argc; ! 107: char **argv; ! 108: { ! 109: ULONG flCreateFlags; ! 110: QMSG qmsg; ! 111: RECTL rcl; ! 112: TID tid; ! 113: ! 114: ! 115: // Make sure the Spy Hook DLL is initialized ! 116: SpyInitializeHook(); ! 117: ! 118: hab = WinInitialize(0); ! 119: uVersion = WinQueryVersion(hab); ! 120: if ((LOBYTE(LOUSHORT(uVersion)) > 10) || ! 121: (HIBYTE(LOUSHORT(uVersion)) > 10)) ! 122: fV11 = FALSE; ! 123: ! 124: hmqSpy = WinCreateMsgQueue(hab, 0); ! 125: ! 126: if (!WinRegisterClass((HAB)NULL, szSpyClass, (PFNWP)SpyWndProc, ! 127: CS_SYNCPAINT, 0)) { ! 128: WinAlarm(HWND_DESKTOP, WA_ERROR); ! 129: return(0); ! 130: } ! 131: ! 132: /* ! 133: * We need to process the options, before we create a heap, or we ! 134: * will blow away our options ! 135: */ ! 136: InitializeOptions(argc, argv); /* initialize Spy initial state */ ! 137: ! 138: /* ! 139: * Create a heap for the program ! 140: */ ! 141: hHeap = WinCreateHeap(0, 0, 0, 0, 0, 0); ! 142: ! 143: hptrArrow = WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, TRUE); ! 144: cxBorder = (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CXBORDER); ! 145: cyBorder = (SHORT)WinQuerySysValue(HWND_DESKTOP, SV_CYBORDER); ! 146: ! 147: hptrSelWin = WinQuerySysPointer(HWND_DESKTOP, SPTR_MOVE, TRUE); ! 148: ! 149: SpyInstallHook(hab, hmqSpy, spyopt.bHooks); ! 150: SpySetAllWindowOpt (fAllWindows); ! 151: SpySetAllFrameOpt (fAllFrames); ! 152: ! 153: flCreateFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER ! 154: | FCF_MINMAX | FCF_SHELLPOSITION | FCF_TASKLIST | FCF_MENU ! 155: | FCF_ACCELTABLE | FCF_ICON; ! 156: ! 157: // See if we get here ! 158: hwndSpyFrame = WinCreateStdWindow(HWND_DESKTOP, ! 159: WS_VISIBLE, ! 160: (PULONG)&flCreateFlags, ! 161: (PSZ)szSpyClass, (PSZ)szTitle, ! 162: WS_VISIBLE, ! 163: (HMODULE)NULL, IDR_SPY, ! 164: (PHWND)&hwndSpy); ! 165: ! 166: WinQueryWindowRect(hwndSpy, &rcl); ! 167: hwndSpyList = WinCreateWindow (hwndSpy, WC_LISTBOX, "", ! 168: fV11 ? (WS_VISIBLE | LS_NOADJUSTPOS) : ! 169: (WS_VISIBLE | LS_NOADJUSTPOS | LS_HORZSCROLL), ! 170: -cxBorder, -cyBorder, ! 171: (SHORT)(rcl.xRight - rcl.xLeft) + 2 * cxBorder, ! 172: (SHORT)(rcl.yTop - rcl.yBottom) + 2 * cyBorder, ! 173: hwndSpy, HWND_TOP, DID_SPYLIST, NULL, NULL); ! 174: ! 175: /* ! 176: * Read the os2.ini information if it exists, and set the menu items ! 177: * to correspond to the initial state read from OS2.ini ! 178: */ ! 179: InitializeMenus(); ! 180: InitializeHelp(); ! 181: ! 182: /* ! 183: * Set the focus to the list box. Note: Only call WinSetFocus if ! 184: * our frame is the active window. As we may have been started in ! 185: * the background. If this is the case, we want to set the frames ! 186: * focus save to the listbox, such that it will be the active window ! 187: * when our frame is activated ! 188: */ ! 189: if (WinQueryWindow(HWND_DESKTOP, QW_TOP, FALSE) == hwndSpyFrame) ! 190: WinSetFocus(HWND_DESKTOP, hwndSpyList); ! 191: else ! 192: WinSetWindowULong(hwndSpyFrame, QWL_HWNDFOCUSSAVE, ! 193: (ULONG)hwndSpyList); ! 194: ! 195: ! 196: ! 197: /* Start the thread that will process the messages from the hook */ ! 198: DosCreateEventSem(NULL, &hevThread, 0L, FALSE); ! 199: DosCreateThread((PTID)&tid, ProcHookThread, 0L, 0L, 4096L); ! 200: ! 201: UpdateHooksMsgTable(); /* Set Spys Msg table */ ! 202: SpyHookOnOrOff (TRUE); /* Turn the hook on */ ! 203: ! 204: ! 205: /* ! 206: * Now process all of the messages ! 207: */ ! 208: while (WinGetMsg(NULL, (PQMSG)&qmsg, NULL, 0, 0)) { ! 209: WinDispatchMsg(NULL, (PQMSG)&qmsg); ! 210: } ! 211: ! 212: SpyReleaseHook (TRUE); /* Release input hook */ ! 213: ! 214: WinDestroyWindow(hwndSpyFrame); ! 215: SpyTerminateHook (); ! 216: ! 217: WinDestroyPointer(hptrArrow); ! 218: WinDestroyPointer(hptrSelWin); ! 219: if (hptrIcon11 != NULL) ! 220: WinDestroyPointer (hptrIcon11); ! 221: ! 222: if (hwndHelpInstance != NULL) ! 223: WinDestroyHelpInstance(hwndHelpInstance); ! 224: ! 225: ! 226: WinDestroyMsgQueue(hmqSpy); ! 227: WinTerminate(hab); ! 228: ! 229: /* If the spy output file is open, close it now */ ! 230: if (spyopt.hfileSpy != NULL) ! 231: DosClose(spyopt.hfileSpy); ! 232: ! 233: ! 234: DosExit(EXIT_PROCESS, 0); ! 235: } ! 236: ! 237: ! 238: ! 239: ! 240: /**************************** Public Function ******************************\ ! 241: * InitializeOptions(argc, argv) ! 242: * ! 243: * Effects: Initialize spy, first from the default options, second from ! 244: * OS2.INI file, and override from command switches. ! 245: * ! 246: * Return value: ! 247: \***************************************************************************/ ! 248: VOID InitializeOptions(argc, argv) ! 249: int argc; ! 250: char **argv; ! 251: { ! 252: ULONG cch; ! 253: ! 254: ! 255: /* ! 256: * If the OS2.INI information exists, initialize our options to ! 257: * the stored values ! 258: */ ! 259: if (PrfQueryProfileSize (HINI_USER, "Spy", "Options", &cch) == 0) { ! 260: cch = sizeof(SPYOPT); ! 261: ! 262: PrfQueryProfileData(HINI_USER, "Spy", "Options", (PSZ)&spyopt, ! 263: &cch); ! 264: PrfQueryProfileString(HINI_USER, "Spy", "FileName", "spy.out", ! 265: (PSZ)spystr.szFileName, sizeof(spystr.szFileName)); ! 266: PrfQueryProfileString(HINI_USER, "Spy", "SaveFileName", "spy.lis", ! 267: (PSZ)spystr.szSaveFileName, sizeof(spystr.szSaveFileName)); ! 268: } ! 269: ! 270: /* ! 271: * Then check for command line overrides ! 272: */ ! 273: while (argc > 1) { ! 274: argv++; /* get beyond the program name */ ! 275: ! 276: /* Test for debug flag */ ! 277: if (!strcmpi(*argv, "/d") ) { ! 278: fDebug = TRUE; ! 279: DebugBreak(); ! 280: } ! 281: ! 282: /* Test for send message hook flag */ ! 283: if (!strcmpi(*argv, "+s")) ! 284: spyopt.bHooks |= SPYH_SENDMSG; ! 285: if (!strcmpi(*argv, "-s")) ! 286: spyopt.bHooks &= ~SPYH_SENDMSG; ! 287: ! 288: /* Test for input hook flag */ ! 289: if (!strcmpi(*argv, "+i")) ! 290: spyopt.bHooks |= SPYH_INPUT; ! 291: if (!strcmpi(*argv, "-i")) ! 292: spyopt.bHooks &= ~SPYH_INPUT; ! 293: ! 294: argc--; ! 295: } ! 296: } ! 297: ! 298: ! 299: ! 300: /**************************** Public Function ******************************\ ! 301: * InitializeMenus() ! 302: * ! 303: * Effects: Initialize the menus from the initialized defaults. ! 304: * ! 305: * Return value: ! 306: \***************************************************************************/ ! 307: VOID InitializeMenus() ! 308: { ! 309: HWND hwndMenu; ! 310: USHORT wAction; ! 311: ! 312: /* ! 313: * Now we need to update the menu items to the final ! 314: * state ! 315: */ ! 316: hwndMenu = WinWindowFromID(hwndSpyFrame, FID_MENU); ! 317: ! 318: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_INPUTHOOK, TRUE), ! 319: MPFROM2SHORT(MIA_CHECKED, ! 320: (spyopt.bHooks & SPYH_INPUT) ? MIA_CHECKED : 0)); ! 321: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_SENDMSGHOOK, TRUE), ! 322: MPFROM2SHORT(MIA_CHECKED, ! 323: (spyopt.bHooks & SPYH_SENDMSG) ? MIA_CHECKED : 0)); ! 324: ! 325: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_SENDEXTEND, TRUE), ! 326: MPFROM2SHORT(MIA_CHECKED, ! 327: spyopt.fSendExtend ? MIA_CHECKED : 0)); ! 328: ! 329: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTSCREEN, TRUE), ! 330: MPFROM2SHORT(MIA_CHECKED, spyopt.fWindow ? MIA_CHECKED : 0)); ! 331: ! 332: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTTERM, TRUE), ! 333: MPFROM2SHORT(MIA_CHECKED, spyopt.fDebugOutput ? MIA_CHECKED : 0)); ! 334: ! 335: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTFILE, TRUE), ! 336: MPFROM2SHORT(MIA_CHECKED, spyopt.fFile ? MIA_CHECKED : 0)); ! 337: ! 338: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(CMD_ALPHASORT, TRUE), ! 339: MPFROM2SHORT(MIA_CHECKED, ! 340: spyopt.fAlphaSortMsgList ? MIA_CHECKED : 0)); ! 341: ! 342: /* ! 343: * If the options specify output to file, open the file now ! 344: */ ! 345: if (spyopt.fFile) { ! 346: if (DosOpen((PSZ)spystr.szFileName, &spyopt.hfileSpy, ! 347: (ULONG *)&wAction, 0L, 0, ! 348: 0x0012, 0x00C1, 0L) != 0) ! 349: spyopt.hfileSpy = NULL; /* Failed on open */ ! 350: } ! 351: } ! 352: ! 353: ! 354: ! 355: /**************************** Public Function ******************************\ ! 356: * InitializeHelp ! 357: * ! 358: * Effects: Initialize the help subsubsystem. ! 359: * ! 360: * ! 361: * Return value: ! 362: \***************************************************************************/ ! 363: VOID InitializeHelp() ! 364: { ! 365: ! 366: /* ! 367: * Now initialize Help - First we need to verify that the the help ! 368: * DLL is avaialable, if not, we will not do help processing. ! 369: */ ! 370: HELPINIT hi; ! 371: char szTitle[256]; /* Assume the title is not more than 256 chars */ ! 372: HWND hwndMenu; ! 373: SHORT sMenuIndex; ! 374: ! 375: /* Now try to create the help instance */ ! 376: hi.hmodHelpTableModule = ! 377: hi.hmodAccelActionBarModule = (HMODULE)NULL; ! 378: hi.pszTutorialName = (PSZ)NULL; ! 379: hi.pszHelpLibraryName = "spy32.hlp"; ! 380: hi.idAccelTable = ! 381: hi.idActionBar = 0; ! 382: hi.cb = sizeof(HELPINIT); ! 383: hi.usShowPanelId = CMIC_HIDE_PANEL_ID; ! 384: hi.phtHelpTable = (PHELPTABLE)MAKEULONG(IDR_SPY, 0xffff); ! 385: ! 386: WinQueryWindowText(hwndSpyFrame, sizeof(szTitle), szTitle); ! 387: hi.pszHelpWindowTitle = szTitle; ! 388: ! 389: hwndHelpInstance = WinCreateHelpInstance(hab, &hi); ! 390: if (hwndHelpInstance != NULL) { ! 391: if(!WinAssociateHelpInstance(hwndHelpInstance, hwndSpyFrame) ) { ! 392: WinDestroyHelpInstance(hwndHelpInstance); ! 393: hwndHelpInstance = (HWND)NULL; ! 394: } ! 395: } ! 396: ! 397: if (hwndHelpInstance == NULL) { ! 398: /* Help was not initialized, so gray out help items */ ! 399: hwndMenu = WinWindowFromID(hwndSpyFrame, FID_MENU); ! 400: for (sMenuIndex = CMD_HOWHELP; sMenuIndex <= CMD_HELPINDEX; ! 401: sMenuIndex++) { ! 402: WinSendMsg(hwndMenu, MM_SETITEMATTR, ! 403: MPFROM2SHORT(sMenuIndex, TRUE), ! 404: MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)); ! 405: } ! 406: } ! 407: } ! 408: ! 409: ! 410: ! 411: /**************************** Public Function ******************************\ ! 412: * MRESULT EXPENTRY SpyWndProc(hwnd, msg, mp1, mp2) ! 413: * ! 414: * Effects: Spy Client window procedure ! 415: * ! 416: * ! 417: * Return value: ! 418: \***************************************************************************/ ! 419: MRESULT EXPENTRY SpyWndProc(hwnd, msg, mp1, mp2) ! 420: HWND hwnd; ! 421: USHORT msg; ! 422: MPARAM mp1; ! 423: MPARAM mp2; ! 424: { ! 425: QMSGSPY qmsgspy; ! 426: VOID SpyPaint(); ! 427: SHORT cBytes; ! 428: ULONG ulAction; ! 429: ! 430: switch (msg) { ! 431: case WM_CREATE: ! 432: /* Set up this global first thing in case we need it elsewhere */ ! 433: hwndSpy = hwnd; ! 434: break; ! 435: ! 436: case WM_SEM2: ! 437: /* ! 438: * Other thread told use there are some messages out there. Loop ! 439: * through and process all of the pending messages, and output ! 440: * the listbox position at the end. Also make sure to flush ! 441: * the file buffer before we go back to sleep. ! 442: */ ! 443: while (SpyGetNextMessage(&qmsgspy, rgMsgData, sizeof(rgMsgData), 0L)) { ! 444: ProcessQueueMsg(&qmsgspy); ! 445: } ! 446: ! 447: if (spyopt.fFile) ! 448: DosBufReset(spyopt.hfileSpy); ! 449: ! 450: DosPostEventSem(hevThread); ! 451: ! 452: break; ! 453: ! 454: case WM_COMMAND: ! 455: switch (SHORT1FROMMP(mp1)) { ! 456: case CMD_ACTIVE: ! 457: ! 458: /* ! 459: * THe active menu item was selected, we will toggle the ! 460: * the selection by setting active to 0 or MIA_CHECKED. ! 461: * Call the hook, and then update the checkmark on the menu ! 462: */ ! 463: fSpyActive ^= MIA_CHECKED; /* Toggle on or off */ ! 464: SpyHookOnOrOff (fSpyActive); ! 465: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 466: MM_SETITEMATTR, MPFROM2SHORT(CMD_ACTIVE, TRUE), ! 467: MPFROM2SHORT(MIA_CHECKED, fSpyActive)); ! 468: ! 469: break; ! 470: case CMD_ABOUT: ! 471: WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)AboutWndProc, NULL, ! 472: IDD_About1Dlg, (PCH)NULL); ! 473: break; ! 474: ! 475: case CMD_EXIT: ! 476: WinPostMsg(NULL, WM_QUIT, 0L, 0L); ! 477: break; ! 478: ! 479: case CMD_CLRWIN: ! 480: /* ! 481: * Delete all items in the list. Simply do this ! 482: * By deleting the first item, until the count goes to ! 483: * zero ! 484: */ ! 485: WinSendMsg(hwndSpyList, LM_DELETEALL, 0L, 0L); ! 486: break; ! 487: ! 488: case CMD_SAVEWIN: ! 489: SpyHookOnOrOff (FALSE); ! 490: WinDlgBox(HWND_DESKTOP, hwndSpyFrame, ! 491: (PFNWP)SpySaveListDlgProc, (HMODULE)NULL, ! 492: IDD_SaveListDlg, (PCH)NULL); ! 493: SpyHookOnOrOff (fSpyActive); ! 494: break; ! 495: ! 496: /* ! 497: * This command saves out the current options to OS2.ini ! 498: */ ! 499: case CMD_SAVEOPT: ! 500: PrfWriteProfileData(HINI_USER, "Spy", "Options", (PSZ)&spyopt, ! 501: sizeof(SPYOPT)); ! 502: PrfWriteProfileString(HINI_USER, "Spy", "FileName", ! 503: (PSZ)spystr.szFileName); ! 504: PrfWriteProfileString(HINI_USER, "Spy", "SaveFileName", ! 505: (PSZ)spystr.szSaveFileName); ! 506: ! 507: break; ! 508: ! 509: case CMD_WINDOWS: ! 510: SpyHookOnOrOff (FALSE); ! 511: hwndWindowLB = NULL; ! 512: iCurItemFocus = (USHORT)-1; ! 513: WinDlgBox(HWND_DESKTOP, hwndSpyFrame, ! 514: (PFNWP)SpyWindowsDlgProc, (HMODULE)NULL, ! 515: IDD_WindowsDlg, (PCH)NULL); ! 516: ! 517: SpyHookOnOrOff (fSpyActive); ! 518: break; ! 519: ! 520: case CMD_QUEUES: ! 521: SpyHookOnOrOff (FALSE); ! 522: hwndWindowLB = NULL; ! 523: iCurItemFocus = (USHORT)-1; ! 524: WinDlgBox(HWND_DESKTOP, hwndSpyFrame, ! 525: (PFNWP)SpyQueuesDlgProc, (HMODULE)NULL, ! 526: IDD_MsgQueueDlg, (PCH)NULL); ! 527: ! 528: SpyHookOnOrOff (fSpyActive); ! 529: break; ! 530: ! 531: case CMD_WNMSSEL: ! 532: case CMD_WNMSDSL: ! 533: SpyHookOnOrOff (FALSE); ! 534: SelOrDeselWithMouse(SHORT1FROMMP(mp1) == CMD_WNMSSEL); ! 535: SpyHookOnOrOff (fSpyActive); ! 536: break; ! 537: ! 538: case CMD_ALLWNDWS: ! 539: ! 540: /* ! 541: * The user selected the ALLFRAMES, toggle the state, and ! 542: * update the menu and the hook state. ! 543: */ ! 544: fAllWindows ^= MIA_CHECKED; /* Toggle on or off */ ! 545: SpySetAllWindowOpt (fAllWindows); ! 546: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 547: MM_SETITEMATTR, MPFROM2SHORT(CMD_ALLWNDWS, TRUE), ! 548: MPFROM2SHORT(MIA_CHECKED, fAllWindows)); ! 549: break; ! 550: ! 551: case CMD_ALLFRAMES: ! 552: ! 553: /* ! 554: * The user selected the ALLFRAMES, toggle the state, and ! 555: * update the menu and the hook state. ! 556: */ ! 557: fAllFrames ^= MIA_CHECKED; /* Toggle on or off */ ! 558: SpySetAllFrameOpt (fAllFrames); ! 559: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 560: MM_SETITEMATTR, MPFROM2SHORT(CMD_ALLFRAMES, TRUE), ! 561: MPFROM2SHORT(MIA_CHECKED, fAllFrames)); ! 562: break; ! 563: ! 564: case CMD_WNDPWIN: ! 565: wDumpCount = 0; ! 566: DumpOneWindowInfo(); ! 567: break; ! 568: case CMD_WNDPALL: ! 569: wDumpCount = 0; ! 570: pspwd = (SPWD *)WinAllocMem(hHeap, sizeof(SPWD)* MAXSPYDUMP); ! 571: cBytes = DumpAllWindowsInfo(HWND_DESKTOP, 0); ! 572: cBytes += DumpAllWindowsInfo(HWND_OBJECT, -10); ! 573: DumpWindowIndex(cBytes); ! 574: WinFreeMem(hHeap, (char *)pspwd, sizeof(SPWD)* MAXSPYDUMP); ! 575: break; ! 576: case CMD_DACCEL: ! 577: DumpFrameAcclTable(); ! 578: break; ! 579: ! 580: case CMD_MESSAGES: ! 581: SpyHookOnOrOff (FALSE); ! 582: WinDlgBox(HWND_DESKTOP, hwndSpyFrame, ! 583: (PFNWP)SpyMsgDlgProc, (HMODULE)NULL, ! 584: IDD_MessagesDlg, (PCH)NULL); ! 585: SpyHookOnOrOff (fSpyActive); ! 586: break; ! 587: ! 588: case CMD_ALPHASORT: ! 589: spyopt.fAlphaSortMsgList ^= TRUE; ! 590: ! 591: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 592: MM_SETITEMATTR, MPFROM2SHORT(CMD_ALPHASORT, TRUE), ! 593: MPFROM2SHORT(MIA_CHECKED, ! 594: spyopt.fAlphaSortMsgList ? MIA_CHECKED : 0)); ! 595: break; ! 596: ! 597: case CMD_SENDMSG: ! 598: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 599: MM_SETITEMATTR, MPFROM2SHORT(CMD_SENDMSG, TRUE), ! 600: MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)); ! 601: WinLoadDlg(HWND_DESKTOP, hwndSpyFrame, ! 602: (PFNWP)SendMsgDlgProc, (HMODULE)NULL, ! 603: IDD_SendMsgDlg, (PCH)NULL); ! 604: break; ! 605: ! 606: /* ! 607: * The command in this section are defined in the Hooks Menu. ! 608: * All of these items toggle selections on or off. The first two ! 609: * Items must be registered with the input hook. The last two simply ! 610: * retrict how much information is displayed for send messages ! 611: */ ! 612: ! 613: case CMD_INPUTHOOK: ! 614: spyopt.bHooks ^= SPYH_INPUT; ! 615: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 616: MM_SETITEMATTR, MPFROM2SHORT(CMD_INPUTHOOK, TRUE), ! 617: MPFROM2SHORT(MIA_CHECKED, ! 618: (spyopt.bHooks & SPYH_INPUT) ? MIA_CHECKED : 0)); ! 619: SpyReleaseHook (FALSE); /* Dont clear queue */ ! 620: SpyInstallHook(hab, hmqSpy, spyopt.bHooks); ! 621: break; ! 622: ! 623: case CMD_SENDMSGHOOK: ! 624: spyopt.bHooks ^= SPYH_SENDMSG; ! 625: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 626: MM_SETITEMATTR, MPFROM2SHORT(CMD_SENDMSGHOOK, TRUE), ! 627: MPFROM2SHORT(MIA_CHECKED, ! 628: (spyopt.bHooks & SPYH_SENDMSG) ? MIA_CHECKED : 0)); ! 629: SpyReleaseHook (FALSE); /* Dont clear queue */ ! 630: SpyInstallHook(hab, hmqSpy, spyopt.bHooks); ! 631: break; ! 632: ! 633: case CMD_SENDEXTEND: ! 634: spyopt.fSendExtend ^= 1; /* Toggle on or off */ ! 635: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 636: MM_SETITEMATTR, MPFROM2SHORT(CMD_SENDEXTEND, TRUE), ! 637: MPFROM2SHORT(MIA_CHECKED, ! 638: spyopt.fSendExtend ? MIA_CHECKED : 0)); ! 639: break; ! 640: ! 641: /* ! 642: * The commands in this section are defined in the Outputs Menu. ! 643: * The first 3 items simply toggle outputs on or off, where the ! 644: * last item allows the user to change all of the output options. ! 645: */ ! 646: case CMD_OUTSCREEN: ! 647: spyopt.fWindow ^= 1; /* Toggle on or off */ ! 648: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 649: MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTSCREEN, TRUE), ! 650: MPFROM2SHORT(MIA_CHECKED, spyopt.fWindow ? MIA_CHECKED : 0)); ! 651: break; ! 652: ! 653: case CMD_OUTTERM: ! 654: spyopt.fDebugOutput ^= 1; /* Toggle on or off */ ! 655: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 656: MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTTERM, TRUE), ! 657: MPFROM2SHORT(MIA_CHECKED, spyopt.fDebugOutput ? MIA_CHECKED : 0)); ! 658: break; ! 659: ! 660: case CMD_OUTFILE: ! 661: spyopt.fFile ^= 1; /* Toggle on or off */ ! 662: WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU), ! 663: MM_SETITEMATTR, MPFROM2SHORT(CMD_OUTFILE, TRUE), ! 664: MPFROM2SHORT(MIA_CHECKED, spyopt.fFile ? MIA_CHECKED : 0)); ! 665: /* ! 666: * Open or close the output file ! 667: */ ! 668: if (spyopt.fFile) { ! 669: if (spyopt.hfileSpy == NULL) ! 670: if (DosOpen((PSZ)spystr.szFileName, &spyopt.hfileSpy, ! 671: &ulAction, 0L, 0, ! 672: 0x0012, 0x00C1, 0L) != 0) ! 673: spyopt.hfileSpy = NULL; /* Failed on open */ ! 674: } else { ! 675: if (spyopt.hfileSpy != NULL) { ! 676: /* file open, not outputing, close it now */ ! 677: DosClose (spyopt.hfileSpy); ! 678: spyopt.hfileSpy = NULL; ! 679: } ! 680: } ! 681: break; ! 682: ! 683: case CMD_OUTPUTS: ! 684: SpyHookOnOrOff (FALSE); ! 685: WinDlgBox(HWND_DESKTOP, hwndSpyFrame, ! 686: (PFNWP)SpyOutputsDlgProc, (HMODULE)NULL, ! 687: IDD_OutputsDlg, (PCH)NULL); ! 688: SpyHookOnOrOff (fSpyActive); ! 689: break; ! 690: ! 691: case CMD_MGDABLE: ! 692: case CMD_MGEABLE: ! 693: EnableOrDisableMsg(SHORT1FROMMP(mp1) == CMD_MGEABLE); ! 694: break; ! 695: /* ! 696: * Help Menu items, send message to help manager ! 697: */ ! 698: case CMD_HOWHELP: ! 699: if (hwndHelpInstance != NULL) ! 700: WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP, ! 701: (MPARAM)NULL, (MPARAM)NULL); ! 702: break; ! 703: ! 704: /* Extended help option was chosen from pull-down */ ! 705: case CMD_HELPEXTENDED: ! 706: if (hwndHelpInstance != NULL) ! 707: WinSendMsg(hwndHelpInstance, HM_EXT_HELP, ! 708: (MPARAM) 0, (MPARAM) 0 ); ! 709: break; ! 710: ! 711: /* Keys help option was chosen from pull-down */ ! 712: ! 713: case CMD_HELPKEYS: ! 714: if (hwndHelpInstance != NULL) ! 715: WinSendMsg(hwndHelpInstance, HM_KEYS_HELP, ! 716: (MPARAM) 0, (MPARAM) 0 ); ! 717: break; ! 718: ! 719: /* Index option was chosen from pull-down */ ! 720: ! 721: case CMD_HELPINDEX: ! 722: if (hwndHelpInstance != NULL) ! 723: WinSendMsg(hwndHelpInstance, HM_HELP_INDEX, ! 724: (MPARAM) 0, (MPARAM) 0 ); ! 725: break; ! 726: } ! 727: ! 728: break; ! 729: case HM_HELPSUBITEM_NOT_FOUND: ! 730: if (hwndHelpInstance != NULL) ! 731: (void)WinSendMsg(hwndHelpInstance, HM_EXT_HELP, ! 732: (MPARAM)NULL, (MPARAM)NULL); ! 733: break; ! 734: case HM_QUERY_KEYS_HELP: ! 735: return (MRESULT)HLP_KEYS; ! 736: ! 737: case WM_SIZE: ! 738: /* We need to resize the listbox, if it exists */ ! 739: if (hwndSpyList != NULL) { ! 740: WinSetWindowPos(hwndSpyList, HWND_TOP, -cxBorder, -cyBorder, ! 741: SHORT1FROMMP(mp2) + 2 * cxBorder, ! 742: SHORT2FROMMP(mp2) + 2 * cyBorder, SWP_MOVE | SWP_SIZE); ! 743: } ! 744: ! 745: /* Now fall through to process the message */ ! 746: default: ! 747: return(WinDefWindowProc(hwnd, msg, mp1, mp2)); ! 748: break; ! 749: } ! 750: return(0L); ! 751: } ! 752: ! 753: ! 754: ! 755: ! 756: /***************************** Private Function ****************************\ ! 757: * USHORT UConvertStringToNum(psz) ! 758: * ! 759: * Effects: ! 760: * Converts the passed string to a number 0xffff if not number ! 761: * ! 762: * History: ! 763: * 27-September-1988 KurtE ! 764: \***************************************************************************/ ! 765: USHORT UConvertStringToNum(psz) ! 766: register char *psz; ! 767: { ! 768: register USHORT uNum; ! 769: /* ! 770: * This aint to fancy yet, but if the first few chars are ! 771: * 0x, we assume the user typed in a HEX number, else if 0-9, ! 772: * we assume decimal, else we use the string, also for windows if the ! 773: * user left the 0000:0000 we ignore the high end and assume it is ! 774: * hex. ! 775: */ ! 776: ! 777: /* First see if digit in first position */ ! 778: if ((*psz >= '0') && (*psz <= '9')) { ! 779: /* Assume numbers now */ ! 780: if ((*psz == '0') && (*(psz+1) == 'x')) { ! 781: ! 782: /* We are in hex mode */ ! 783: psz += 2; ! 784: uNum = 0; ! 785: for (;;) { ! 786: if ((*psz >= '0') && (*psz <= '9')) ! 787: uNum = uNum * 16 + (USHORT)(*psz - '0'); ! 788: else if ((*psz >= 'a') && (*psz <= 'f')) ! 789: uNum = uNum * 16 + (USHORT)(*psz - 'a'); ! 790: else if ((*psz >= 'F') && (*psz <= 'F')) ! 791: uNum = uNum * 16 + (USHORT)(*psz - 'A'); ! 792: else ! 793: break; ! 794: psz++; ! 795: } ! 796: ! 797: } else { ! 798: /* Decimal mode */ ! 799: uNum = (USHORT)(*psz++ - '0'); ! 800: while ((*psz >= '0') && (*psz <= '9')) { ! 801: uNum = uNum * 10 + (USHORT)(*psz++ - '0'); ! 802: } ! 803: } ! 804: ! 805: return (uNum); ! 806: ! 807: } else if (psz=strchr(psz,':')) { ! 808: // boy this is sh.t, it should be combined above!!! ! 809: /* We are in hex mode */ ! 810: psz++; ! 811: uNum = 0; ! 812: for (;;) { ! 813: if ((*psz >= '0') && (*psz <= '9')) ! 814: uNum = uNum * 16 + (USHORT)(*psz - '0'); ! 815: else if ((*psz >= 'a') && (*psz <= 'f')) ! 816: uNum = uNum * 16 + (USHORT)(*psz - 'a'); ! 817: else if ((*psz >= 'F') && (*psz <= 'F')) ! 818: uNum = uNum * 16 + (USHORT)(*psz - 'A'); ! 819: else ! 820: break; ! 821: psz++; ! 822: } ! 823: ! 824: } else ! 825: /* Not num, return 0xffff */ ! 826: return (0xffff); ! 827: } ! 828: ! 829: ! 830: ! 831: ! 832: ! 833: /**************************** Public Function ******************************\ ! 834: * void ProcHookThread() ! 835: * ! 836: * Effects: This function will wait for the hook to have messages, when it ! 837: * does, it will Set a memory semaphore, Post a WM_SEM1 message to the other ! 838: * thread, and wait for the other thread has processed all of the messages. ! 839: * ! 840: * Return value: none ! 841: \***************************************************************************/ ! 842: ! 843: void ProcHookThread() ! 844: { ! 845: ULONG ulPostCt; ! 846: /* We'll look for a variation to run while the thread is active. */ ! 847: if (fDebug) ! 848: DebugBreak(); ! 849: ! 850: while (TRUE) { ! 851: /* ! 852: * Wait for a message to become available. ! 853: */ ! 854: if (!SpyGetNextMessage(NULL, NULL, 0, -1L)) ! 855: break; ! 856: ! 857: /* ! 858: * Now we have a message, set our semaphore, Post a WM_SEM2 ! 859: * message to the Client window, and wait for the client to ! 860: * clear the semaphore. ! 861: */ ! 862: DosResetEventSem(hevThread, &ulPostCt); ! 863: WinPostMsg(hwndSpy, WM_SEM2, (MPARAM)1, (MPARAM)1); ! 864: DosWaitEventSem(hevThread, -1L); ! 865: } ! 866: ! 867: DosExit(EXIT_THREAD, 0); ! 868: } ! 869: ! 870: ! 871: ! 872: ! 873: /**************************** Public Function ******************************\ ! 874: * void ProcessQueueMsg(pqmsg) ! 875: * ! 876: * Effects: This function will process the hook, by calling the hooks ! 877: * get message. We will than post the message to the current output ! 878: * destinations. ! 879: * ! 880: * Return value: none ! 881: \***************************************************************************/ ! 882: ! 883: void ProcessQueueMsg(pqmsgspy) ! 884: QMSGSPY *pqmsgspy; ! 885: { ! 886: MSGI *pmsgi; ! 887: CHAR cSource; ! 888: CHAR cThread; ! 889: char szNextMessage[100]; ! 890: char szTime[12]; ! 891: SHORT cch; ! 892: CHAR bAscii; ! 893: PSZ prgData; ! 894: ! 895: ! 896: ! 897: /* ! 898: * Now lets Build the message to output ! 899: */ ! 900: if (WinIsWindow(hab, pqmsgspy->qmsg.hwnd)) { ! 901: if (WinIsChild(pqmsgspy->qmsg.hwnd, hwndSpy)) ! 902: return; /* dont want endless loops */ ! 903: } ! 904: ! 905: cThread = ':'; ! 906: if (pqmsgspy->qmsg.time == (ULONG)-1) { ! 907: /* Sent message */ ! 908: szTime[0] = '\0'; ! 909: cSource = 'S'; ! 910: if (pqmsgspy->fs) ! 911: cThread = '*'; ! 912: } else { ! 913: cSource = 'I'; ! 914: if (pqmsgspy->fs != PM_REMOVE) ! 915: cThread = '-'; /* Show different for non-remove */ ! 916: ! 917: sprintf (szTime, "%-08lx", pqmsgspy->qmsg.time); ! 918: } ! 919: ! 920: if ((pmsgi = PmsgiFromMsg(pqmsgspy->qmsg.msg)) == NULL) { ! 921: /* ! 922: * Message not in list, use default ! 923: */ ! 924: cch = sprintf(szNextMessage, ! 925: "%c%cMSG:0x%04x H:%p 1:%08lx 2:%08lx T:%s", ! 926: cSource, cThread, (SHORT)pqmsgspy->qmsg.msg, pqmsgspy->qmsg.hwnd, ! 927: pqmsgspy->qmsg.mp1, pqmsgspy->qmsg.mp2, szTime); ! 928: } else if (pmsgi->wOptions & MSGI_MOUSE) { ! 929: /* ! 930: * Mouse message, decode to mouse types ! 931: */ ! 932: cch = sprintf(szNextMessage, ! 933: "%c%c%-20s H:%p X:%-4d Y:%-4d HT:%04x T:%s", ! 934: cSource, cThread, pmsgi->szMsg, pqmsgspy->qmsg.hwnd, ! 935: SHORT1FROMMP(pqmsgspy->qmsg.mp1), SHORT2FROMMP(pqmsgspy->qmsg.mp1), ! 936: SHORT1FROMMP(pqmsgspy->qmsg.mp2), szTime); ! 937: } else if (pmsgi->wOptions & MSGI_KEY) { ! 938: /* ! 939: * Key messages, output special ! 940: */ ! 941: bAscii = (CHAR)SHORT1FROMMP(pqmsgspy->qmsg.mp2); ! 942: if ((bAscii < ' ') || (bAscii > '~')) ! 943: bAscii = ' '; ! 944: ! 945: cch = sprintf(szNextMessage, ! 946: "%c%c%-20s H:%p F:%04x R:%d S:%2x C:%04x(%c) V:%02x T:%s", ! 947: cSource, cThread, pmsgi->szMsg, pqmsgspy->qmsg.hwnd, ! 948: SHORT1FROMMP(pqmsgspy->qmsg.mp1), ! 949: CHAR3FROMMP(pqmsgspy->qmsg.mp1), CHAR4FROMMP(pqmsgspy->qmsg.mp1), ! 950: SHORT1FROMMP(pqmsgspy->qmsg.mp2), bAscii, ! 951: SHORT2FROMMP(pqmsgspy->qmsg.mp2), szTime); ! 952: } else { ! 953: /* No special format */ ! 954: cch = sprintf(szNextMessage, ! 955: "%c%c%-20s H:%p 1:%08lx 2:%08lx T:%s", ! 956: cSource, cThread, pmsgi->szMsg, pqmsgspy->qmsg.hwnd, ! 957: pqmsgspy->qmsg.mp1, pqmsgspy->qmsg.mp2, szTime); ! 958: } ! 959: ! 960: OutputString(szNextMessage, cch); ! 961: ! 962: /* ! 963: * Now dump out any additional information associated with the ! 964: * message. The processing depends of the type of message on ! 965: * how we are going to process the data. ! 966: */ ! 967: if (spyopt.fSendExtend) { ! 968: prgData = DumpParam((PSZ)rgMsgData, pqmsgspy->cbDataMP1, ! 969: pqmsgspy->fMP1Valid, pqmsgspy->bMPType); ! 970: ! 971: DumpParam(prgData, pqmsgspy->cbDataMP2, pqmsgspy->fMP1Valid, ! 972: (UCHAR)((pqmsgspy->bMPType) >> 3)); ! 973: } ! 974: ! 975: } ! 976: ! 977: ! 978: ! 979: ! 980: /**************************** Public Function ******************************\ ! 981: * PSZ DumpParam(PSZ prgData, MPARAM mp, SHORT cb, BOOL fValid, UCHAR bMPType) ! 982: * ! 983: * Dump the additional information that was captured for the message. ! 984: * using the currently defined types. ! 985: * ! 986: * Return value: PSZ - Pointer to next available byte after process DATA ! 987: \***************************************************************************/ ! 988: PSZ DumpParam(prgData, cb, fValidData, bMPType) ! 989: PSZ prgData; ! 990: SHORT cb; ! 991: BOOL fValidData; ! 992: UCHAR bMPType; ! 993: { ! 994: char szNextMessage[100]; ! 995: SHORT cch; ! 996: ! 997: ! 998: if (fValidData) { ! 999: /* Process by type */ ! 1000: switch (bMPType & 0x07) { ! 1001: case MPT_SWP: ! 1002: cch = sprintf(szNextMessage, ! 1003: " SWP: fs:%p cx:%d cy:%d y:%d x:%d HB:%p H:%p", ! 1004: ((PSWP)prgData)->fl, ((PSWP)prgData)->cy, ((PSWP)prgData)->cx, ! 1005: ((PSWP)prgData)->y, ((PSWP)prgData)->x, ! 1006: ((PSWP)prgData)->hwndInsertBehind, ! 1007: ((PSWP)prgData)->hwnd); ! 1008: ! 1009: break; ! 1010: ! 1011: case MPT_RECTL: ! 1012: cch = sprintf(szNextMessage, ! 1013: " RECTL: xLeft:%d yBottom:%d xRight:%d yTop:%d", ! 1014: ((PRECTL)prgData)->xLeft, ((PRECTL)prgData)->yBottom, ! 1015: ((PRECTL)prgData)->xRight, ((PRECTL)prgData)->yTop); ! 1016: break; ! 1017: ! 1018: case MPT_QMSG: ! 1019: cch = sprintf(szNextMessage, ! 1020: " QMSG: H:%p M:%04x M1:%08lx M2:%08lx T:%08lx (%d, %d)", ! 1021: ((PQMSG)prgData)->hwnd, ((PQMSG)prgData)->msg, ! 1022: ((PQMSG)prgData)->mp1,((PQMSG)prgData)->mp2, ! 1023: ((PQMSG)prgData)->time, ! 1024: ((PQMSG)prgData)->ptl.x, ((PQMSG)prgData)->ptl.y); ! 1025: break; ! 1026: ! 1027: default: ! 1028: goto NoData; ! 1029: } ! 1030: ! 1031: OutputString(szNextMessage, cch); ! 1032: } ! 1033: NoData: ! 1034: return (prgData + cb); ! 1035: } ! 1036: ! 1037: ! 1038: ! 1039: ! 1040: /**************************** Public Function ******************************\ ! 1041: * void OutputString(char szOut, SHORT cch); ! 1042: * ! 1043: * Effects: This function will output the specified string to the ! 1044: * destinations. ! 1045: * ! 1046: * Return value: none ! 1047: \***************************************************************************/ ! 1048: ! 1049: void OutputString(szOut, cch) ! 1050: char szOut[]; ! 1051: SHORT cch; ! 1052: { ! 1053: SHORT item; ! 1054: char *psz; ! 1055: ULONG cchWritten; ! 1056: ! 1057: /* This is a private entry point in the PMWIN dll that places */ ! 1058: /* strings into the window. */ ! 1059: SHORT _far16 _pascal _loadds DebugOutput( char _far16 * ); ! 1060: ! 1061: /* Now display the new Line on the screen */ ! 1062: if (spyopt.fWindow) { ! 1063: item = (SHORT)WinSendMsg(hwndSpyList, LM_INSERTITEM, ! 1064: (MPARAM)LIT_END, (MPARAM)(PSZ)szOut); ! 1065: ! 1066: WinSendMsg(hwndSpyList, LM_SETTOPINDEX, (MPARAM)item, 0L); ! 1067: ! 1068: /* See if we have to many lines now */ ! 1069: while (item >= spyopt.cWindowLines) ! 1070: item = (SHORT)WinSendMsg(hwndSpyList, LM_DELETEITEM, ! 1071: (MPARAM)0, 0L); ! 1072: } ! 1073: ! 1074: /* now for file or debug terminal need cr/lf */ ! 1075: psz = szOut + cch; /* point to trailing null */ ! 1076: *psz++ = '\r'; ! 1077: *psz++ = '\n'; ! 1078: *psz = '\0'; ! 1079: ! 1080: if (spyopt.fDebugOutput) ! 1081: DebugOutput((char _far16*)szOut); ! 1082: ! 1083: if (spyopt.fFile) ! 1084: DosWrite(spyopt.hfileSpy, (PSZ)szOut, cch+2, ! 1085: &cchWritten); ! 1086: ! 1087: } ! 1088: ! 1089: ! 1090: /**************************** Public Function ******************************\ ! 1091: * MSGI * PmsgiFromMsg(USHORT msg) ! 1092: * ! 1093: * Effects: Locate the msg in the array of message items ! 1094: * ! 1095: * Return value: pointer to item that has the specified msg, or NULL ! 1096: \***************************************************************************/ ! 1097: MSGI *PmsgiFromMsg(msg) ! 1098: USHORT msg; ! 1099: { ! 1100: register MSGI *pmsgi = rgmsgi; /* Start at beginning */ ! 1101: register USHORT i; ! 1102: ! 1103: /* ! 1104: * Currently is a simple linear search, should be made faster ! 1105: * Probabably a binary search. ! 1106: */ ! 1107: for (i=0; i< cmsgi; i++) { ! 1108: if (pmsgi->msg == msg) ! 1109: return (pmsgi); ! 1110: if (pmsgi->msg > msg) ! 1111: return (NULL); ! 1112: pmsgi++; ! 1113: }; ! 1114: ! 1115: return (NULL); ! 1116: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.