ResUtilFindDependentDiskResourceDriveLetter function (resapi.h)
Retrieves the drive letter associated with a Physical Disk dependency of a resource. The PRESUTIL_FIND_DEPENDENT_DISK_RESOURCE_DRIVE_LETTER type defines a pointer to this function.
Syntax
DWORD ResUtilFindDependentDiskResourceDriveLetter(
[in] HCLUSTER hCluster,
[in] HRESOURCE hResource,
[out] LPWSTR pszDriveLetter,
[in, out] DWORD *pcchDriveLetter
);
Parameters
[in] hCluster
Cluster handle.
[in] hResource
Handle to the resource to query for dependencies.
[out] pszDriveLetter
Buffer in which to store the drive letter.
[in, out] pcchDriveLetter
On input, specifies the size of the pszDriveLetter buffer as a count of WCHARs. On output, specifies the size of the resulting data as a count of WCHARs that includes the terminating NULL.
Return value
If the operations succeeds, the function returns ERROR_SUCCESS (0).
If the operation fails, the function returns a system error code. The following are possible error codes.
Return code | Description |
---|---|
|
No Physical Disk dependency was found in the specified resource's list of dependencies. |
|
No drive letter could be returned. |
|
The buffer passed in was too small. The pcchDriveLetter parameter specifies the required size. |
Remarks
Do not call this function from a resource DLL. It will cause a deadlock. You should have your resource extension call this function and write the results out as a private property that your resource DLL can then read.
If the resource identified by hResource depends on more than one Physical Disk resource, ResUtilFindDependentDiskResourceDriveLetter returns the drive letter of the first Physical Disk dependency that is enumerated for the resource.
Examples
The following example takes a resource name as a command line argument and displays the drive letter associated with the resource's Physical Disk dependency (if any). This example uses the ClusDocEx.h header file defined in the Failover Cluster documentation.
//////////////////////////////////////////////////////////////////////
#include "ClusDocEx.h"
int main( int argc, char argv[] )
{
HCLUSTER hCluster = NULL;
HRESOURCE hRes = NULL;
DWORD dw;
DWORD cchResDrive = ClusDocEx_DEFAULT_CCH;
DWORD cchResName = ClusDocEx_DEFAULT_CCH;
WCHAR *pszResDrive = new WCHAR[cchResDrive];
WCHAR *pszResName = new WCHAR[cchResName];
dw = ClusDocEx_ConvertArg( argv[1], pszResName, cchResName );
if( dw == ERROR_SUCCESS )
{
hCluster = ClusDocEx_OpenLocalClusterWithName();
if( hCluster != NULL )
{
hRes = OpenClusterResource( hCluster, pszResName );
if( hRes != NULL )
{
dw = ResUtilFindDependentDiskResourceDriveLetter( hCluster,
hRes,
pszResDrive,
&cchResDrive );
if( dw == ERROR_MORE_DATA )
{
delete [] pszResDrive;
pszResDrive = new WCHAR[cchResDrive];
dw = ResUtilFindDependentDiskResourceDriveLetter( hCluster,
hRes,
pszResDrive,
&cchResDrive );
}
switch( dw )
{
case ERROR_SUCCESS:
wprintf( L"%ls depends on drive %ls.\n", pszResName, pszResDrive );
break;
case ERROR_NO_MORE_ITEMS:
case ERROR_RESOURCE_NOT_PRESENT:
wprintf( L"No Physical Disk dependency found for %ls.\n", pszResName );
break;
default:
ClusDocEx_DebugPrint( L"Could not obtain drive information", dw );
break;
}
CloseClusterResource( hRes );
}
else // if hRes == NULL
{
ClusDocEx_DebugPrint( L"Could not open a resource handle", GetLastError() );
}
CloseCluster( hCluster );
}
else // if hCluster == NULL
{
ClusDocEx_DebugPrint( L"Could not open a cluster handle", GetLastError() );
}
}
delete [] pszResName;
delete [] pszResDrive;
return 0;
}
If the resource identified by hResource refers to a mount point disk, there may or may not be a drive letter associated with the disk resource. If the mount point disk has no associated drive letter, the value returned by ResUtilFindDependentDiskResourceDriveLetter will be in the format of DiskXPartitionY, which is valid data but cannot be passed directly to file system APIs such as CreateFile.
The following example takes the output string from ResUtilFindDependentDiskResourceDriveLetter and transforms it to Win32 format. The output string from this function can be passed to CreateFile. If the function fails, the return value is NULL; call GetLastError to get extended error info. If the function succeeds the user has to free the buffer returned using LocalFree.
#define UNICODE 1
#define _UNICODE 1
#pragma comment(lib, "ResUtils.lib")
#include <windows.h>
#include <stdlib.h>
#include <ResApi.h>
#include <strsafe.h>
#define IS_DRIVELETTER(x) ((iswalpha((x)[0])) && ((x)[1] == L':'))
#define IS_NTPATH(x) ((wcsstr((x), L"Disk") != NULL) && (wcsstr((x), L"Partition") != NULL))
#define GLOBALROOT_DISK_FORMAT L"\\\\\?\\GLOBALROOT\\Device\\Harddisk%u\\Partition%u"
LPWSTR ConvertNtDiskPathToW32DiskPath( LPCWSTR InputString )
{
LPWSTR outputString=NULL;
DWORD status=ERROR_INVALID_PARAMETER;
DWORD len;
DWORD diskNum, partNum;
if ((InputString == NULL) || (InputString[0] == 0))
{
goto Error_exit;
}
// Find out the required buffer size.
len = 0;
if (IS_DRIVELETTER(InputString))
{
len = wcslen(InputString) + 4;
}
else if (IS_NTPATH(InputString))
{
len = wcslen(GLOBALROOT_DISK_FORMAT) + 16;
}
else
{
//Malformed string.
goto Error_exit;
}
if ((outputString = (LPWSTR)LocalAlloc(LPTR, len * sizeof(WCHAR))) == NULL)
{
status = GetLastError();
goto Error_exit;
}
if (IS_DRIVELETTER(InputString))
{
StringCchCopyW(outputString, len, InputString);
}
else
{
//Has to be NT path format.
swscanf_s(InputString, L"Disk%uPartition%u", &diskNum, &partNum);
StringCchPrintfW(outputString, len, GLOBALROOT_DISK_FORMAT, diskNum, partNum);
}
status = ERROR_SUCCESS;
Error_exit:
if (status != ERROR_SUCCESS)
{
if (outputString)
{
LocalFree(outputString);
}
SetLastError(status);
return NULL;
}
return outputString;
}
Requirements
Requirement | Value |
---|---|
Minimum supported client | None supported |
Minimum supported server | Windows Server 2008 Enterprise, Windows Server 2008 Datacenter |
Target Platform | Windows |
Header | resapi.h |
Library | ResUtils.lib |
DLL | ResUtils.dll |
See also
ResUtilGetResourceDependencyByClass
ResUtilGetResourceDependencyByName
ResUtilGetResourceDependentIPAddressProps