Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

301 lines
9.9 KiB

/*****************************************************************************
* *
* HELPCALL.C *
* *
* Copyright (C) Microsoft Corporation 1989. *
* All Rights reserved. *
* *
******************************************************************************
* *
* Program Description: Sample interface to windows help *
* *
******************************************************************************
* *
* Revision History: Created by RKB 11/30/88 *
* Revised to new API 1/12/88 (RKB) *
* Added to USER 3/28/89 (BG) *
* Slight update 6/15/89 (BG) *
* Clean ugly code 10/30/89 (BG) *
* GlobalFree if QUIT 1/26/90 (CRC) *
* *
******************************************************************************
*/
#define NO_REDEF_SENDMESSAGE
#include "user.h"
//
// We define certain things here because including mvdm\inc\*.h files here
// will lead to endless mess.
//
#define WM_WINHELP 0x38
DWORD API NotifyWow(WORD, LPBYTE);
#define FUN_WINHELP 171 //
WORD msgWinHelp = 0;
char CODESEG szMS_WINHELP[] = "MS_WINHELP";
/*
Communicating with WinHelp involves using Windows SendMessage() function
to pass blocks of information to WinHelp. The call looks like.
SendMessage(hwndHelp, msgWinHelp, hwndMain, (LONG)hHlp);
Where:
hwndHelp - the window handle of the help application. This
is obtained by enumerating all the windows in the
system and sending them HELP_FIND commands. The
application may have to load WinHelp.
msgWinHelp - the value obtained from a RegisterWindowMessage()
szWINHELP
hwndMain - the handle to the main window of the application
calling help
hHlp - a handle to a block of data with a HLP structure
at it head.
The data in the handle will look like:
+-------------------+
| cbData |
| usCommand |
| ulTopic |
| ulReserved |
| offszHelpFile |\ - offsets measured from beginning
/ | offaData | \ of header.
/ +-------------------| /
/ | Help file name |/
\ | and path |
\ +-------------------+
\ | Other data |
| (keyword) |
+-------------------+
The defined commands are:
HELP_CONTEXT 0x0001 Display topic in ulTopic
HELP_KEY 0x0101 Display topic for keyword in offabData
HELP_QUIT 0x0002 Terminate help
*/
/*******************
**
** Name: HFill
**
** Purpose: Builds a data block for communicating with help
**
** Arguments: lpszHelp - pointer to the name of the help file to use
** usCommand - command being set to help
** ulData - data for the command
**
** Returns: a handle to the data block or hNIL if the the
** block could not be created.
**
*******************/
HANDLE HFill(LPCSTR lpszHelp, WORD usCommand, DWORD ulData)
{
WORD cb; /* Size of the data block */
HANDLE hHlp; /* Handle to return */
BYTE bHigh; /* High byte of usCommand */
LPHLP qhlp; /* Pointer to data block */
/* Calculate size */
if (lpszHelp)
cb = sizeof(HLP) + lstrlen(lpszHelp) + 1;
else
cb = sizeof(HLP);
bHigh = (BYTE)HIBYTE(usCommand);
if (bHigh == 1)
cb += lstrlen((LPSTR)ulData) + 1;
else if (bHigh == 2)
cb += *((int far *)ulData);
/* Get data block */
if (!(hHlp = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD)cb)))
return NULL;
if (!(qhlp = (LPHLP)GlobalLock(hHlp)))
{
GlobalFree(hHlp);
return NULL;
}
qhlp->cbData = cb; /* Fill in info */
qhlp->usCommand = usCommand;
qhlp->ulReserved = 0;
if (lpszHelp)
{
qhlp->offszHelpFile = sizeof(HLP);
lstrcpy((LPSTR)(qhlp+1), lpszHelp);
}
else
qhlp->offszHelpFile = 0;
switch(bHigh)
{
case 0:
qhlp->offabData = 0;
qhlp->ulTopic = ulData;
break;
case 1:
qhlp->offabData = sizeof(HLP) + lstrlen(lpszHelp) + 1;
lstrcpy((LPSTR)qhlp + qhlp->offabData, (LPSTR)ulData);
break;
case 2:
qhlp->offabData = sizeof(HLP) + lstrlen(lpszHelp) + 1;
LCopyStruct((LPSTR)ulData, (LPSTR)qhlp + qhlp->offabData, *((int far *)ulData));
break;
}
GlobalUnlock(hHlp);
return hHlp;
}
char CODESEG szEXECHELP[] = "\\WINHELP -x";
BOOL _fastcall LaunchHelper(LPSTR lpfile)
{
int len;
len = lstrlen(lpfile);
if (lpfile[len-1]=='\\')
/* Are we at the root?? If so, skip over leading backslash in text
* string. */
lstrcat(lpfile, szEXECHELP+1);
else
lstrcat(lpfile, szEXECHELP);
return ((HINSTANCE)WinExec(lpfile, SW_SHOW) > HINSTANCE_ERROR);
}
BOOL LaunchHelp(VOID)
{
char szFile[128];
/* Search in windows directory */
GetWindowsDirectory(szFile, sizeof(szFile));
if (LaunchHelper(szFile))
return(TRUE);
/* Search system directory */
GetSystemDirectory(szFile, sizeof(szFile));
if (LaunchHelper(szFile))
return(TRUE);
/* Last ditch: simply let dos do it */
lstrcpy(szFile, szEXECHELP+1);
return ((HINSTANCE)WinExec(szFile, SW_SHOW) > HINSTANCE_ERROR);
}
/*******************
**
** Name: WinHelp
**
** Purpose: Displays help
**
** Arguments:
** hwndMain handle to main window of application
** lpszHelp path (if not current directory) and file
** to use for help topic.
** usCommand Command to send to help
** ulData Data associated with command:
** HELP_QUIT - no data (undefined)
** HELP_LAST - no data (undefined)
** HELP_CONTEXT - context number to display
** HELP_KEY - string ('\0' terminated)
** use as keyword to topic
** to display
** HELP_FIND - no data (undefined)
**
** Returns: TRUE iff success
**
*******************/
BOOL API IWinHelp(hwndMain, lpszHelp, usCommand, ulData)
HWND hwndMain;
LPCSTR lpszHelp;
WORD usCommand;
DWORD ulData;
{
register HANDLE hHlp;
DWORD dwHelpPid; /* loword is hwndHelp */
/* hiword TRUE if hwndHelp is of this process */
if (msgWinHelp == 0) {
/* Register private WinHelp message for communicating to WinHelp via
* WinHelp api.
*/
char static CODESEG szWM_WINHELP[] = "WM_WINHELP";
msgWinHelp = RegisterWindowMessage(szWM_WINHELP);
}
/* Move Help file name to a handle */
if (!(hHlp = HFill(lpszHelp, usCommand, ulData)))
return(FALSE);
if ((dwHelpPid = (DWORD)NotifyWow(FUN_WINHELP, szMS_WINHELP)) == (DWORD)NULL)
{
if (usCommand == HELP_QUIT) /* Don't bother to load HELP just to*/
{
GlobalFree(hHlp);
return(TRUE);
}
/* Can't find it --> launch it */
if (!LaunchHelp() || ((dwHelpPid = (DWORD)NotifyWow(FUN_WINHELP, szMS_WINHELP)) == (DWORD)NULL))
{
/* Can't find help, or not enough memory to load help.*/
GlobalFree(hHlp);
return(FALSE);
}
}
// if winhelp.exe was launched from this process, normal sendmessage else
// we need to thunk the data across WOWVDM processes and the format is
// msg = WM_WINHELP, a private msg
// wparam = 0 instead of hwndMain, (note 1)
// lparam = LPHLP
//
// note 1: winhelp, calls GetWindowWord(wParam, GWW_HINSTANCE) when it receives HELP_QUIT
// command. If this matches a value in its table and is the only registered instance
// winhelp will close - this is quite ok undernormal circumstances (just one WOWVDM)
// but under multiple WOWVDM, numeric value of hinstances could be same for different
// hwnds.
//
// So we workaround this by passing a NULL hwnd in wParam and by not sending HELP_QUIT
// message - which effectively implies that WinHelp will close only if there are no
// references to it from the same WOWVDM (as itself).
//
// This is the best compromise I could comeup with for running "only one WinHelp for all
// WOWVDMs".
//
// - nanduri
if (HIWORD(dwHelpPid)) {
SendMessage((HWND)LOWORD(dwHelpPid), msgWinHelp, (WPARAM)hwndMain, MAKELPARAM(hHlp, 0));
}
else {
if (usCommand != HELP_QUIT) {
SendMessage((HWND)LOWORD(dwHelpPid), WM_WINHELP, (WPARAM)0, (LPARAM)GlobalLock(hHlp));
GlobalUnlock(hHlp);
}
}
GlobalFree(hHlp);
return(TRUE);
}