Source code of Windows XP (NT5)
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

/*++
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