_UNDOCUMENTED CORNER_ edited by Andrew Schulman "Spying on WinHelp" by Ron Burk [LISTING ONE] /* helpspy.c - spy on WM_WINHELP messages, system-wide */ #include #include #include #include "hookmsg.h" #include "helpspy.h" #define MAX_STRING (256) LRESULT CALLBACK _export HookProc(int, WPARAM, LPARAM); BOOL CALLBACK _export DlgProc(HWND, UINT, WPARAM, LPARAM); UINT WM_WINHELP; /* a registered window message */ UINT WM_WINDOC; /* the one that Viewer uses */ HWND ListBox; /* listbox to display messages */ HICON MyIcon; typedef struct HelpParams { int Size; int Message; long Context; long Unknown; int PathOffset; int StringOffset; char Path[1]; } HelpParams; static HHOOK MsgHook; #ifdef __BORLANDC__ #pragma argsused #endif int PASCAL WinMain(HINSTANCE Me, HINSTANCE Previous, LPSTR lpszCmdLine, int nCmdShow) { if(Previous) { MessageBox(NULL, "HelpSpy already running.", "HelpSpy", MB_OK); return 0; } MyIcon = LoadIcon(Me, "HelpSpyIcon"); WM_WINHELP = RegisterWindowMessage("WM_WINHELP"); WM_WINDOC = RegisterWindowMessage("WM_WINDOC"); MsgHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, Me, NULL); DialogBox(Me, "HelpSpyDialog", NULL, DlgProc); UnhookWindowsHookEx(MsgHook); return 0; } /* HookProc - pass only WM_WINHELP messages to DumpWinHelp(). */ LRESULT CALLBACK _export HookProc(int Code, WPARAM Param1, LPARAM Param2) { void DumpWinHelp(UINT Message, LPARAM Param2); typedef struct HMSG { LPARAM lParam; WPARAM wParam; UINT message; HWND hwnd; } HMSG; HMSG *Message = (HMSG *)Param2; if(Message->message == WM_WINHELP || Message->message == WM_WINDOC) DumpWinHelp(Message->message, Message->lParam); if(Code < 0) CallNextHookEx(MsgHook, Code, Param1, Param2); return 0; } /* DumpWinHelp() - dump a WM_WINHELP message. */ void DumpWinHelp(UINT Message, LPARAM Param2) { char String[MAX_STRING]; char *Command = "HELP_UNKNOWN"; HGLOBAL Handle = (HGLOBAL)Param2; HelpParams *Params = (HelpParams *)GlobalLock(Handle); switch(Params->Message) { case HELP_CONTEXT: Command = "HELP_CONTEXT"; break; case HELP_CONTEXTPOPUP: Command = "HELP_CONTEXTPOPUP"; break; case HELP_CONTENTS: Command = "HELP_CONTENTS"; break; case HELP_SETCONTENTS: Command = "HELP_SETCONTENTS"; break; case HELP_KEY: Command = "HELP_KEY"; break; case HELP_PARTIALKEY: Command = "HELP_PARTIALKEY"; break; case HELP_MULTIKEY: Command = "HELP_MULTIKEY"; break; case HELP_COMMAND: Command = "HELP_COMMAND"; break; case HELP_SETWINPOS: Command = "HELP_SETWINPOS"; break; case HELP_FORCEFILE: Command = "HELP_FORCEFILE"; break; case HELP_HELPONHELP: Command = "HELP_HELPONHELP"; break; case HELP_QUIT: Command = "HELP_QUIT"; break; } sprintf(String, "%s(%s", (Message == WM_WINHELP) ? "WinHelp" : "MVAPI", Command); switch(Params->Message) { case HELP_SETCONTENTS : case HELP_CONTEXT : case HELP_CONTEXTPOPUP : sprintf(String+strlen(String), ",%ld)", Params->Context); break; case HELP_KEY : case HELP_PARTIALKEY : case HELP_COMMAND : sprintf(String+strlen(String), ",'%s')", (char *)Params + Params->StringOffset); break; case HELP_CONTENTS : case HELP_FORCEFILE : case HELP_HELPONHELP : case HELP_QUIT : strcat(String, ")"); break; case HELP_SETWINPOS : { HELPWININFO *Info = (HELPWININFO *) ((char *)Params + Params->StringOffset); sprintf(String+strlen(String), ",x=%d,y=%d,dx=%d,dy=%d,wMax=%d,\"%s\")", Info->x, Info->y, Info->dx, Info->dy, Info->wMax, Info->rgchMember); break; } case HELP_MULTIKEY : { MULTIKEYHELP *MultiKey = (MULTIKEYHELP *) ((char *)Params + Params->StringOffset); sprintf(String+strlen(String), ",'%c', '%.*s')", MultiKey->mkKeylist, MultiKey->mkSize-sizeof(UINT)-sizeof(BYTE), MultiKey->szKeyphrase); break; } default : strcat(String, ")"); } GlobalUnlock(Handle); SendMessage(ListBox, LB_INSERTSTRING, 0, (LPARAM)(LPCSTR)String); } /* DlgProc() - Store listbox handle in global variable. */ #ifdef __BORLANDC__ #pragma argsused #endif BOOL CALLBACK _export DlgProc(HWND Dialog, UINT Message, WPARAM Param1, LPARAM Param2) { if(Message == WM_INITDIALOG) { ListBox = GetDlgItem(Dialog, ID_LISTBOX); return TRUE; } else if(Message == WM_PAINT && IsIconic(Dialog)) { PAINTSTRUCT PaintInfo; BeginPaint(Dialog, &PaintInfo); DrawIcon(PaintInfo.hdc, 0, 0, MyIcon); EndPaint(Dialog, &PaintInfo); } else if(Message == WM_COMMAND) if(Param1 == IDOK || Param1 == IDCANCEL) { EndDialog(Dialog, 0); return TRUE; } return FALSE; } [LISTING TWO] APP =helpspy OBJ =$(APP).obj MODEL =-ml! #DEBUG =-d CCFLAGS =$(DEBUG) $(MODEL) -DSTRICT -wed .rc.res : rc -r $*.rc .c.obj : cc -c $(CCFLAGS) $*.c $(APP).exe : $(OBJ) $(APP).res makefile cc $(DEBUG) $(MODEL) $(OBJ) $(APP).res $(APP).res $(APP).obj : $(APP).h [LISTING THREE] #include #define ID_LISTBOX 101 #define MENU_HELP 201 [LISTING FOUR] #include "helpspy.h" HelpSpyDialog DIALOG 15, 131, 306, 41 STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX CAPTION "HelpSpy" BEGIN CONTROL "", ID_LISTBOX, "LISTBOX", LBS_NOTIFY | LBS_DISABLENOSCROLL | WS_CHILD | WS_VISIBLE | WS_VSCROLL, 2, 0, 304, 42 END HelpSpyIcon ICON "helpspy.ico"