From b6aad50245569eabe3d0da7d1d68533d5889cb7d Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Mon, 11 Nov 2002 22:20:47 +0000 Subject: [PATCH] Implemented a Wine-only scheme for interprocess WinHelp message passing. --- dlls/user/user16.c | 18 ++++ programs/Makefile.in | 7 +- programs/winhelp/string.c | 15 ++- programs/winhelp/winhelp.c | 81 +++++++++++++- windows/winhelp.c | 210 ++++++++++++++++++------------------- 5 files changed, 211 insertions(+), 120 deletions(-) diff --git a/dlls/user/user16.c b/dlls/user/user16.c index 02d2b1ea06e..2f442935672 100644 --- a/dlls/user/user16.c +++ b/dlls/user/user16.c @@ -438,3 +438,21 @@ BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags ) CONV_RECT32TO16( &rect32, rc ); return ret; } + +/********************************************************************** + * WinHelp (USER.171) + */ +BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand, + DWORD dwData ) +{ + BOOL ret; + DWORD mutex_count; + + /* We might call WinExec() */ + ReleaseThunkLock(&mutex_count); + + ret = WinHelpA(WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData)); + + RestoreThunkLock(mutex_count); + return ret; +} diff --git a/programs/Makefile.in b/programs/Makefile.in index 74a3de9addf..4aa98583642 100644 --- a/programs/Makefile.in +++ b/programs/Makefile.in @@ -67,7 +67,8 @@ INSTALLPROGS = \ # Symlinks to apps that we want to run from inside the source tree SYMLINKS = \ wineconsole.exe \ - winedbg.exe + winedbg.exe \ + winhelp.exe @MAKE_RULES@ @@ -120,7 +121,11 @@ wineconsole.exe$(DLLEXT): wineconsole/wineconsole.exe$(DLLEXT) winedbg.exe$(DLLEXT): winedbg/winedbg.exe$(DLLEXT) $(RM) $@ && $(LN_S) winedbg/winedbg.exe$(DLLEXT) $@ +winhelp.exe$(DLLEXT): winhelp/winhelp.exe$(DLLEXT) + $(RM) $@ && $(LN_S) winhelp/winhelp.exe$(DLLEXT) $@ + wineconsole/wineconsole.exe$(DLLEXT): wineconsole winedbg/winedbg.exe$(DLLEXT): winedbg +winhelp/winhelp.exe$(DLLEXT): winhelp ### Dependencies: diff --git a/programs/winhelp/string.c b/programs/winhelp/string.c index 8d5c76656fc..17da0f88fd8 100644 --- a/programs/winhelp/string.c +++ b/programs/winhelp/string.c @@ -18,19 +18,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "windows.h" -#include "winhelp.h" - /* Class names */ -CHAR MAIN_WIN_CLASS_NAME[] = "WHMain"; -CHAR BUTTON_BOX_WIN_CLASS_NAME[] = "WHButtonBox"; -CHAR TEXT_WIN_CLASS_NAME[] = "WHText"; -CHAR SHADOW_WIN_CLASS_NAME[] = "WHShadow"; -CHAR STRING_BUTTON[] = "BUTTON"; +char MAIN_WIN_CLASS_NAME[] = "MS_WINHELP"; +char BUTTON_BOX_WIN_CLASS_NAME[] = "WHButtonBox"; +char TEXT_WIN_CLASS_NAME[] = "WHText"; +char SHADOW_WIN_CLASS_NAME[] = "WHShadow"; +char STRING_BUTTON[] = "BUTTON"; /* Resource names */ -CHAR STRING_DIALOG_TEST[] = "DIALOG_TEST"; +char STRING_DIALOG_TEST[] = "DIALOG_TEST"; /* Local Variables: */ /* c-file-style: "GNU" */ diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c index 659b53533f8..b0f3b805a16 100644 --- a/programs/winhelp/winhelp.c +++ b/programs/winhelp/winhelp.c @@ -54,11 +54,11 @@ static BOOL MacroTest = FALSE; */ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) { - MSG msg; - LONG lHash = 0; + MSG msg; + LONG lHash = 0; Globals.hInstance = hInstance; - + /* Get options */ while (*cmdline && (*cmdline == ' ' || *cmdline == '-')) { @@ -87,6 +87,14 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) case 't': MacroTest = TRUE; break; + + case 'x': + show = SW_HIDE; + break; + + default: + WINE_FIXME("Unsupported cmd line: %s\n", cmdline); + break; } } @@ -142,6 +150,69 @@ static BOOL WINHELP_RegisterWinClasses(void) RegisterClass(&class_shadow)); } +typedef struct +{ + WORD size; + WORD command; + LONG data; + LONG reserved; + WORD ofsFilename; + WORD ofsData; +} WINHELP,*LPWINHELP; + +/****************************************************************** + * WINHELP_HandleCommand + * + * + */ +static LRESULT WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam) +{ + COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + WINHELP* wh; + + if (cds->dwData != 0xA1DE505) + { + WINE_FIXME("Wrong magic number (%08lx)\n", cds->dwData); + return 0; + } + + wh = (WINHELP*)cds->lpData; + + if (wh) + { + WINE_TRACE("Got[%u]: cmd=%u data=%08lx fn=%s\n", + wh->size, wh->command, wh->data, + wh->ofsFilename ? (LPSTR)wh + wh->ofsFilename : ""); + switch (wh->command) + { + case HELP_QUIT: + MACRO_Exit(); + break; + case HELP_FINDER: + /* in fact, should be the topic dialog box */ + if (wh->ofsFilename) + { + MACRO_JumpHash((LPSTR)wh + wh->ofsFilename, "main", 0); + } + break; + case HELP_CONTEXT: + case HELP_SETCONTENTS: + case HELP_CONTENTS: + case HELP_CONTEXTPOPUP: + case HELP_FORCEFILE: + case HELP_HELPONHELP: + case HELP_KEY: + case HELP_PARTIALKEY: + case HELP_COMMAND: + case HELP_MULTIKEY: + case HELP_SETWINPOS: + WINE_FIXME("NIY\n"); + break; + } + } + return 0L; +} + /*********************************************************************** * * WINHELP_CreateHelpWindow @@ -257,6 +328,7 @@ static BOOL WINHELP_CreateHelpWindow(HLPFILE_PAGE* page, LPCSTR lpszWindow, WINHELP_SetupText(win->hTextWnd); InvalidateRect(win->hTextWnd, NULL, TRUE); SendMessage(win->hMainWnd, WM_USER, 0, 0); + ShowWindow(win->hMainWnd, nCmdShow); UpdateWindow(win->hTextWnd); @@ -418,8 +490,9 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, case WM_DESTROY: if (Globals.hPopupWnd) DestroyWindow(Globals.hPopupWnd); break; + case WM_COPYDATA: + return WINHELP_HandleCommand((HWND)wParam, lParam); } - return DefWindowProc(hWnd, msg, wParam, lParam); } diff --git a/windows/winhelp.c b/windows/winhelp.c index 6cb6abd5523..b9bfd85ad6b 100644 --- a/windows/winhelp.c +++ b/windows/winhelp.c @@ -2,6 +2,7 @@ * Windows Help * * Copyright 1996 Martin von Loewis + * 2002 Eric Pouech * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,17 +28,31 @@ # include #endif #include "wine/debug.h" -#include "windef.h" +#include "winbase.h" #include "wingdi.h" -#include "wownt32.h" -#include "wine/winuser16.h" -#include "wine/winbase16.h" -#include "win.h" +#include "winuser.h" +#include "winnls.h" WINE_DEFAULT_DEBUG_CHANNEL(win); - -/* WinHelp internal structure */ +/* Wine doesn't use the way WinHelp API sends information in Windows, because: + * 1/ it's not consistent acrosss Win9x, NT... + * 2/ NT implementation is not yet fully understood (and includes some shared + * memory mechanism) + * 3/ uses a dynamically allocated message number (WM_WINHELP), which + * obfuscates the code + * + * So we use (for now) the simple protocol: + * 1/ it's based on copy data + * 2/ we tag the message with a magic number, to make it a bit more robust + * (even if it's not 100% safe) + * 3/ data structure (WINHELP) has the same layout that the one used on Win95. + * This doesn't bring much, except not going to far away from real + * implementation. + * + * This means anyway that native winhelp.exe and winhlp32.exe cannot be + * called/manipulated from WinHelp API. + */ typedef struct { WORD size; @@ -46,117 +61,100 @@ typedef struct LONG reserved; WORD ofsFilename; WORD ofsData; -} WINHELP,*LPWINHELP; +} WINHELP; -/********************************************************************** - * WinHelp (USER.171) +/* magic number for this message: + * aide means help is French ;-) + * SOS means ??? */ -BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand, - DWORD dwData ) -{ - BOOL ret; - DWORD mutex_count; - - /* We might call WinExec() */ - ReleaseThunkLock( &mutex_count ); - - if (!(ret = WinHelpA( WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData) ))) - { - /* try to start the 16-bit winhelp */ - if (WinExec( "winhelp.exe -x", SW_SHOWNORMAL ) >= 32) - { - K32WOWYield16(); - ret = WinHelpA( WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData) ); - } - } - - RestoreThunkLock( mutex_count ); - return ret; -} - +#define WINHELP_MAGIC 0xA1DE505 /********************************************************************** * WinHelpA (USER32.@) */ BOOL WINAPI WinHelpA( HWND hWnd, LPCSTR lpHelpFile, UINT wCommand, ULONG_PTR dwData ) { - static WORD WM_WINHELP = 0; - HWND hDest; - LPWINHELP lpwh; - HGLOBAL16 hwh; - int size,dsize,nlen; + COPYDATASTRUCT cds; + HWND hDest; + int size, dsize, nlen; + WINHELP* lpwh; - - if(!WM_WINHELP) - { - WM_WINHELP=RegisterWindowMessageA("WM_WINHELP"); - if(!WM_WINHELP) - return FALSE; - } - - hDest = FindWindowA( "MS_WINHELP", NULL ); - if(!hDest) { - if(wCommand == HELP_QUIT) return TRUE; - if (WinExec ( "winhlp32.exe -x", SW_SHOWNORMAL ) < 32) { - ERR("can't start winhlp32.exe -x ?\n"); - return FALSE; - } - if ( ! ( hDest = FindWindowA ( "MS_WINHELP", NULL ) )) { - FIXME("did not find MS_WINHELP (FindWindow() failed, maybe global window handling still unimplemented)\n"); - return FALSE; - } + hDest = FindWindowA("MS_WINHELP", NULL); + if (!hDest) + { + if (wCommand == HELP_QUIT) return TRUE; + if (WinExec("winhelp.exe -x", SW_SHOWNORMAL) < 32) + { + ERR("can't start winhelp.exe -x ?\n"); + return FALSE; } + if (!(hDest = FindWindowA("MS_WINHELP", NULL))) + { + FIXME("Did not find a MS_WINHELP Window\n"); + return FALSE; + } + } + switch (wCommand) + { + case HELP_CONTEXT: + case HELP_SETCONTENTS: + case HELP_CONTENTS: + case HELP_CONTEXTPOPUP: + case HELP_FORCEFILE: + case HELP_HELPONHELP: + case HELP_FINDER: + case HELP_QUIT: + dsize = 0; + break; + case HELP_KEY: + case HELP_PARTIALKEY: + case HELP_COMMAND: + dsize = dwData ? strlen((LPSTR)dwData) + 1 : 0; + break; + case HELP_MULTIKEY: + dsize = ((LPMULTIKEYHELPA)dwData)->mkSize; + break; + case HELP_SETWINPOS: + dsize = ((LPHELPWININFOA)dwData)->wStructSize; + break; + default: + FIXME("Unknown help command %d\n", wCommand); + return FALSE; + } + if (lpHelpFile) + nlen = strlen(lpHelpFile) + 1; + else + nlen = 0; + size = sizeof(WINHELP) + nlen + dsize; - switch(wCommand) - { - case HELP_CONTEXT: - case HELP_SETCONTENTS: - case HELP_CONTENTS: - case HELP_CONTEXTPOPUP: - case HELP_FORCEFILE: - case HELP_HELPONHELP: - case HELP_FINDER: - case HELP_QUIT: - dsize=0; - break; - case HELP_KEY: - case HELP_PARTIALKEY: - case HELP_COMMAND: - dsize = dwData ? strlen( (LPSTR)dwData )+1: 0; - break; - case HELP_MULTIKEY: - dsize = ((LPMULTIKEYHELPA)dwData)->mkSize; - break; - case HELP_SETWINPOS: - dsize = ((LPHELPWININFOA)dwData)->wStructSize; - break; - default: - FIXME("Unknown help command %d\n",wCommand); - return FALSE; - } - if(lpHelpFile) - nlen = strlen(lpHelpFile)+1; - else - nlen = 0; - size = sizeof(WINHELP) + nlen + dsize; - hwh = GlobalAlloc16(0,size); - lpwh = GlobalLock16(hwh); - lpwh->size = size; - lpwh->command = wCommand; - lpwh->data = dwData; - if(nlen) { - strcpy(((char*)lpwh) + sizeof(WINHELP),lpHelpFile); - lpwh->ofsFilename = sizeof(WINHELP); - } else - lpwh->ofsFilename = 0; - if(dsize) { - memcpy(((char*)lpwh)+sizeof(WINHELP)+nlen,(LPSTR)dwData,dsize); - lpwh->ofsData = sizeof(WINHELP)+nlen; - } else - lpwh->ofsData = 0; - GlobalUnlock16(hwh); - return SendMessage16(HWND_16(hDest),WM_WINHELP,HWND_16(hWnd),hwh); + lpwh = HeapAlloc(GetProcessHeap(), 0, size); + if (!lpwh) return FALSE; + + cds.dwData = WINHELP_MAGIC; + cds.cbData = size; + cds.lpData = (void*)lpwh; + + lpwh->size = size; + lpwh->command = wCommand; + lpwh->data = dwData; + if (nlen) + { + strcpy(((char*)lpwh) + sizeof(WINHELP), lpHelpFile); + lpwh->ofsFilename = sizeof(WINHELP); + } else + lpwh->ofsFilename = 0; + if (dsize) + { + memcpy(((char*)lpwh) + sizeof(WINHELP) + nlen, (LPSTR)dwData, dsize); + lpwh->ofsData = sizeof(WINHELP) + nlen; + } else + lpwh->ofsData = 0; + WINE_TRACE("Sending[%u]: cmd=%u data=%08lx fn=%s\n", + lpwh->size, lpwh->command, lpwh->data, + lpwh->ofsFilename ? (LPSTR)lpwh + lpwh->ofsFilename : ""); + + return SendMessageA(hDest, WM_COPYDATA, hWnd, (LPARAM)&cds); }