|  | /* | 
|  | * 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 | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #ifdef HAVE_UNISTD_H | 
|  | # include <unistd.h> | 
|  | #endif | 
|  | #include "wine/debug.h" | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winuser.h" | 
|  | #include "winnls.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(win); | 
|  |  | 
|  | /* Wine doesn't use the way WinHelp API sends information in Windows, because: | 
|  | * 1/ it's not consistent across 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; | 
|  | WORD command; | 
|  | LONG data; | 
|  | LONG reserved; | 
|  | WORD ofsFilename; | 
|  | WORD ofsData; | 
|  | } WINHELP; | 
|  |  | 
|  | /* magic number for this message: | 
|  | *  aide means help is French ;-) | 
|  | *  SOS means ??? | 
|  | */ | 
|  | #define WINHELP_MAGIC   0xA1DE505 | 
|  |  | 
|  | /********************************************************************** | 
|  | *		WinHelpA (USER32.@) | 
|  | */ | 
|  | BOOL WINAPI WinHelpA( HWND hWnd, LPCSTR lpHelpFile, UINT wCommand, ULONG_PTR dwData ) | 
|  | { | 
|  | COPYDATASTRUCT      cds; | 
|  | HWND                hDest; | 
|  | int                 size, dsize, nlen; | 
|  | WINHELP*            lpwh; | 
|  |  | 
|  | 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 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; | 
|  |  | 
|  | 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=%08x fn=%s\n", | 
|  | lpwh->size, lpwh->command, lpwh->data, | 
|  | lpwh->ofsFilename ? (LPSTR)lpwh + lpwh->ofsFilename : ""); | 
|  |  | 
|  | return SendMessageA(hDest, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds); | 
|  | } | 
|  |  | 
|  |  | 
|  | /********************************************************************** | 
|  | *		WinHelpW (USER32.@) | 
|  | */ | 
|  | BOOL WINAPI WinHelpW( HWND hWnd, LPCWSTR helpFile, UINT command, ULONG_PTR dwData ) | 
|  | { | 
|  | INT len; | 
|  | LPSTR file; | 
|  | BOOL ret = FALSE; | 
|  |  | 
|  | if (!helpFile) return WinHelpA( hWnd, NULL, command, dwData ); | 
|  |  | 
|  | len = WideCharToMultiByte( CP_ACP, 0, helpFile, -1, NULL, 0, NULL, NULL ); | 
|  | if ((file = HeapAlloc( GetProcessHeap(), 0, len ))) | 
|  | { | 
|  | WideCharToMultiByte( CP_ACP, 0, helpFile, -1, file, len, NULL, NULL ); | 
|  | ret = WinHelpA( hWnd, file, command, dwData ); | 
|  | HeapFree( GetProcessHeap(), 0, file ); | 
|  | } | 
|  | return ret; | 
|  | } |