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.
1258 lines
35 KiB
1258 lines
35 KiB
|
|
|
|
#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
|
|
|