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
ERROR_NO_MORE_ITEMS
No Physical Disk dependency was found in the specified resource's list of dependencies.
ERROR_RESOURCE_NOT_PRESENT
No drive letter could be returned.
ERROR_MORE_DATA
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

ResUtilGetResourceDependency

ResUtilGetResourceDependencyByClass

ResUtilGetResourceDependencyByName

ResUtilGetResourceDependentIPAddressProps

ResUtilGetResourceNameDependency

Resource Utility Functions