803 lines
25 KiB
C++
803 lines
25 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 2000.
|
|
//
|
|
// File: errormsg.cxx
|
|
//
|
|
// Contents: Error messages for output/running queries
|
|
//
|
|
// History: 96/Mar/3 DwightKr Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#define ERROR_MESSAGE_SIZE 512
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetErrorPageNoThrow - public
|
|
//
|
|
// Synposis: Generates an error page based on the error parameters passed.
|
|
//
|
|
// Arguments: [eErrorClass] - class of error (IDQ, HTX, restirction, etc)
|
|
// [status] - error code generated
|
|
// [ulErrorLine] - line on which the error occured
|
|
// [wcsErrorFileName] - name of file which generated the error
|
|
// [pVariableSet] - replaceable parameters which generated the error
|
|
// [pOutputFormat] - format of dates & numbers
|
|
// [locale] - locale of the browser
|
|
// [webServer] - the web server
|
|
// [vString] - virtual string to contain error code
|
|
//
|
|
// History: 96/Feb/29 DwightKr Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void GetErrorPageNoThrow(
|
|
int eErrorClass,
|
|
NTSTATUS status,
|
|
ULONG ulErrorLine,
|
|
WCHAR const * wcsErrorFileName,
|
|
CVariableSet * pVariableSet,
|
|
COutputFormat * pOutputFormat,
|
|
LCID locale,
|
|
CWebServer & webServer,
|
|
CVirtualString & vString )
|
|
{
|
|
//
|
|
// If the error was caused by a failure to WRITE to the web server,
|
|
// then don't bother trying to report an error, there is no one to
|
|
// receive it.
|
|
//
|
|
if ( eWebServerWriteError == eErrorClass )
|
|
{
|
|
ciGibDebugOut(( DEB_IWARN, "Failed to write to the web server" ));
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If the error was the result of an access denied problem, then simply
|
|
// return a 401 error to the browser
|
|
//
|
|
|
|
WCHAR awcsErrorMessage[ERROR_MESSAGE_SIZE];
|
|
WCHAR * pwszErrorMessage = awcsErrorMessage;
|
|
ULONG cchAvailMessage = ERROR_MESSAGE_SIZE;
|
|
|
|
//
|
|
// Generate the Win32 error code by removing the facility code (7) and
|
|
// the error bit.
|
|
//
|
|
ULONG Win32status = status;
|
|
if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
|
|
{
|
|
Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
|
|
}
|
|
|
|
if ( (STATUS_ACCESS_DENIED == status) ||
|
|
(STATUS_NETWORK_ACCESS_DENIED == status) ||
|
|
(ERROR_ACCESS_DENIED == Win32status) ||
|
|
(ERROR_INVALID_ACCESS == Win32status) ||
|
|
(ERROR_NETWORK_ACCESS_DENIED == Win32status)
|
|
)
|
|
{
|
|
ciGibDebugOut(( DEB_WARN, "mapping 0x%x to 401 access denied\n", status ));
|
|
|
|
ReturnServerError( HTTP_STATUS_DENIED, webServer );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Map special error codes to their message equivalents.
|
|
//
|
|
if ( QUERY_E_DUPLICATE_OUTPUT_COLUMN == status )
|
|
{
|
|
status = MSG_CI_IDQ_DUPLICATE_COLUMN;
|
|
}
|
|
else if ( QUERY_E_INVALID_OUTPUT_COLUMN == status )
|
|
{
|
|
status = MSG_CI_IDQ_NO_SUCH_COLUMN_PROPERTY;
|
|
}
|
|
|
|
if ( 0 != wcsErrorFileName )
|
|
{
|
|
WCHAR *p = wcsrchr( wcsErrorFileName, L'\\' );
|
|
if ( 0 == p )
|
|
p = wcsrchr( wcsErrorFileName, L'/' );
|
|
if ( 0 == p )
|
|
p = wcsrchr( wcsErrorFileName, L':' );
|
|
|
|
if ( 0 != p )
|
|
wcsErrorFileName = p + 1;
|
|
}
|
|
|
|
//
|
|
// Don't pass a specific lang id to FormatMessage since it will
|
|
// fail if there's no message in that language. Instead set
|
|
// the thread locale, which will get FormatMessage to use a search
|
|
// algorithm to find a message of the appropriate language or
|
|
// use a reasonable fallback msg if there's none.
|
|
//
|
|
LCID SaveLCID = GetThreadLocale();
|
|
SetThreadLocale(locale);
|
|
|
|
switch (eErrorClass)
|
|
{
|
|
case eIDQParseError:
|
|
{
|
|
//
|
|
// These are errors encountered while parsing the IDQ file
|
|
//
|
|
DWORD_PTR args [] = {
|
|
(DWORD_PTR) ulErrorLine,
|
|
(DWORD_PTR) wcsErrorFileName
|
|
};
|
|
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
GetModuleHandle(L"idq.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
(va_list *) args ) )
|
|
{
|
|
ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
|
|
|
|
swprintf( pwszErrorMessage,
|
|
L"Processing of IDQ file %ls failed with error 0x%x\n",
|
|
wcsErrorFileName,
|
|
status );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eIDQPlistError:
|
|
{
|
|
//
|
|
// These are errors encountered while parsing the [names] section
|
|
//
|
|
|
|
if (wcsErrorFileName != 0)
|
|
{
|
|
DWORD_PTR args [] = {
|
|
(DWORD_PTR) wcsErrorFileName,
|
|
(DWORD_PTR) ulErrorLine,
|
|
};
|
|
|
|
NTSTATUS MsgNum = MSG_IDQ_FILE_MESSAGE;
|
|
if (ulErrorLine != 0)
|
|
{
|
|
MsgNum = MSG_IDQ_FILE_LINE_MESSAGE;
|
|
}
|
|
|
|
ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
GetModuleHandle(L"idq.dll"),
|
|
MsgNum,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
(va_list *) args );
|
|
pwszErrorMessage += cchMsg;
|
|
cchAvailMessage -= cchMsg;
|
|
}
|
|
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
|
|
GetModuleHandle(L"query.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
0 ) )
|
|
{
|
|
ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
|
|
|
|
swprintf( pwszErrorMessage,
|
|
L"Processing of IDQ file [names] failed with error 0x%x\n",
|
|
status );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eHTXParseError:
|
|
{
|
|
//
|
|
// These are errors encountered while parsing the IDQ file
|
|
//
|
|
DWORD_PTR args [] = {
|
|
(DWORD_PTR) ulErrorLine,
|
|
(DWORD_PTR) wcsErrorFileName
|
|
};
|
|
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
GetModuleHandle(L"idq.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
(va_list *) args ) )
|
|
{
|
|
ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
|
|
|
|
swprintf( pwszErrorMessage,
|
|
L"Error 0x%x occured while parsing in HTX file %ls\n",
|
|
status,
|
|
wcsErrorFileName );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eRestrictionParseError:
|
|
{
|
|
//
|
|
// These are errors encountered while parsing the restriction
|
|
//
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
|
|
GetModuleHandle(L"query.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
0 ) )
|
|
{
|
|
ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
|
|
|
|
swprintf( pwszErrorMessage,
|
|
L"Restriction parsing failed with error 0x%x\n",
|
|
status );
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
//
|
|
// All other errors; other major classes of errors are caught above.
|
|
//
|
|
|
|
DWORD_PTR args [] = {
|
|
(DWORD_PTR) ulErrorLine,
|
|
(DWORD_PTR) wcsErrorFileName
|
|
};
|
|
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
GetModuleHandle(L"idq.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
(va_list *) args ) )
|
|
{
|
|
if (wcsErrorFileName != 0)
|
|
{
|
|
NTSTATUS MsgNum = MSG_IDQ_FILE_MESSAGE;
|
|
args[0] = (DWORD_PTR)wcsErrorFileName;
|
|
if (ulErrorLine != 0)
|
|
{
|
|
args[1] = ulErrorLine;
|
|
MsgNum = MSG_IDQ_FILE_LINE_MESSAGE;
|
|
}
|
|
|
|
ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
GetModuleHandle(L"idq.dll"),
|
|
MsgNum,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
(va_list *) args );
|
|
pwszErrorMessage += cchMsg;
|
|
cchAvailMessage -= cchMsg;
|
|
}
|
|
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
|
|
GetModuleHandle(L"query.dll"),
|
|
status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
0 ) )
|
|
{
|
|
//
|
|
// Try looking up the error in the Win32 list of error codes
|
|
//
|
|
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
|
|
GetModuleHandle(L"kernel32.dll"),
|
|
Win32status,
|
|
0,
|
|
pwszErrorMessage,
|
|
cchAvailMessage,
|
|
0 ) )
|
|
{
|
|
ciGibDebugOut(( DEB_ERROR,
|
|
"Format message failed with error 0x%x\n",
|
|
GetLastError() ));
|
|
|
|
swprintf( pwszErrorMessage,
|
|
L"Error 0x%x caught while processing query\n",
|
|
status );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
SetThreadLocale(SaveLCID);
|
|
|
|
BOOL fCaughtException = FALSE;
|
|
|
|
//
|
|
// Try to bind to language object by looking up registry and get
|
|
// the error message HTX file associated with this class of error.
|
|
//
|
|
TRY
|
|
{
|
|
CWebLangLocator langreg( locale );
|
|
|
|
WCHAR * wcsErrorFile = 0;
|
|
|
|
if ( langreg.LocaleFound() )
|
|
{
|
|
//
|
|
// If the locale was found in the registry, get the error message
|
|
// file associated with this language.
|
|
//
|
|
|
|
switch (eErrorClass)
|
|
{
|
|
case eIDQParseError:
|
|
case eIDQPlistError:
|
|
wcsErrorFile = langreg.GetIDQErrorFile();
|
|
break;
|
|
|
|
case eHTXParseError:
|
|
wcsErrorFile = langreg.GetHTXErrorFile();
|
|
break;
|
|
|
|
case eRestrictionParseError:
|
|
wcsErrorFile = langreg.GetRestrictionErrorFile();
|
|
break;
|
|
|
|
default:
|
|
wcsErrorFile = langreg.GetDefaultErrorFile();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ( 0 != pVariableSet ) &&
|
|
( 0 != pOutputFormat ) &&
|
|
( 0 != wcsErrorFile ) &&
|
|
( wcslen(wcsErrorFile) > 0 ) )
|
|
{
|
|
//
|
|
// Set CiErrorMessage and CiErrorNumber.
|
|
//
|
|
// The variables won't own the memory for the strings;
|
|
// the pointers will be reset later.
|
|
//
|
|
PROPVARIANT propVariant;
|
|
propVariant.vt = VT_LPWSTR;
|
|
propVariant.pwszVal = awcsErrorMessage;
|
|
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
|
|
&propVariant,
|
|
0 );
|
|
|
|
WCHAR achErrorNumber[11];
|
|
swprintf( achErrorNumber, L"0x%8x", status );
|
|
|
|
propVariant.pwszVal = achErrorNumber;
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
|
|
&propVariant,
|
|
0 );
|
|
|
|
WCHAR wcsPhysicalPath[_MAX_PATH];
|
|
ULONG cwcVirtualPath = wcslen(wcsErrorFile) + 1;
|
|
|
|
XPtrST<WCHAR> wcsVirtualPath( new WCHAR[cwcVirtualPath] );
|
|
|
|
//
|
|
// We could have a virtual root or a physical root
|
|
// All virtual roots begin with a "/".
|
|
//
|
|
|
|
if (wcsErrorFile[0] == L'/')
|
|
{
|
|
//
|
|
// Ask the web server to convert the virtual path to our error
|
|
// message file to a physical path.
|
|
//
|
|
webServer.GetPhysicalPath( wcsErrorFile, wcsPhysicalPath, _MAX_PATH );
|
|
|
|
RtlCopyMemory( wcsVirtualPath.GetPointer(),
|
|
wcsErrorFile,
|
|
cwcVirtualPath*sizeof(WCHAR) );
|
|
}
|
|
else
|
|
{
|
|
// simply copy the path to physical path. It has to be a physical
|
|
// path. If not, it will result in an error later.
|
|
|
|
wcscpy(wcsPhysicalPath, wcsErrorFile);
|
|
}
|
|
|
|
CSecurityIdentity securityStub;
|
|
|
|
CHTXFile htxFile( wcsVirtualPath,
|
|
pOutputFormat->CodePage(),
|
|
securityStub,
|
|
pOutputFormat->GetServerInstance() );
|
|
|
|
ciGibDebugOut((DEB_ITRACE, "File is: %ws\n", wcsPhysicalPath));
|
|
htxFile.ParseFile( wcsPhysicalPath, *pVariableSet, webServer );
|
|
htxFile.GetHeader( vString, *pVariableSet, *pOutputFormat );
|
|
}
|
|
else
|
|
{
|
|
vString.StrCat( L"<HTML>" );
|
|
HTMLEscapeW( awcsErrorMessage,
|
|
vString,
|
|
pOutputFormat->CodePage() );
|
|
}
|
|
}
|
|
CATCH ( CException, e )
|
|
{
|
|
fCaughtException = TRUE;
|
|
}
|
|
END_CATCH
|
|
|
|
TRY
|
|
{
|
|
// Extending the vstring can fail
|
|
|
|
if ( fCaughtException )
|
|
{
|
|
vString.StrCat( L"<HTML>" );
|
|
HTMLEscapeW( awcsErrorMessage,
|
|
vString,
|
|
pOutputFormat->CodePage() );
|
|
}
|
|
|
|
// These can fail if the variable wasn't set above
|
|
|
|
if ( pVariableSet )
|
|
{
|
|
PROPVARIANT propVariant;
|
|
propVariant.vt = VT_EMPTY;
|
|
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
|
|
&propVariant,
|
|
0 );
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
|
|
&propVariant,
|
|
0 );
|
|
}
|
|
}
|
|
CATCH ( CException, e )
|
|
{
|
|
// give up
|
|
}
|
|
END_CATCH
|
|
} //GetErrorPageNoThrow
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetErrorPageNoThrow - public
|
|
//
|
|
// Synposis: Generates an error page based on the error parameters passed.
|
|
// The error description is already available.
|
|
//
|
|
// Arguments: [scError] - error SCODE generated
|
|
// [pwszErrorMessage] - description provided by ole-db error mechanism
|
|
// [pVariableSet] - replaceable parameters which generated the error
|
|
// [pOutputFormat] - format of dates & numbers
|
|
// [locale] - locale of the browser
|
|
// [webServer] - the web server
|
|
// [vString] - virtual string to contain error code
|
|
//
|
|
// History: 08-May-97 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void GetErrorPageNoThrow( int eErrorClass,
|
|
SCODE scError,
|
|
WCHAR const * pwszErrorMessage,
|
|
CVariableSet * pVariableSet,
|
|
COutputFormat * pOutputFormat,
|
|
LCID locale,
|
|
CWebServer & webServer,
|
|
CVirtualString & vString
|
|
)
|
|
{
|
|
BOOL fCaughtException = FALSE;
|
|
|
|
//
|
|
// Try to bind to language object by looking up registry and get
|
|
// the error message HTX file associated with this class of error.
|
|
//
|
|
TRY
|
|
{
|
|
//
|
|
// If the error was the result of an access denied problem, then simply
|
|
// return a 401 error to the browser
|
|
//
|
|
|
|
//
|
|
// Generate the Win32 error code by removing the facility code (7) and
|
|
// the error bit.
|
|
//
|
|
ULONG Win32status = scError;
|
|
if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
|
|
{
|
|
Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
|
|
}
|
|
|
|
|
|
if ( (STATUS_ACCESS_DENIED == scError) ||
|
|
(STATUS_NETWORK_ACCESS_DENIED == scError) ||
|
|
(ERROR_ACCESS_DENIED == Win32status) ||
|
|
(ERROR_INVALID_ACCESS == Win32status) ||
|
|
(ERROR_NETWORK_ACCESS_DENIED == Win32status)
|
|
)
|
|
{
|
|
ciGibDebugOut(( DEB_WARN, "mapping 0x%x to 401 access denied\n", scError ));
|
|
|
|
ReturnServerError( HTTP_STATUS_DENIED, webServer );
|
|
return;
|
|
}
|
|
|
|
CWebLangLocator langreg( locale );
|
|
|
|
WCHAR * wcsErrorFile = 0;
|
|
|
|
if ( langreg.LocaleFound() )
|
|
{
|
|
//
|
|
// If the locale was found in the registry, get the error message
|
|
// file associated with this language.
|
|
//
|
|
|
|
switch (eErrorClass)
|
|
{
|
|
case eIDQParseError:
|
|
case eIDQPlistError:
|
|
wcsErrorFile = langreg.GetIDQErrorFile();
|
|
break;
|
|
|
|
case eHTXParseError:
|
|
wcsErrorFile = langreg.GetHTXErrorFile();
|
|
break;
|
|
|
|
case eRestrictionParseError:
|
|
wcsErrorFile = langreg.GetRestrictionErrorFile();
|
|
break;
|
|
|
|
default:
|
|
wcsErrorFile = langreg.GetDefaultErrorFile();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ( 0 != pVariableSet ) &&
|
|
( 0 != pOutputFormat ) &&
|
|
( 0 != wcsErrorFile ) &&
|
|
( wcslen(wcsErrorFile) > 0 ) )
|
|
{
|
|
//
|
|
// Set CiErrorMessage and CiErrorNumber.
|
|
//
|
|
// The variables won't own the memory for the strings;
|
|
// the pointers will be reset later.
|
|
//
|
|
PROPVARIANT propVariant;
|
|
propVariant.vt = VT_LPWSTR;
|
|
propVariant.pwszVal = (LPWSTR)pwszErrorMessage;
|
|
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
|
|
&propVariant,
|
|
0 );
|
|
|
|
WCHAR achErrorNumber[11];
|
|
swprintf( achErrorNumber, L"0x%8x", scError );
|
|
|
|
propVariant.pwszVal = achErrorNumber;
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
|
|
&propVariant,
|
|
0 );
|
|
|
|
WCHAR wcsPhysicalPath[_MAX_PATH];
|
|
ULONG cwcVirtualPath = wcslen(wcsErrorFile) + 1;
|
|
|
|
XPtrST<WCHAR> wcsVirtualPath( new WCHAR[cwcVirtualPath] );
|
|
|
|
//
|
|
// We could have a virtual root or a physical root
|
|
// All virtual roots begin with a "/".
|
|
//
|
|
|
|
if (wcsErrorFile[0] == L'/')
|
|
{
|
|
//
|
|
// Ask the web server to convert the virtual path to our error
|
|
// message file to a physical path.
|
|
//
|
|
webServer.GetPhysicalPath( wcsErrorFile, wcsPhysicalPath, _MAX_PATH );
|
|
|
|
RtlCopyMemory( wcsVirtualPath.GetPointer(),
|
|
wcsErrorFile,
|
|
cwcVirtualPath*sizeof(WCHAR) );
|
|
}
|
|
else
|
|
{
|
|
// simply copy the path to physical path. It has to be a physical
|
|
// path. If not, it will result in an error later.
|
|
|
|
wcscpy(wcsPhysicalPath, wcsErrorFile);
|
|
}
|
|
|
|
|
|
|
|
CSecurityIdentity securityStub;
|
|
|
|
CHTXFile htxFile( wcsVirtualPath,
|
|
pOutputFormat->CodePage(),
|
|
securityStub,
|
|
pOutputFormat->GetServerInstance() );
|
|
|
|
ciGibDebugOut((DEB_ITRACE, "File is: %ws\n", wcsPhysicalPath));
|
|
htxFile.ParseFile( wcsPhysicalPath, *pVariableSet, webServer );
|
|
htxFile.GetHeader( vString, *pVariableSet, *pOutputFormat );
|
|
}
|
|
else
|
|
{
|
|
vString.StrCat( L"<HTML>" );
|
|
vString.StrCat( pwszErrorMessage );
|
|
}
|
|
}
|
|
CATCH ( CException, e )
|
|
{
|
|
fCaughtException = TRUE;
|
|
}
|
|
END_CATCH
|
|
|
|
TRY
|
|
{
|
|
// Extending the vstring can fail
|
|
|
|
if ( fCaughtException )
|
|
{
|
|
vString.StrCat( L"<HTML>" );
|
|
vString.StrCat( pwszErrorMessage );
|
|
}
|
|
|
|
// These can fail if the variable wasn't set above
|
|
|
|
if ( pVariableSet )
|
|
{
|
|
PROPVARIANT propVariant;
|
|
propVariant.vt = VT_EMPTY;
|
|
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
|
|
&propVariant,
|
|
0 );
|
|
pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
|
|
&propVariant,
|
|
0 );
|
|
}
|
|
}
|
|
CATCH ( CException, e )
|
|
{
|
|
// give up
|
|
}
|
|
END_CATCH
|
|
} //GetErrorPageNoThrow
|
|
|
|
|
|
enum
|
|
{
|
|
eAccessDeniedMsg = 0,
|
|
eServerBusyMsg,
|
|
eServerErrorMsg,
|
|
};
|
|
|
|
#define MAX_SERVER_ERROR_MSGSIZE 100
|
|
|
|
WCHAR g_awszServerErrorMsgs [3] [MAX_SERVER_ERROR_MSGSIZE] =
|
|
{
|
|
L"Access denied.\r\n",
|
|
L"Server too busy.\r\n",
|
|
L"Unexpected server error.\r\n",
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReturnServerError - public
|
|
//
|
|
// Synposis: Generates an error page for an HTTP error code.
|
|
//
|
|
// Arguments: [httpError] - the HTTP status code
|
|
// [webServer] - the web server
|
|
//
|
|
// Notes: This is used when the server is too busy; it should be a
|
|
// very low-overhead path.
|
|
//
|
|
// History: 12 Aug 1997 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void ReturnServerError( ULONG httpError,
|
|
CWebServer & webServer )
|
|
{
|
|
char const * pszHeader = "";
|
|
int iMessage = 0;
|
|
|
|
switch (httpError)
|
|
{
|
|
case HTTP_STATUS_DENIED:
|
|
pszHeader = "401 Access denied";
|
|
iMessage = eAccessDeniedMsg;
|
|
break;
|
|
|
|
case HTTP_STATUS_SERVICE_UNAVAIL:
|
|
pszHeader = "503 Server busy";
|
|
iMessage = eServerBusyMsg;
|
|
break;
|
|
|
|
default:
|
|
ciGibDebugOut(( DEB_ERROR, "unexpected server error status %d\n", httpError ));
|
|
httpError = HTTP_STATUS_SERVER_ERROR;
|
|
iMessage = eServerErrorMsg;
|
|
break;
|
|
}
|
|
|
|
webServer.WriteHeader( 0, pszHeader );
|
|
|
|
WCHAR * pwszMessage = g_awszServerErrorMsgs[iMessage];
|
|
webServer.WriteClient( pwszMessage );
|
|
webServer.SetHttpStatus( httpError );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LoadServerErrors - public
|
|
//
|
|
// Synposis: Load messages for server errors.
|
|
//
|
|
// Arguments: -NONE-
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 29 Sep 1997 AlanW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void LoadServerErrors( )
|
|
{
|
|
unsigned iMessage = eAccessDeniedMsg;
|
|
SCODE scMessage = MSG_CI_ACCESS_DENIED;
|
|
const unsigned cMessages = sizeof g_awszServerErrorMsgs /
|
|
sizeof g_awszServerErrorMsgs[0];
|
|
|
|
|
|
while (iMessage < cMessages)
|
|
{
|
|
FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
|
|
GetModuleHandle(L"idq.dll"),
|
|
scMessage,
|
|
GetSystemDefaultLangID(),
|
|
&g_awszServerErrorMsgs [iMessage][0],
|
|
MAX_SERVER_ERROR_MSGSIZE,
|
|
0 );
|
|
scMessage++;
|
|
iMessage++;
|
|
}
|
|
}
|