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.
608 lines
12 KiB
608 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
custerr.cxx
|
|
|
|
Abstract:
|
|
|
|
Custom Error Utility
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 04-Sep-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
#define TEST_HRESULT(api,hr,fatal) \
|
|
if( FAILED(hr) ) { \
|
|
\
|
|
wprintf( \
|
|
L"%S:%lu failed, error %lx %S\n", \
|
|
(api), \
|
|
__LINE__, \
|
|
(result), \
|
|
(fatal) \
|
|
? "ABORTING" \
|
|
: "CONTINUING" \
|
|
); \
|
|
\
|
|
if( fatal ) { \
|
|
\
|
|
goto cleanup; \
|
|
\
|
|
} \
|
|
\
|
|
} else
|
|
|
|
#define ALLOC( cb ) (PVOID)LocalAlloc( LPTR, (cb) )
|
|
#define FREE( ptr ) (VOID)LocalFree( (HLOCAL)(ptr) )
|
|
|
|
|
|
//
|
|
// Private types.
|
|
//
|
|
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
VOID
|
|
Usage(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetCustomError(
|
|
IMSAdminBase * AdmCom,
|
|
LPWSTR MetaPath,
|
|
LPWSTR FileName
|
|
);
|
|
|
|
VOID
|
|
DumpCustomError(
|
|
IMSAdminBase * AdmCom,
|
|
LPWSTR MetaPath
|
|
);
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
INT
|
|
__cdecl
|
|
wmain(
|
|
INT argc,
|
|
LPWSTR argv[]
|
|
)
|
|
{
|
|
|
|
HRESULT result;
|
|
IMSAdminBase * admCom;
|
|
LPWSTR metaPath;
|
|
LPWSTR fileName;
|
|
LPWSTR arg;
|
|
INT i;
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
admCom = NULL;
|
|
|
|
//
|
|
// Establish defaults.
|
|
//
|
|
|
|
metaPath = L"w3svc";
|
|
fileName = NULL;
|
|
|
|
//
|
|
// Validate the command line arguments.
|
|
//
|
|
|
|
for( i = 1 ; i < argc ; i++ ) {
|
|
arg = argv[i];
|
|
|
|
if( arg[0] != L'-' ||
|
|
arg[1] == L'\0' ||
|
|
arg[2] != L':' ||
|
|
arg[3] == L'\0' ) {
|
|
Usage();
|
|
return 1;
|
|
}
|
|
|
|
switch( arg[1] ) {
|
|
case L'h' :
|
|
case L'H' :
|
|
case L'?' :
|
|
Usage();
|
|
return 1;
|
|
|
|
case L'p' :
|
|
case L'P' :
|
|
metaPath = arg + 3;
|
|
break;
|
|
|
|
case L'f' :
|
|
case L'F' :
|
|
fileName = arg + 3;
|
|
break;
|
|
|
|
default :
|
|
Usage();
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize COM.
|
|
//
|
|
|
|
result = CoInitializeEx(
|
|
NULL,
|
|
COINIT_MULTITHREADED
|
|
);
|
|
|
|
TEST_HRESULT( "CoInitializeEx()", result, TRUE );
|
|
|
|
//
|
|
// Get the admin object.
|
|
//
|
|
|
|
result = MdGetAdminObject( &admCom );
|
|
|
|
TEST_HRESULT( "MdGetAdminObject()", result, TRUE );
|
|
|
|
//
|
|
// Do it.
|
|
//
|
|
|
|
if( fileName == NULL ) {
|
|
DumpCustomError( admCom, metaPath );
|
|
} else {
|
|
SetCustomError( admCom, metaPath, fileName );
|
|
}
|
|
|
|
cleanup:
|
|
|
|
//
|
|
// Release the admin object.
|
|
//
|
|
|
|
if( admCom != NULL ) {
|
|
|
|
result = MdReleaseAdminObject( admCom );
|
|
TEST_HRESULT( "MdReleaseAdminObject()", result, FALSE );
|
|
|
|
}
|
|
|
|
//
|
|
// Shutdown COM.
|
|
//
|
|
|
|
CoUninitialize();
|
|
return 0;
|
|
|
|
} // main
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
VOID
|
|
Usage(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
wprintf(
|
|
L"use: custerr [options]\n"
|
|
L"\n"
|
|
L"valid options are:\n"
|
|
L"\n"
|
|
L" -p:meta_path\n"
|
|
L" -f:error_file\n"
|
|
L"\n"
|
|
);
|
|
|
|
} // Usage
|
|
|
|
VOID
|
|
SetCustomError(
|
|
IMSAdminBase * AdmCom,
|
|
LPWSTR MetaPath,
|
|
LPWSTR FileName
|
|
)
|
|
{
|
|
|
|
HANDLE fileHandle;
|
|
DWORD length;
|
|
DWORD lengthHigh;
|
|
DWORD bytesRemaining;
|
|
HANDLE mappingHandle;
|
|
PCHAR view;
|
|
PCHAR viewScan;
|
|
PWCHAR multiSz;
|
|
PWCHAR multiSzScan;
|
|
HRESULT result;
|
|
BOOL gotOne;
|
|
METADATA_HANDLE metaHandle;
|
|
METADATA_RECORD metaRecord;
|
|
DWORD err;
|
|
CHAR ansiFileName[MAX_PATH];
|
|
WCHAR fullMetaPath[MAX_PATH];
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
fileHandle = INVALID_HANDLE_VALUE;
|
|
mappingHandle = NULL;
|
|
view = NULL;
|
|
multiSz = NULL;
|
|
metaHandle = 0;
|
|
|
|
//
|
|
// Open the file, get its length.
|
|
//
|
|
|
|
sprintf(
|
|
ansiFileName,
|
|
"%S",
|
|
FileName
|
|
);
|
|
|
|
fileHandle = CreateFileA(
|
|
ansiFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if( fileHandle == INVALID_HANDLE_VALUE ) {
|
|
err = GetLastError();
|
|
wprintf(
|
|
L"custerr: cannot open %s, error %lu\n",
|
|
FileName,
|
|
err
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
length = GetFileSize( fileHandle, &lengthHigh );
|
|
|
|
if( length == 0xFFFFFFFF || lengthHigh > 0 ) {
|
|
err = GetLastError();
|
|
wprintf(
|
|
L"custerr: cannot read %s, error %lu\n",
|
|
FileName,
|
|
err
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Map it in.
|
|
//
|
|
|
|
mappingHandle = CreateFileMapping(
|
|
fileHandle,
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if( mappingHandle == NULL ) {
|
|
err = GetLastError();
|
|
wprintf(
|
|
L"custerr: cannot read %s, error %lu\n",
|
|
FileName,
|
|
err
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
view = (PCHAR)MapViewOfFile(
|
|
mappingHandle,
|
|
FILE_MAP_READ,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if( view == NULL ) {
|
|
err = GetLastError();
|
|
wprintf(
|
|
L"custerr: cannot read %s, error %lu\n",
|
|
FileName,
|
|
err
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Allocate the multisz buffer. Assume it will be roughly the same
|
|
// size as the file.
|
|
//
|
|
|
|
multiSz = (PWCHAR) ALLOC( length * sizeof(WCHAR) );
|
|
|
|
if( multiSz == NULL ) {
|
|
wprintf(
|
|
L"custerr: not enough memory\n"
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Build the multisz.
|
|
//
|
|
|
|
viewScan = view;
|
|
multiSzScan = multiSz;
|
|
bytesRemaining = length;
|
|
|
|
while( bytesRemaining > 0 ) {
|
|
|
|
//
|
|
// Skip leading whitespace.
|
|
//
|
|
|
|
while( bytesRemaining > 0 &&
|
|
( *viewScan == ' ' || *viewScan == '\t' ||
|
|
*viewScan == '\r' || *viewScan == '\n' ) ) {
|
|
bytesRemaining--;
|
|
viewScan++;
|
|
}
|
|
|
|
//
|
|
// Copy it over, collapse embedded whitespace, perform
|
|
// cheesy ANSI-to-UNICODE conversion.
|
|
//
|
|
|
|
gotOne = FALSE;
|
|
|
|
while( bytesRemaining > 0 &&
|
|
( *viewScan != '\r' && *viewScan != '\n' ) ) {
|
|
bytesRemaining--;
|
|
if( *viewScan != ' ' && *viewScan != '\t' ) {
|
|
*multiSzScan++ = (WCHAR)*viewScan;
|
|
gotOne = TRUE;
|
|
}
|
|
viewScan++;
|
|
}
|
|
|
|
if( gotOne ) {
|
|
*multiSzScan++ = L'\0';
|
|
}
|
|
|
|
}
|
|
|
|
*multiSzScan++ = L'\0';
|
|
|
|
//
|
|
// Open the metabase.
|
|
//
|
|
|
|
swprintf(
|
|
fullMetaPath,
|
|
L"/%S/%s",
|
|
IIS_MD_LOCAL_MACHINE_PATH,
|
|
MetaPath
|
|
);
|
|
|
|
result = AdmCom->OpenKey(
|
|
METADATA_MASTER_ROOT_HANDLE,
|
|
fullMetaPath,
|
|
METADATA_PERMISSION_WRITE,
|
|
METABASE_OPEN_TIMEOUT,
|
|
&metaHandle
|
|
);
|
|
|
|
TEST_HRESULT( "AdmCom->OpenKey()", result, TRUE );
|
|
|
|
//
|
|
// Write the new custom error value.
|
|
//
|
|
|
|
length = ( multiSzScan - multiSz ) * sizeof(WCHAR);
|
|
|
|
INITIALIZE_METADATA_RECORD(
|
|
&metaRecord,
|
|
MD_CUSTOM_ERROR,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_SERVER,
|
|
MULTISZ_METADATA,
|
|
length,
|
|
multiSz
|
|
);
|
|
|
|
result = AdmCom->SetData(
|
|
metaHandle,
|
|
L"",
|
|
&metaRecord
|
|
);
|
|
|
|
TEST_HRESULT( "AdmCom->SetData()", result, TRUE );
|
|
|
|
cleanup:
|
|
|
|
if( metaHandle != 0 ) {
|
|
AdmCom->CloseKey( metaHandle );
|
|
}
|
|
|
|
if( multiSz != NULL ) {
|
|
FREE( multiSz );
|
|
}
|
|
|
|
if( view != NULL ) {
|
|
UnmapViewOfFile( view );
|
|
}
|
|
|
|
if( mappingHandle != NULL ) {
|
|
CloseHandle( mappingHandle );
|
|
}
|
|
|
|
if( fileHandle != INVALID_HANDLE_VALUE ) {
|
|
CloseHandle( fileHandle );
|
|
}
|
|
|
|
} // SetCustomError
|
|
|
|
VOID
|
|
DumpCustomError(
|
|
IMSAdminBase * AdmCom,
|
|
LPWSTR MetaPath
|
|
)
|
|
{
|
|
|
|
|
|
HRESULT result;
|
|
METADATA_HANDLE metaHandle;
|
|
METADATA_RECORD metaRecord;
|
|
DWORD bytesRequired;
|
|
PWCHAR buffer;
|
|
PWCHAR bufferScan;
|
|
WCHAR fullMetaPath[MAX_PATH];
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
metaHandle = 0;
|
|
buffer = NULL;
|
|
|
|
//
|
|
// Open the metabase.
|
|
//
|
|
|
|
swprintf(
|
|
fullMetaPath,
|
|
L"/%S/%s",
|
|
IIS_MD_LOCAL_MACHINE_PATH,
|
|
MetaPath
|
|
);
|
|
|
|
result = AdmCom->OpenKey(
|
|
METADATA_MASTER_ROOT_HANDLE,
|
|
fullMetaPath,
|
|
METADATA_PERMISSION_READ,
|
|
METABASE_OPEN_TIMEOUT,
|
|
&metaHandle
|
|
);
|
|
|
|
TEST_HRESULT( "AdmCom->OpenKey()", result, TRUE );
|
|
|
|
//
|
|
// Get the data size.
|
|
//
|
|
|
|
INITIALIZE_METADATA_RECORD(
|
|
&metaRecord,
|
|
MD_CUSTOM_ERROR,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_SERVER,
|
|
MULTISZ_METADATA,
|
|
2,
|
|
L""
|
|
);
|
|
|
|
result = AdmCom->GetData(
|
|
metaHandle,
|
|
L"",
|
|
&metaRecord,
|
|
&bytesRequired
|
|
);
|
|
|
|
if( result != RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) ) {
|
|
TEST_HRESULT( "AdmCom->GetData()", result, TRUE );
|
|
}
|
|
|
|
//
|
|
// Allocate our data buffer.
|
|
//
|
|
|
|
buffer = (PWCHAR)ALLOC( bytesRequired );
|
|
|
|
if( buffer == NULL ) {
|
|
wprintf(
|
|
L"custerr: not enough memory\n"
|
|
);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Now actually read it.
|
|
//
|
|
|
|
INITIALIZE_METADATA_RECORD(
|
|
&metaRecord,
|
|
MD_CUSTOM_ERROR,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_SERVER,
|
|
MULTISZ_METADATA,
|
|
bytesRequired,
|
|
buffer
|
|
);
|
|
|
|
result = AdmCom->GetData(
|
|
metaHandle,
|
|
L"",
|
|
&metaRecord,
|
|
&bytesRequired
|
|
);
|
|
|
|
TEST_HRESULT( "AdmCom->GetData()", result, TRUE );
|
|
|
|
//
|
|
// Print it.
|
|
//
|
|
|
|
bufferScan = buffer;
|
|
|
|
while( *bufferScan != L'\0' ) {
|
|
wprintf( L"%s\n", bufferScan );
|
|
bufferScan += wcslen( bufferScan ) + 1;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if( buffer != NULL ) {
|
|
FREE( buffer );
|
|
}
|
|
|
|
if( metaHandle != 0 ) {
|
|
AdmCom->CloseKey( metaHandle );
|
|
}
|
|
|
|
} // DumpCustomError
|
|
|