|
|
#include <windows.h>
#include <stdio.h>
#include <resapi.h>
#include <clusapi.h>
#include <clusstor.h>
#define MAX_NAME_SIZE MAX_PATH
#define START_BUFFER_SIZE 2048
#define PHYSICAL_DISK_WSTR L"Physical Disk"
//
// Always specify the fully qualified path name to the DLL.
//
#define MODULE_NAME_VALID "%SystemRoot%\\cluster\\passthru.dll"
#define PROC_EXCEPTION "TestDllCauseException"
#define PROC_GET_BOOT_SECTOR "TestDllGetBootSector"
#define PROC_CONTEXT_AS_ERROR "TestDllReturnContextAsError"
#define PROC_NOT_ENOUGH_PARMS "TestDllNotEnoughParms"
#define PROC_TOO_MANY_PARMS "TestDllTooManyParms"
// 6118L ERROR_NO_BROWSER_SERVERS_FOUND
#define CONTEXT_ERROR_STR "6118"
#define MODULE_NAME_INVALID "NoSuchModule.dll"
#define PROC_NAME_INVALID "NoSuchProc"
#define MAX_OUT_BUFFER_SIZE 2048
#define BOOT_SECTOR_SIZE 512
// Specfic ASR tests
#define ASRP_GET_LOCAL_DISK_INFO "AsrpGetLocalDiskInfo"
#define ASRP_GET_LOCAL_VOLUME_INFO "AsrpGetLocalVolumeInfo"
#define SYSSETUP_DLL "syssetup.dll"
//
// Use this to verify the parse routine.
//
// #define TEST_PARSE_ROUTINE 11
typedef struct _RESOURCE_STATE { CLUSTER_RESOURCE_STATE State; LPWSTR ResNodeName; LPWSTR ResGroupName; } RESOURCE_STATE, *PRESOURCE_STATE;
VOID DumpBuffer( IN PUCHAR Buffer, IN DWORD ByteCount );
DWORD GetResourceInfo( RESOURCE_HANDLE hOriginal, RESOURCE_HANDLE hResource, PVOID lpParams );
DWORD GetResourceState( HRESOURCE Resource, PRESOURCE_STATE ResState );
DWORD GetSignature( RESOURCE_HANDLE hResource, DWORD *dwSignature );
BOOLEAN GetSignatureFromDiskInfo( PBYTE DiskInfo, DWORD *Signature, DWORD DiskInfoSize );
LPBYTE ParseDiskInfo( PBYTE DiskInfo, DWORD DiskInfoSize, DWORD SyntaxValue );
VOID PrintError( DWORD ErrorCode );
DWORD ResourceCallback( RESOURCE_HANDLE hOriginal, RESOURCE_HANDLE hResource, PVOID lpParams );
CLUSTER_RESOURCE_STATE WINAPI WrapGetClusterResourceState( IN HRESOURCE hResource, OUT OPTIONAL LPWSTR * ppwszNodeName, OUT OPTIONAL LPWSTR * ppwszGroupName );
DWORD WrapClusterResourceControl( RESOURCE_HANDLE hResource, DWORD dwControlCode, LPVOID *ppwszOutBuffer, DWORD *dwBytesReturned );
DWORD __cdecl main( int argc, char *argv[] )
{ DWORD dwStatus = NO_ERROR;
//
// No parameter validation...
//
dwStatus = ResUtilEnumResources( NULL, PHYSICAL_DISK_WSTR, ResourceCallback, NULL );
if ( NO_ERROR != dwStatus ) { printf("\nResUtilEnumResources returns: %d \n", dwStatus); PrintError(dwStatus); }
return dwStatus;
} // main
DWORD ResourceCallback( RESOURCE_HANDLE hOriginal, RESOURCE_HANDLE hResource, PVOID lpParams ) { PCHAR outBuffer = NULL;
DWORD dwStatus = NO_ERROR;
DWORD inBufferSize = sizeof(DISK_DLL_EXTENSION_INFO); DWORD outBufferSize = MAX_OUT_BUFFER_SIZE; DWORD bytesReturned;
DISK_DLL_EXTENSION_INFO inBuffer;
// printf("hOriginal 0x%x hResource 0x%x lpParams 0x%x \n", hOriginal, hResource, lpParams);
//
// Demonstrate how to get various resource info.
//
dwStatus = GetResourceInfo( hOriginal, hResource, lpParams );
//////////////////////////////////////////////////////////////////////////
//
// Demonstrate calling into the disk extension DLL.
//
//////////////////////////////////////////////////////////////////////////
printf("\nStarting disk extension DLL tests \n");
outBuffer = LocalAlloc( LPTR, outBufferSize );
if ( !outBuffer ) {
dwStatus = GetLastError(); goto FnExit; }
//////////////////////////////////////////////////////////////////////////
//
// Buffer verification tests
//
//////////////////////////////////////////////////////////////////////////
//
// No input buffer - should fail.
//
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, NULL, // Error
inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("Input buffer missing: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//
// Incorrect input buffer size - should fail.
//
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, 28, // Error
outBuffer, outBufferSize, &bytesReturned );
printf("Input buffer size incorrect: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//
// Input buffer incorrect version - should fail.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) );
inBuffer.MajorVersion = NT4_MAJOR_VERSION; // Error
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("Input buffer version incorrect: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//
// No output buffer - should fail.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, NULL, // Error
outBufferSize, &bytesReturned );
printf("Output buffer missing: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//////////////////////////////////////////////////////////////////////////
//
// DLL verification tests
//
//////////////////////////////////////////////////////////////////////////
//
// Disk resource has hard-coded DLL name. A call with any invalid
// proc name will always fail.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION;
strncpy( inBuffer.DllModuleName, MODULE_NAME_INVALID, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_NAME_INVALID, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL name invalid: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//
// Valid ASR DLL, invalid proc name - should fail.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, SYSSETUP_DLL, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_NAME_INVALID, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL valid, Proc invalid: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
#if ALLOW_DLL_PARMS
//
// DLL procedure generates exception - should fail gracefully.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, MODULE_NAME_VALID, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_EXCEPTION, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL proc generates exception: %d (0x%x) [failure expected] \n", dwStatus, dwStatus); PrintError(dwStatus);
#if 0
//
// We can't protect against this type of error, so don't test it.
//
//
// DLL procedure has less parameters then we are calling - should fail gracefully.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, MODULE_NAME_VALID, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_NOT_ENOUGH_PARMS, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL proc doesn't support required number of parms: %d [failure expected] \n", dwStatus); PrintError(dwStatus);
//
// DLL procedure has more parameters then we are calling - should fail gracefully.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, MODULE_NAME_VALID, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_TOO_MANY_PARMS, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL proc supports more parms than expected: %d [failure expected] \n", dwStatus); PrintError(dwStatus); #endif
//
// DLL procedure returns error based on context.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, MODULE_NAME_VALID, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, PROC_CONTEXT_AS_ERROR, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 ); strncpy( inBuffer.ContextStr, CONTEXT_ERROR_STR, RTL_NUMBER_OF( inBuffer.ContextStr ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("DLL proc returns error based on context (%s) : %d [failure expected] \n", CONTEXT_ERROR_STR, dwStatus); PrintError(dwStatus);
#endif // ALLOW_DLL_PARMS
////////////////////////////////////
// Check: AsrpGetLocalDiskInfo
////////////////////////////////////
//
// Amount of data returned is larger than the buffer we specified. Should
// indicate an error and bytesReturned should show how many bytes we need.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, SYSSETUP_DLL, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, ASRP_GET_LOCAL_DISK_INFO, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, 1, &bytesReturned );
printf("Output buffer too small (bytes returned %d): %d [failure expected] \n", bytesReturned, dwStatus); PrintError(dwStatus);
if ( 0 == bytesReturned ) { printf("Bytes returned is zero, stopping. \n"); goto FnExit; }
if ( ERROR_MORE_DATA != dwStatus ) { printf("Unexpected status returned, stopping. \n"); goto FnExit; }
//
// This valid ASR routine should work.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) );
inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, SYSSETUP_DLL, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, ASRP_GET_LOCAL_DISK_INFO, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
LocalFree( outBuffer ); outBuffer = NULL;
outBufferSize = bytesReturned + 1; outBuffer = LocalAlloc( LPTR, outBufferSize );
if ( !outBuffer ) { dwStatus = GetLastError(); printf("Unable to allocate real buffer size %d bytes, error %d \n", outBufferSize, dwStatus); PrintError(dwStatus); goto FnExit; }
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("Returned buffer size %d (0x%x) and status %d [success expected] \n", bytesReturned, bytesReturned, dwStatus);
printf("\nDLL: %s Proc: %s \n\n", inBuffer.DllModuleName, inBuffer.DllProcName );
PrintError(dwStatus);
if ( NO_ERROR == dwStatus ) { DumpBuffer( outBuffer, bytesReturned ); }
////////////////////////////////////
// Check: AsrpGetLocalVolumeInfo
////////////////////////////////////
//
// Amount of data returned is larger than the buffer we specified. Should
// indicate an error and bytesReturned should show how many bytes we need.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) ); inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, SYSSETUP_DLL, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, ASRP_GET_LOCAL_VOLUME_INFO, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, 1, &bytesReturned );
printf("Output buffer too small (bytes returned %d): %d [failure expected] \n", bytesReturned, dwStatus); PrintError(dwStatus);
if ( 0 == bytesReturned ) { printf("Bytes returned is zero, stopping. \n"); goto FnExit; }
if ( ERROR_MORE_DATA != dwStatus ) { printf("Unexpected status returned, stopping. \n"); goto FnExit; }
//
// This valid ASR routine should work.
//
ZeroMemory( &inBuffer, sizeof(inBuffer) );
inBuffer.MajorVersion = NT5_MAJOR_VERSION; strncpy( inBuffer.DllModuleName, SYSSETUP_DLL, RTL_NUMBER_OF( inBuffer.DllModuleName ) - 1 ); strncpy( inBuffer.DllProcName, ASRP_GET_LOCAL_VOLUME_INFO, RTL_NUMBER_OF( inBuffer.DllProcName ) - 1 );
LocalFree( outBuffer ); outBuffer = NULL;
outBufferSize = bytesReturned + 1; outBuffer = LocalAlloc( LPTR, outBufferSize );
if ( !outBuffer ) { dwStatus = GetLastError(); printf("Unable to allocate real buffer size %d bytes, error %d \n", outBufferSize, dwStatus); PrintError(dwStatus); goto FnExit; }
dwStatus = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_STORAGE_DLL_EXTENSION, &inBuffer, inBufferSize, outBuffer, outBufferSize, &bytesReturned );
printf("Returned buffer size %d (0x%x) and status %d [success expected] \n", bytesReturned, bytesReturned, dwStatus);
printf("\nDLL: %s Proc: %s \n\n", inBuffer.DllModuleName, inBuffer.DllProcName );
PrintError(dwStatus);
if ( NO_ERROR == dwStatus ) { DumpBuffer( outBuffer, bytesReturned ); }
FnExit:
if ( outBuffer ) { LocalFree( outBuffer); }
//
// If you return any kind of error, the enumeration stops. Since we want to enumerate all
// the disks, always return success.
//
return NO_ERROR;
} // ResourceCallBack
DWORD GetResourceInfo( RESOURCE_HANDLE hOriginal, RESOURCE_HANDLE hResource, PVOID lpParams ) { DWORD dwSignature; DWORD dwStatus;
RESOURCE_STATE resState;
ZeroMemory( &resState, sizeof(RESOURCE_STATE) );
dwStatus = GetSignature( hResource, &dwSignature );
if ( NO_ERROR != dwStatus ) { printf("Unable to get signature: %d \n", dwStatus); PrintError(dwStatus); goto FnExit; }
dwStatus = GetResourceState( hResource, &resState );
if ( NO_ERROR != dwStatus ) { printf("Unable to get resource state: %d \n", dwStatus); PrintError(dwStatus); goto FnExit; }
printf("\n"); printf("Signature: %08X \n", dwSignature); printf("Node : %ws \n", resState.ResNodeName); printf("Group : %ws \n", resState.ResGroupName);
printf("Status : %08X - ", resState.State);
switch( resState.State ) { case ClusterResourceInherited: printf("Inherited"); break;
case ClusterResourceInitializing: printf("Initializing"); break;
case ClusterResourceOnline: printf("Online"); break;
case ClusterResourceOffline: printf("Offline"); break;
case ClusterResourceFailed: printf("Failed"); break;
case ClusterResourcePending: printf("Pending"); break;
case ClusterResourceOnlinePending: printf("Online Pending"); break;
case ClusterResourceOfflinePending: printf("Offline Pending"); break;
default: printf("Unknown"); }
printf("\n");
FnExit:
if ( resState.ResNodeName ) { LocalFree( resState.ResNodeName ); }
if ( resState.ResGroupName ) { LocalFree( resState.ResGroupName ); }
return dwStatus;
} // GetResourceInfo
DWORD GetResourceState( HRESOURCE Resource, PRESOURCE_STATE ResState ) { CLUSTER_RESOURCE_STATE nState;
LPWSTR lpszResNodeName = NULL; LPWSTR lpszResGroupName = NULL;
DWORD dwStatus = NO_ERROR;
nState = WrapGetClusterResourceState( Resource, &lpszResNodeName, &lpszResGroupName );
if ( nState == ClusterResourceStateUnknown ) {
dwStatus = GetLastError(); printf("WrapGetClusterResourceState failed: %d \n", dwStatus); PrintError(dwStatus); goto FnExit; }
ResState->State = nState; ResState->ResNodeName = lpszResNodeName; ResState->ResGroupName = lpszResGroupName;
FnExit:
return dwStatus;
} // GetResourceState
DWORD DisplayResourceName( RESOURCE_HANDLE hResource ) { LPWSTR lpszOutBuffer = NULL; DWORD dwStatus; DWORD dwBytesReturned;
dwStatus = WrapClusterResourceControl( hResource, CLUSCTL_RESOURCE_GET_NAME, &lpszOutBuffer, &dwBytesReturned );
if ( NO_ERROR == dwStatus ) { wprintf( L"Resource Name: %ls\n", lpszOutBuffer );
} else { printf("CLUSCTL_RESOURCE_GET_NAME failed: %d \n", dwStatus); PrintError(dwStatus); }
if (lpszOutBuffer) { LocalFree(lpszOutBuffer); }
return dwStatus;
} // DisplayResourceName
DWORD GetSignature( RESOURCE_HANDLE hResource, DWORD *dwSignature ) { PBYTE outBuffer = NULL;
DWORD dwStatus; DWORD dwBytesReturned;
dwStatus = WrapClusterResourceControl( hResource, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO, &outBuffer, &dwBytesReturned );
if ( NO_ERROR == dwStatus ) {
if ( !GetSignatureFromDiskInfo(outBuffer, dwSignature, dwBytesReturned) ) { printf("Unable to get signature from DiskInfo. \n"); dwStatus = ERROR_BAD_FORMAT; }
} else { printf("CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO failed: %d \n", dwStatus); PrintError(dwStatus); }
if (outBuffer) { LocalFree(outBuffer); }
return dwStatus;
} // GetSignature
BOOLEAN GetSignatureFromDiskInfo( PBYTE DiskInfo, DWORD *Signature, DWORD DiskInfoSize ) { #if TEST_PARSE_ROUTINE
PCLUSPROP_DISK_NUMBER diskNumber = NULL; PCLUSPROP_SCSI_ADDRESS scsiAddress = NULL; PCLUSPROP_PARTITION_INFO partInfo = NULL;
PBYTE junkInfo = NULL; PDWORD dumpInfo = (PDWORD)DiskInfo;
#endif
PCLUSPROP_DISK_SIGNATURE diskSignature = NULL;
diskSignature = (PCLUSPROP_DISK_SIGNATURE)ParseDiskInfo( DiskInfo, DiskInfoSize, CLUSPROP_SYNTAX_DISK_SIGNATURE );
if ( !diskSignature ) { return FALSE; }
*Signature = diskSignature->dw;
#if TEST_PARSE_ROUTINE
diskNumber = (PCLUSPROP_DISK_NUMBER)ParseDiskInfo( DiskInfo, DiskInfoSize, CLUSPROP_SYNTAX_DISK_NUMBER );
if ( diskNumber ) { printf("diskNumber->Syntax: %08X \n", diskNumber->Syntax); printf("diskNumber->cbLength: %08X \n", diskNumber->cbLength); printf("diskNumber->dw: %08X \n", diskNumber->dw); }
scsiAddress = (PCLUSPROP_SCSI_ADDRESS)ParseDiskInfo( DiskInfo, DiskInfoSize, CLUSPROP_SYNTAX_SCSI_ADDRESS );
if ( scsiAddress ) { printf("scsiAddress->Syntax: %08X \n", scsiAddress->Syntax); printf("scsiAddress->cbLength: %08X \n", scsiAddress->cbLength); printf("scsiAddress->PortNumber: %02X \n", scsiAddress->PortNumber); printf("scsiAddress->PathId: %02X \n", scsiAddress->PathId); printf("scsiAddress->TargetId: %02X \n", scsiAddress->TargetId); printf("scsiAddress->Lun: %02X \n", scsiAddress->Lun); }
partInfo = (PCLUSPROP_PARTITION_INFO)ParseDiskInfo( DiskInfo, DiskInfoSize, CLUSPROP_SYNTAX_PARTITION_INFO );
if ( partInfo ) {
printf("Partition info... \n"); }
//
// The following should fail...
//
junkInfo = ParseDiskInfo( DiskInfo, DiskInfoSize, -1 );
if (junkInfo) { printf("Problem parsing list. Used invalid syntax and pointer returned! \n"); }
#endif
return TRUE;
} // GetSignatureFromDiskInfo
LPBYTE ParseDiskInfo( PBYTE DiskInfo, DWORD DiskInfoSize, DWORD SyntaxValue ) { CLUSPROP_BUFFER_HELPER ListEntry; // used to parse the value list
DWORD cbOffset = 0; // offset to next entry in the value list
DWORD cbPosition = 0; // tracks the advance through the value list buffer
LPBYTE returnPtr = 0;
ListEntry.pb = DiskInfo;
while (TRUE) {
if ( CLUSPROP_SYNTAX_ENDMARK == *ListEntry.pdw ) { break; }
cbOffset = ALIGN_CLUSPROP( ListEntry.pValue->cbLength + sizeof(CLUSPROP_VALUE) );
//
// Check for specific syntax in the property list.
//
if ( SyntaxValue == *ListEntry.pdw ) {
//
// Make sure the complete entry fits in the buffer specified.
//
if ( cbPosition + cbOffset > DiskInfoSize ) {
printf("Possibly corrupt list! \n");
} else {
returnPtr = ListEntry.pb; }
break; }
//
// Verify that the offset to the next entry is
// within the value list buffer, then advance
// the CLUSPROP_BUFFER_HELPER pointer.
//
cbPosition += cbOffset; if ( cbPosition > DiskInfoSize ) break; ListEntry.pb += cbOffset; }
return returnPtr;
} // ParseDiskInfo
VOID PrintError( IN DWORD ErrorCode ) { LPVOID lpMsgBuf; ULONG count;
count = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, ErrorCode, 0, (LPTSTR) &lpMsgBuf, 0, NULL );
if (count != 0) { printf(" (%d) %s\n", ErrorCode, (LPCTSTR) lpMsgBuf); LocalFree( lpMsgBuf ); } else { printf("Format message failed. Error: %d\n", GetLastError()); }
} // PrintError
DWORD WrapClusterResourceControl( RESOURCE_HANDLE hResource, DWORD dwControlCode, LPVOID *OutBuffer, DWORD *dwBytesReturned ) { DWORD dwStatus;
DWORD cbOutBufferSize = MAX_NAME_SIZE; DWORD cbResultSize = MAX_NAME_SIZE; LPVOID tempOutBuffer = LocalAlloc( LPTR, cbOutBufferSize );
dwStatus = ClusterResourceControl( hResource, NULL, dwControlCode, NULL, 0, tempOutBuffer, cbOutBufferSize, &cbResultSize );
//
// Reallocation routine if buffer is too small
//
if ( ERROR_MORE_DATA == dwStatus ) { LocalFree( tempOutBuffer );
cbOutBufferSize = cbResultSize;
tempOutBuffer = LocalAlloc( LPTR, cbOutBufferSize );
dwStatus = ClusterResourceControl( hResource, NULL, dwControlCode, NULL, 0, tempOutBuffer, cbOutBufferSize, &cbResultSize ); }
//
// On success, give the user the allocated buffer. The user is responsible
// for freeing this buffer. On failure, free the buffer and return a status.
//
if ( NO_ERROR == dwStatus ) { *OutBuffer = tempOutBuffer; *dwBytesReturned = cbResultSize; } else { *OutBuffer = NULL; *dwBytesReturned = 0; LocalFree( tempOutBuffer ); }
return dwStatus;
} // WrapClusterResourceControl
CLUSTER_RESOURCE_STATE WINAPI WrapGetClusterResourceState( IN HRESOURCE hResource, OUT OPTIONAL LPWSTR * ppwszNodeName, OUT OPTIONAL LPWSTR * ppwszGroupName ) { CLUSTER_RESOURCE_STATE cState = ClusterResourceStateUnknown; LPWSTR pwszNodeName = NULL; DWORD cchNodeName = 128; LPWSTR pwszGroupName = NULL; DWORD cchGroupName = 128; DWORD cchTempNodeName = cchNodeName; DWORD cchTempGroupName = cchGroupName;
// Zero the out parameters
if ( ppwszNodeName != NULL ) { *ppwszNodeName = NULL; }
if ( ppwszGroupName != NULL ) { *ppwszGroupName = NULL; }
pwszNodeName = (LPWSTR) LocalAlloc( LPTR, cchNodeName * sizeof( *pwszNodeName ) ); if ( pwszNodeName != NULL ) { pwszGroupName = (LPWSTR) LocalAlloc( LPTR, cchGroupName * sizeof( *pwszGroupName ) ); if ( pwszGroupName != NULL ) { cState = GetClusterResourceState( hResource, pwszNodeName, &cchTempNodeName, pwszGroupName, &cchTempGroupName ); if ( GetLastError() == ERROR_MORE_DATA ) { cState = ClusterResourceStateUnknown; // reset to error condition
LocalFree( pwszNodeName ); pwszNodeName = NULL; cchNodeName = ++cchTempNodeName;
LocalFree( pwszGroupName ); pwszGroupName = NULL; cchGroupName = ++cchTempGroupName;
pwszNodeName = (LPWSTR) LocalAlloc( LPTR, cchNodeName * sizeof( *pwszNodeName ) ); if ( pwszNodeName != NULL ) { pwszGroupName = (LPWSTR) LocalAlloc( LPTR, cchGroupName * sizeof( *pwszGroupName ) ); if ( pwszGroupName != NULL ) { cState = GetClusterResourceState( hResource, pwszNodeName, &cchNodeName, pwszGroupName, &cchGroupName ); } } } } }
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( cState != ClusterResourceStateUnknown ) && ( ppwszNodeName != NULL ) ) { *ppwszNodeName = pwszNodeName; }
//
// if there was not an error and the argument was not NULL, then return the string.
//
if ( ( cState != ClusterResourceStateUnknown ) && ( ppwszGroupName != NULL ) ) { *ppwszGroupName = pwszGroupName; }
//
// if there was an error or the argument was NULL, then free the string.
//
if ( ( cState == ClusterResourceStateUnknown ) || ( ppwszNodeName == NULL ) ) { LocalFree( pwszNodeName ); }
//
// if there was an error or the argument was NULL, then free the string.
//
if ( ( cState == ClusterResourceStateUnknown ) || ( ppwszGroupName == NULL ) ) { LocalFree( pwszGroupName ); }
return cState;
} //*** WrapGetClusterResourceState()
#define MAX_COLUMNS 16
VOID DumpBuffer( IN PUCHAR Buffer, IN DWORD ByteCount ) { DWORD idx; DWORD jdx; DWORD columns;
UCHAR tempC;
if ( !Buffer || !ByteCount ) { printf("Invalid parameter specified: buffer %p byte count %d \n", Buffer, ByteCount); return; }
//
// Print header.
//
printf("\n"); printf(" Address 00 01 02 03 04 05 06 07 - 08 09 0a 0b 0c 0d 0e 0f \n"); printf("--------- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ");
for ( idx = 0; idx < ByteCount; idx += MAX_COLUMNS ) {
if ( idx % MAX_COLUMNS == 0 ) { printf("\n%08x: ", idx); }
if ( ByteCount - idx >= MAX_COLUMNS ) { columns = MAX_COLUMNS; } else { columns = ByteCount - idx; }
for ( jdx = 0; jdx < MAX_COLUMNS; jdx++) {
if ( jdx == 8 ) { printf("- "); }
if ( jdx < columns ) { printf("%02x ", Buffer[idx+jdx]); } else { printf(" "); } }
printf(" ");
for ( jdx = 0; jdx < columns; jdx++ ) {
tempC = Buffer[idx+jdx];
if ( isprint(tempC) ) { printf("%c", tempC); } else { printf("."); }
}
}
printf("\n\n");
} // DumpBuffer
|