mirror of https://github.com/lianthony/NT4.0
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.
527 lines
15 KiB
527 lines
15 KiB
/*****************************************************************************
|
|
* *
|
|
* MISCLYR.C *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1990. *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* *
|
|
* Misc layer functions. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Testing Notes *
|
|
* *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Current Owner: *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Released by Development: *
|
|
* *
|
|
******************************************************************************
|
|
*
|
|
* Revision History: Created 5/19/89 by Robert Bunney
|
|
* 06/26/90 RussPJ Deleted extern of lstrcpy
|
|
* 07/10/90 RobertBu I added an InvalidateRect() to the SetTitleQch()
|
|
* function so that the background gets erased when
|
|
* setting a title in the title window.
|
|
* 07/11/90 RobertBu SetTitleQch() was changed to send a message to the
|
|
* title window instead of using SetWindowText() because
|
|
* of problems with the mapping to PM.
|
|
* 07/14/90 RobertBu Changed RgbGetProfileQch() so that it used pszCaption
|
|
* instead of a hard coded string. It would not have
|
|
* worked for WinDoc.
|
|
* 07/19/90 RobertBu Added ErrorQch() (used by macros return error
|
|
* structures).
|
|
* 07/23/90 RobertBu Changed resident error table and added FLoadStrings()
|
|
* to load resident strings from the resource file.
|
|
* 07/26/90 RobertBu Changed pszCaption to pchINI for WIN.INI access.
|
|
* Added code to load another string from the .RC file
|
|
* for international.
|
|
* 08/06/90 RobertBu Changed order so that fFatalExit is set before the
|
|
* error dialog is put up (to prevent us from repainting
|
|
* after the dialog goes dow
|
|
* 08/21/90 RobertBu Changed HelpExec() so that it executes with show normal
|
|
* if a bad show parameter is passed (rather than just
|
|
* returning)
|
|
* 30-Aug-1990 RussPJ Modifed HfsPathOpenQfd to make a "safe" copy of
|
|
* filenames that are too long for DOS.
|
|
* 04-Oct-1990 LeoN hwndTopic => hwndTopicCur; hwndHelp => ahwnd[iCurWindow].hwndParent
|
|
* 04-Nov-1990 Tomsn Use new VA address type (enabling zeck compression)
|
|
* 06-Nov-1990 DavidFe Took out the old QFD support functions as the FM code
|
|
* takes care of all that stuff now.
|
|
* 07-Nov-1990 LeoN Re-enable DosExit Prototype
|
|
* 15-Nov-1990 LeoN Remove GetLastActivePopup call from ErrorHwnd and use
|
|
* the passed in hwnd. Callers are modified to pass the
|
|
* appropriate hwnd instead.
|
|
* 16-Nov-1990 LeoN Ensure that parent error window is visible. Error
|
|
* while bringing up system help could leave it
|
|
* invisible, while still displaying it's message box.
|
|
* Dismissing the message would leave the invisible
|
|
* instance active.
|
|
* 26-Nov-1990 LeoN ErrorHwnd can have problems recursing on itself.
|
|
* Place an upper limit on that.
|
|
* 29-Nov-1990 RobertBu #ifdef'ed out dead routines
|
|
* 03-Dec-1990 LeoN Added wMapFSErrorW
|
|
* 08-Dec-1990 RobertBu Removed HelpOn stuff from this module.
|
|
* 13-Dec-1990 LeoN Make ErrorQch SYSTEMMODAL
|
|
* 02-Apr-1991 RobertBu Removed CBT support
|
|
* 16-Apr-1991 RussPJ Added path searching for HelpExec(). (3.1 bug #989)
|
|
* 14-May-1991 RussPJ Fixed 3.1 #976 - SmallSysFont
|
|
* 01-Jul-1991 RussPJ Fixed 3.1 #1199 - Increased buffers for error msgs.
|
|
* 01-Jul-1991 RussPJ Fixed 3.1 #1193 - Changed error msg icon to 'i'.
|
|
* 08-Jul-1991 LeoN Help31 #1201: handle NULL hwnd in ErrorHwnd
|
|
* 22-Jan-1992 JohnSc Help31 #1401: add wERRA_LINGER to allow slow death
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "help.h"
|
|
#pragma hdrstop
|
|
|
|
#include <dos.h>
|
|
#include <ctype.h>
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Defines *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#define MAX_STRINGTBL 999
|
|
#define MAX_MSG 256
|
|
#define cbFileNameMax 20 // REVIEW -- should probably be 30 for mac
|
|
|
|
/*-------------------------------------------------------------------*\
|
|
* Filename length, including name, extension, '.', and '\0', at least
|
|
\*-------------------------------------------------------------------*/
|
|
#define cbMAXDOSFILENAME 14
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Variables *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#define MSB_GUARANTEED (MB_OK | MB_TASKMODAL | MB_ICONHAND)
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: ErrorHwnd
|
|
-
|
|
* Purpose: Backend for more generic error messages -- see Error
|
|
*
|
|
* Arguments: hwnd - window handle to use for owner of message box
|
|
* nError - error number
|
|
* wAction - action to take (see Error())
|
|
*
|
|
* Returns: Nothing
|
|
*
|
|
* Globals Used: pszCaption - application caption
|
|
* hInsNow - application instance handle
|
|
*
|
|
***************************************************************************/
|
|
|
|
static int cInHere = 0; // recursion prophylactic
|
|
#define CINHEREMAX 5 // max number of recursions
|
|
|
|
VOID STDCALL ErrorHwnd(HWND hwnd, int nError, int wAction, int RealError)
|
|
{
|
|
char szBuf[256];
|
|
|
|
/*
|
|
* In some cases, we will have already reported an error, but the
|
|
* original caller of the routine that may have generated the error
|
|
* won't know that. So, the routine being called can supress the
|
|
* caller's error message by setting the fSupressNextError flag.
|
|
*/
|
|
|
|
if (fSupressNextError) {
|
|
fSupressNextError = FALSE;
|
|
goto Action;
|
|
}
|
|
|
|
if (fSupressErrors)
|
|
goto Action;
|
|
|
|
if (cInHere < CINHEREMAX) {
|
|
|
|
// REVIEW: We limit the number of recursive calls that can be made to
|
|
// this routine to avoid what are essentially out of stack space
|
|
// scenarios. The number above (5) is pretty arbitrary, but I didn't
|
|
// want to claim that we can never get an error within an error by
|
|
// making it a boolean. 26-Nov-1990 leon
|
|
|
|
cInHere++;
|
|
|
|
if (wAction == wERRA_DIE)
|
|
fFatalExit = TRUE;
|
|
|
|
if (hwnd && !IsWindowVisible(hwnd))
|
|
hwnd = (hwndAnimate ? hwndAnimate : NULL);
|
|
else if (!hwnd)
|
|
hwnd = (hwndAnimate ? hwndAnimate : ahwnd[iCurWindow].hwndParent);
|
|
|
|
if (nError == wERRS_OOM ||
|
|
(nError >=wERRS_OOM_FIRST && nError <= wERRS_OOM_LAST))
|
|
wsprintf(szBuf, "%s (%u)", (LPSTR) pszOutOfMemory, nError);
|
|
else {
|
|
wsprintf(szBuf, "%s (%u)", (LPSTR) GetStringResource(nError), RealError);
|
|
}
|
|
|
|
/*
|
|
* If we can't display our message box, assume we're out of memory
|
|
* and die.
|
|
*/
|
|
|
|
if (hwndNote)
|
|
ShowNote(0, NULL, 1, FALSE);
|
|
|
|
// BUGBUG: wERRS_OOM could be a different value. See strtable.h
|
|
|
|
#if defined(_PRIVATE) && defined(_DEBUG)
|
|
{
|
|
int answer;
|
|
PSTR pszNewMsg = lcMalloc(strlen(szBuf) + 100);
|
|
strcpy(pszNewMsg, szBuf);
|
|
strcat(pszNewMsg, "\r\n\r\nClick YES to break into the debugger.");
|
|
|
|
if (fAutoClose)
|
|
KillTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE);
|
|
answer = MessageBox(hwnd, pszNewMsg, pszCaption,
|
|
MB_YESNO | MB_DEFBUTTON2);
|
|
if (fAutoClose)
|
|
SetTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE, NOTE_TIMEOUT,
|
|
NULL);
|
|
switch (answer) {
|
|
case IDYES:
|
|
DebugBreak();
|
|
|
|
// deliberately fall through
|
|
|
|
default:
|
|
lcFree(pszNewMsg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#else
|
|
// Normal action
|
|
|
|
if (fAutoClose)
|
|
KillTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE);
|
|
|
|
if (!MessageBox(hwnd, szBuf, pszCaption,
|
|
(nError == wERRS_OOM) ? MSB_GUARANTEED :
|
|
MB_OK | MB_TASKMODAL | MB_ICONINFORMATION) &&
|
|
nError == wERRS_OOM) {
|
|
MessageBox(hwnd, pszOutOfMemory, pszCaption, MSB_GUARANTEED);
|
|
wAction = wERRA_DIE;
|
|
}
|
|
|
|
if (fAutoClose)
|
|
SetTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE, NOTE_TIMEOUT,
|
|
NULL);
|
|
#endif
|
|
|
|
Action:
|
|
switch (wAction) {
|
|
HDE hde;
|
|
CHAR pszExecWinhelpWhenDone[MAX_PATH + 13] ;
|
|
case wERRA_DIE:
|
|
default:
|
|
Cleanup();
|
|
_exit(-1); // BAD! can we exit more gracefully?
|
|
break;
|
|
|
|
case wERRA_DIE_SPAWN:
|
|
hde = HdeGetEnv();
|
|
lstrcpy(pszExecWinhelpWhenDone,"winhelp.exe ");
|
|
lstrcat(pszExecWinhelpWhenDone, QDE_FM(QdeFromGh(hde)));
|
|
Cleanup();
|
|
WinExec(pszExecWinhelpWhenDone, SW_SHOW);
|
|
_exit(-1);
|
|
break;
|
|
|
|
case wERRA_RETURN:
|
|
break;
|
|
}
|
|
cInHere--;
|
|
}
|
|
}
|
|
|
|
VOID STDCALL ErrorVarArgs(int nError, WORD wAction, LPCSTR pszMsg)
|
|
{
|
|
char nszFormat[MAX_MSG];
|
|
char szMsg[MAX_MSG * 2];
|
|
|
|
/*
|
|
* In some cases, we will have already reported an error, but the
|
|
* original caller of the routine that may have generated the error
|
|
* won't know that. So, the routine being called can supress the
|
|
* caller's error message by setting the fSupressNextError flag.
|
|
*/
|
|
|
|
if (fSupressNextError) {
|
|
fSupressNextError = FALSE;
|
|
if (wAction != wERRA_RETURN) {
|
|
Cleanup();
|
|
_exit(-1); // BAD! can we exit more gracefully?
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (fSupressErrors) {
|
|
if (wAction != wERRA_RETURN) {
|
|
Cleanup();
|
|
_exit(-1); // BAD! can we exit more gracefully?
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!fHelpAuthor && nError >= FIRST_AUTHOR_BUG && nError <= LAST_AUTHOR_BUG)
|
|
nError = wERRS_HELPAUTHORBUG;
|
|
|
|
#if defined(_PRIVATE) && defined(_DEBUG)
|
|
{
|
|
int answer;
|
|
|
|
if (pszMsg) {
|
|
wsprintf(szMsg, GetStringResource(nError), pszMsg);
|
|
}
|
|
else
|
|
strcpy(szMsg, GetStringResource(nError));
|
|
|
|
if (fAutoClose)
|
|
KillTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE);
|
|
answer = MessageBox((hwndAnimate ? hwndAnimate : ahwnd[iCurWindow].hwndParent),
|
|
szMsg, "Click Retry to break into debugger",
|
|
MB_ABORTRETRYIGNORE);
|
|
if (fAutoClose)
|
|
SetTimer(ahwnd[MAIN_HWND].hwndParent, ID_AUTO_CLOSE, NOTE_TIMEOUT,
|
|
NULL);
|
|
switch (answer) {
|
|
case IDABORT:
|
|
Cleanup();
|
|
_exit(-1); // BAD! can we exit more gracefully?
|
|
return;
|
|
|
|
case IDRETRY:
|
|
DebugBreak();
|
|
|
|
// deliberately fall through
|
|
|
|
case IDIGNORE:
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (LoadString(hInsNow, nError, nszFormat, MAX_MSG)) {
|
|
if (pszMsg) {
|
|
wsprintf(szMsg, nszFormat, pszMsg);
|
|
if (OkMsgBox(szMsg))
|
|
return;
|
|
}
|
|
else if (OkMsgBox(nszFormat))
|
|
return;
|
|
}
|
|
|
|
MessageBox((hwndAnimate ? hwndAnimate : ahwnd[iCurWindow].hwndParent), pszOutOfMemory, pszCaption, MSB_GUARANTEED);
|
|
|
|
if (wAction != wERRA_RETURN) {
|
|
Cleanup();
|
|
_exit(-1); // BAD! can we exit more gracefully?
|
|
}
|
|
}
|
|
|
|
/*******************
|
|
-
|
|
- Name: Error
|
|
*
|
|
* Purpose: Displays an error message
|
|
*
|
|
* Arguments: nError - string identifyer
|
|
* wAction - action to take after displaying the string. May be:
|
|
* wERRA_RETURN - Display message and return
|
|
* wERRA_DIE - Display message and kill app
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* REVIEW Note: We should probably revisit the way we determine what
|
|
* icons and modalities we use based on nError and wAction.
|
|
*
|
|
* Note: OOM uses SYSTEMMODAL and ICONHAND to guarantee display (no icon
|
|
* is actually displayed in this case).
|
|
* "Help unavailable during printer setup" uses SYSTEMMODAL on purpose.
|
|
* If wAction is DIE, we use system modal to prevent another
|
|
* help request which could blow away this message box and try to
|
|
* carry on.
|
|
*
|
|
******************/
|
|
|
|
VOID STDCALL Error(int nError, int wAction)
|
|
{
|
|
int RealError = nError;
|
|
ASSERT(nError != wERRS_INTERNAL_ERROR);
|
|
|
|
if (nError == wERRS_BADFILE || nError == wERRS_OLDFILE ||
|
|
nError == wERRS_ADVISOR_FILE) {
|
|
|
|
// If we were invoked simply by specifying a filename, and that filename
|
|
// is bad, then we should exit.
|
|
|
|
if (fNoSwitches)
|
|
QuitHelp();
|
|
return; // this error will already have been reported to the user
|
|
}
|
|
|
|
if (fSequence == 5 || fSequence == 6) {
|
|
char szMsg[512];
|
|
HBT hbtCntJump;
|
|
HBT hbtCntText = HbtOpenBtreeSz(txtCntText, hfsGid, fFSOpenReadOnly);
|
|
ASSERT(hbtCntText);
|
|
if (!hbtCntText)
|
|
goto UhOh;
|
|
|
|
GetStringResource2(wERRS_BAD_CNT, szMsg);
|
|
dwSequence--;
|
|
RcLookupByKey(hbtCntText,
|
|
(KEY) (LPVOID) &dwSequence,
|
|
NULL, szMsg + strlen(szMsg));
|
|
RcCloseBtreeHbt(hbtCntText);
|
|
strcat(szMsg, "\042\r\n\r\n");
|
|
|
|
hbtCntJump = HbtOpenBtreeSz(txtCntJump, hfsGid, fFSOpenReadOnly);
|
|
ASSERT(hbtCntJump);
|
|
RcLookupByKey(hbtCntText,
|
|
(KEY) (LPVOID) &dwSequence,
|
|
NULL, szMsg + strlen(szMsg));
|
|
RcCloseBtreeHbt(hbtCntJump);
|
|
|
|
dwSequence++;
|
|
ErrorQch(szMsg);
|
|
return;
|
|
}
|
|
|
|
UhOh:
|
|
if (!fHelpAuthor && nError >= FIRST_AUTHOR_BUG && nError <= LAST_AUTHOR_BUG )
|
|
nError = wERRS_HELPAUTHORBUG;
|
|
|
|
ErrorHwnd((hwndAnimate ? hwndAnimate : ahwnd[iCurWindow].hwndParent), nError, wAction, RealError);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: ErrorQch
|
|
-
|
|
* Purpose: Displays standard WinHelp error message dialog based
|
|
* the string passed.
|
|
*
|
|
* Arguments: qch - string to display
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* Globals Used: ahwnd[iCurWindow].hwndParent - main window handle
|
|
* pszCaption - main help caption
|
|
*
|
|
* Notes: Used by
|
|
*
|
|
***************************************************************************/
|
|
|
|
VOID STDCALL ErrorQch(LPCSTR qch)
|
|
{
|
|
/*
|
|
* In some cases, we will have already reported an error, but the
|
|
* original caller of the routine that may have generated the error won't
|
|
* know that. So, the routine being called can supress the caller's error
|
|
* message by setting the fSupressNextError flag.
|
|
*/
|
|
|
|
if (fSupressNextError) {
|
|
fSupressNextError = FALSE;
|
|
return;
|
|
}
|
|
|
|
if (!fSupressErrors)
|
|
OkMsgBox(qch);
|
|
}
|
|
|
|
void STDCALL CloseHelp(void)
|
|
{
|
|
fNoHide = TRUE;
|
|
PostMessage(ahwnd[MAIN_HWND].hwndParent, WM_CLOSE, 0, 0L);
|
|
}
|
|
|
|
/***************************************************************************
|
|
-
|
|
- Name: Cleanup
|
|
*
|
|
* Purpose: Get rid of things that might cause trouble if we exited.
|
|
* This includes: DCs, open files, GDI objects.
|
|
*
|
|
* Arguments: none
|
|
* Returns: none
|
|
*
|
|
***************************************************************************/
|
|
|
|
void STDCALL Cleanup(void)
|
|
{
|
|
HDE hde;
|
|
QDE qde;
|
|
|
|
if ((hde = HdeGetEnv()) != NULL) {
|
|
qde = QdeFromGh(hde);
|
|
|
|
if (qde->hdc != NULL) {
|
|
|
|
/*
|
|
* If we ReleaseDC before we SetHDC, SetHDC will fail, because
|
|
* even if we are setting it to null, the preexisting non-zero,
|
|
* but released, ds may be accessed to release fonts.
|
|
*/
|
|
|
|
HDC hdc = qde->hdc;
|
|
|
|
SetHDC(hde, NULL);
|
|
ReleaseDC(qde->hwnd, hdc);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* What about fonts, pens, brushes? Assume all clean except what gets
|
|
* cleaned up in normal WM_DESTROY processing in main window.
|
|
*/
|
|
|
|
DestroyWindow(ahwnd[MAIN_HWND].hwndParent);
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: AuthorMsg
|
|
|
|
PURPOSE: Displays a message only if "Help Author = 1" is in win.ini
|
|
|
|
PARAMETERS:
|
|
pszMsg
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
29-Oct-1993 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL AuthorMsg(PCSTR pszMsg, HWND hwnd)
|
|
{
|
|
if (fHelpAuthor)
|
|
OkMsgBox(pszMsg);
|
|
}
|