609 lines
12 KiB
C++
609 lines
12 KiB
C++
/*++
|
||
|
||
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
|
||
|