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.
2818 lines
73 KiB
2818 lines
73 KiB
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
resprop.c
|
|
|
|
Abstract:
|
|
|
|
Implements the management of properties.
|
|
|
|
Author:
|
|
|
|
Rod Gamache (rodga) 19-Mar-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#pragma warning( push )
|
|
#pragma warning( disable : 4115 ) // Clusrtl - struct def in parentheses
|
|
#pragma warning( disable : 4201 ) // SDK - nameless struct/union
|
|
|
|
#define UNICODE 1
|
|
#include "clusres.h"
|
|
#include "clusrtl.h"
|
|
#include "stdio.h"
|
|
#include "stdlib.h"
|
|
|
|
#pragma warning( pop )
|
|
|
|
//
|
|
// Cluster Registry API function pointers
|
|
//
|
|
CLUSTER_REG_APIS
|
|
ResUtilClusterRegApis = {
|
|
(PFNCLRTLCREATEKEY) ClusterRegCreateKey,
|
|
(PFNCLRTLOPENKEY) ClusterRegOpenKey,
|
|
(PFNCLRTLCLOSEKEY) ClusterRegCloseKey,
|
|
(PFNCLRTLSETVALUE) ClusterRegSetValue,
|
|
(PFNCLRTLQUERYVALUE) ClusterRegQueryValue,
|
|
(PFNCLRTLENUMVALUE) ClusterRegEnumValue,
|
|
(PFNCLRTLDELETEVALUE) ClusterRegDeleteValue,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilEnumProperties(
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT LPWSTR pszOutProperties,
|
|
IN DWORD cbOutPropertiesSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerates the properties for a given object.
|
|
|
|
Arguments:
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pszOutProperties - Supplies the output buffer.
|
|
|
|
cbOutPropertiesSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pszOutProperties.
|
|
|
|
pcbRequired - The required number of bytes if pszOutProperties is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlEnumProperties( pPropertyTable,
|
|
pszOutProperties,
|
|
cbOutPropertiesSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
|
|
} // ResUtilEnumProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilEnumPrivateProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
OUT LPWSTR pszOutProperties,
|
|
IN DWORD cbOutPropertiesSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerates the properties for a given object.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pszOutProperties - Supplies the output buffer.
|
|
|
|
cbOutPropertiesSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pszOutProperties.
|
|
|
|
pcbRequired - The required number of bytes if pszOutProperties is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlEnumPrivateProperties( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pszOutProperties,
|
|
cbOutPropertiesSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
|
|
} // ResUtilEnumProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT LPWSTR pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the properties for a given object.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pPropertyList - Supplies the output buffer.
|
|
|
|
cbPropertyListSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pPropertyList.
|
|
|
|
pcbRequired - The required number of bytes if pPropertyList is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlGetProperties( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
pPropertyList,
|
|
cbPropertyListSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
} // ResUtilGetProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetAllProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the default and 'unknown' properties for a given object.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pPropertyList - Supplies the output buffer.
|
|
|
|
cbPropertyListSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pPropertyList.
|
|
|
|
pcbRequired - The required number of bytes if pPropertyList is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlGetAllProperties( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
pPropertyList,
|
|
cbPropertyListSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
} // ResUtilGetAllProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetPropertiesToParameterBlock(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT LPBYTE pOutParams,
|
|
IN BOOL bCheckForRequiredProperties,
|
|
OUT OPTIONAL LPWSTR * pszNameOfPropInError
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the default and 'unknown' properties for a given object and stores
|
|
them in a parameter block.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pOutParams - Supplies the output parameter block.
|
|
|
|
bCheckForRequiredProperties - Boolean value specifying whether missing
|
|
required properties should cause an error.
|
|
|
|
pszNameOfPropInError - String pointer in which to return the name of the
|
|
property in error (optional).
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD status;
|
|
|
|
status = ClRtlGetPropertiesToParameterBlock( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
pOutParams,
|
|
bCheckForRequiredProperties,
|
|
pszNameOfPropInError );
|
|
return(status);
|
|
|
|
} // ResUtilGetPropertiesToParameterBlock
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilPropertyListFromParameterBlock(
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT PVOID pOutPropertyList,
|
|
IN OUT LPDWORD pcbOutPropertyListSize,
|
|
IN const LPBYTE pInParams,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructs a property list from a parameter block.
|
|
|
|
Arguments:
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pOutPropertyList - Supplies the output buffer.
|
|
|
|
pcbOutPropertyListSize - Supplies the size of the output buffer.
|
|
|
|
pInParams - Supplies the input parameter block.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pOutPropertyList.
|
|
|
|
pcbRequired - The required number of bytes if pOutPropertyList is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD status;
|
|
|
|
status = ClRtlPropertyListFromParameterBlock( pPropertyTable,
|
|
pOutPropertyList,
|
|
pcbOutPropertyListSize,
|
|
pInParams,
|
|
pcbBytesReturned,
|
|
pcbRequired );
|
|
return(status);
|
|
|
|
} // ResUtilPropertyListFromParameterBlock
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetPrivateProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
OUT PVOID pOutPropertyList,
|
|
IN DWORD cbOutPropertyListSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the private properties for a given object.
|
|
|
|
This routine assumes that it uses the Cluster Registry API's for
|
|
access to registry info.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pOutPropertyList - Supplies the output buffer.
|
|
|
|
cbOutPropertyListSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - The number of bytes returned in pOutPropertyList.
|
|
|
|
pcbRequired - The required number of bytes if pOutPropertyList is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlGetPrivateProperties( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pOutPropertyList,
|
|
cbOutPropertyListSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
} // ResUtilGetPrivateProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetPropertySize(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
|
|
IN OUT LPDWORD pcbOutPropertyListSize,
|
|
IN OUT LPDWORD pnPropertyCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the total number of bytes required for this property.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlGetPropertySize( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTableItem,
|
|
pcbOutPropertyListSize,
|
|
pnPropertyCount ) );
|
|
|
|
} // ResUtilGetPropertySize
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetProperty(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
|
|
OUT PVOID * pOutPropertyItem,
|
|
IN OUT LPDWORD pcbOutPropertyItemSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
The buffer size has already been determined to be large enough to hold
|
|
the return data.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlGetProperty( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTableItem,
|
|
pOutPropertyItem,
|
|
pcbOutPropertyItemSize ) );
|
|
|
|
} // ResUtilGetProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilVerifyPropertyTable(
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN PVOID Reserved,
|
|
IN BOOL bAllowUnknownProperties,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize,
|
|
OUT OPTIONAL PBYTE pOutParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate a property list.
|
|
|
|
Arguments:
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
Reserved - Possible pointer to a future ReadOnly property table.
|
|
|
|
bAllowUnknownProperties - TRUE if unknown properties should be accepted.
|
|
|
|
pInPropertyList - The input buffer.
|
|
|
|
cbInPropertyListSize - The input buffer size.
|
|
|
|
pOutParams - Parameters block in which to return the data.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlVerifyPropertyTable( pPropertyTable,
|
|
Reserved,
|
|
bAllowUnknownProperties,
|
|
pInPropertyList,
|
|
cbInPropertyListSize,
|
|
pOutParams ) );
|
|
|
|
} // ResUtilVerifyPropertyTable
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetPropertyTable(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN PVOID Reserved,
|
|
IN BOOL bAllowUnknownProperties,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize,
|
|
OUT OPTIONAL PBYTE pOutParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this object's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
Reserved - Possible pointer to a future ReadOnly property table.
|
|
|
|
bAllowUnknownProperties - TRUE if unknown properties should be accepted.
|
|
|
|
pInPropertyList - The input buffer.
|
|
|
|
cbInPropertyListSize - The input buffer size.
|
|
|
|
pOutParams - Parameters block in which to return the data.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlSetPropertyTable( NULL,
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
Reserved,
|
|
bAllowUnknownProperties,
|
|
pInPropertyList,
|
|
cbInPropertyListSize,
|
|
FALSE, // bForceWrite
|
|
pOutParams ) );
|
|
|
|
} // ResUtilSetPropertyTable
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetPropertyTableEx(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN PVOID Reserved,
|
|
IN BOOL bAllowUnknownProperties,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize,
|
|
IN BOOL bForceWrite,
|
|
OUT OPTIONAL PBYTE pOutParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this object's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
Reserved - Possible pointer to a future ReadOnly property table.
|
|
|
|
bAllowUnknownProperties - TRUE if unknown properties should be accepted.
|
|
|
|
pInPropertyList - The input buffer.
|
|
|
|
cbInPropertyListSize - The input buffer size.
|
|
|
|
bForceWrite - TRUE = always write the properties to the cluster database.
|
|
FALSE = only write the properties if they changed.
|
|
|
|
pOutParams - Parameters block in which to return the data.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlSetPropertyTable( NULL,
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
Reserved,
|
|
bAllowUnknownProperties,
|
|
pInPropertyList,
|
|
cbInPropertyListSize,
|
|
bForceWrite,
|
|
pOutParams ) );
|
|
|
|
} // ResUtilSetPropertyTableEx
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetPropertyParameterBlock(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN PVOID Reserved,
|
|
IN const LPBYTE pInParams,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize,
|
|
OUT OPTIONAL PBYTE pOutParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this object's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pInParams - Parameters block to set.
|
|
|
|
pInPropertyList - Full Property list.
|
|
|
|
cbInPropertyListSize - Size of the input full property list.
|
|
|
|
pOutParams - Parameters block to copy pInParams to.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlSetPropertyParameterBlock( NULL, // IN HANDLE hXsaction,
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
Reserved,
|
|
pInParams,
|
|
pInPropertyList,
|
|
cbInPropertyListSize,
|
|
FALSE, // bForceWrite
|
|
pOutParams ) );
|
|
|
|
} // ResUtilSetPropertyParameterBlock
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetPropertyParameterBlockEx(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN PVOID Reserved,
|
|
IN const LPBYTE pInParams,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize,
|
|
IN BOOL bForceWrite,
|
|
OUT OPTIONAL PBYTE pOutParams
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this object's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pInParams - Parameters block to set.
|
|
|
|
pInPropertyList - Full Property list.
|
|
|
|
cbInPropertyListSize - Size of the input full property list.
|
|
|
|
bForceWrite - TRUE = always write the properties to the cluster database.
|
|
FALSE = only write the properties if they changed.
|
|
|
|
pOutParams - Parameters block to copy pInParams to.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlSetPropertyParameterBlock( NULL, // IN HANDLE hXsaction,
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
Reserved,
|
|
pInParams,
|
|
pInPropertyList,
|
|
cbInPropertyListSize,
|
|
bForceWrite,
|
|
pOutParams ) );
|
|
|
|
} // ResUtilSetPropertyParameterBlockEx
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetUnknownProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set items that are not in the property table list.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this object's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pInPropertyList - Full Property list.
|
|
|
|
cbInPropertyListSize - Size of the input full property list.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlpSetNonPropertyTable( NULL, // IN HANDLE hXsaction
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
NULL,
|
|
pInPropertyList,
|
|
cbInPropertyListSize ) );
|
|
|
|
} // ResUtilSetUnknownProperties
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilVerifyPrivatePropertyList(
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate a private property list.
|
|
|
|
Arguments:
|
|
|
|
pInPropertyList - The input buffer.
|
|
|
|
cbInPropertyListSize - The input buffer size.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlVerifyPrivatePropertyList( pInPropertyList, cbInPropertyListSize ) );
|
|
|
|
} // ResUtilVerifyPrivatePropertyList
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilSetPrivatePropertyList(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PVOID pInPropertyList,
|
|
IN DWORD cbInPropertyListSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - The opened registry key for this resource's parameters.
|
|
If not specified, the property list will only be validated.
|
|
|
|
pInPropertyList - The input buffer.
|
|
|
|
cbInPropertyListSize - The input buffer size.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 Error on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction
|
|
hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pInPropertyList,
|
|
cbInPropertyListSize ) );
|
|
|
|
} // ResUtilSetPrivatePropertyList
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilAddUnknownProperties(
|
|
IN HKEY hkeyClusterKey,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
IN OUT PVOID pOutPropertyList,
|
|
IN DWORD cbOutPropertyListSize,
|
|
IN OUT LPDWORD pcbBytesReturned,
|
|
IN OUT LPDWORD pcbRequired
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds the unknown properties for a given object to the end of a property
|
|
list.
|
|
|
|
Arguments:
|
|
|
|
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
|
to read from.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
pOutPropertyList - Supplies the output buffer.
|
|
|
|
cbOutPropertyListSize - Supplies the size of the output buffer.
|
|
|
|
pcbBytesReturned - On input, contains the number of bytes in use in the
|
|
output buffer. On output, contains the total number of bytes in
|
|
pOutPropertyList.
|
|
|
|
pcbRequired - The required number of bytes if pOutPropertyList is too small.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Operation was successful.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD status;
|
|
|
|
status = ClRtlAddUnknownProperties( hkeyClusterKey,
|
|
&ResUtilClusterRegApis,
|
|
pPropertyTable,
|
|
pOutPropertyList,
|
|
cbOutPropertyListSize,
|
|
pcbBytesReturned,
|
|
pcbRequired );
|
|
|
|
return(status);
|
|
|
|
} // ResUtilAddUnknownProperties
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Utility routines to grovel though a Control Function item list buffer
|
|
//
|
|
//***************************************************************************
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindSzProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPWSTR * pszPropertyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified string property in the Property List buffer pointed at
|
|
by pPropertyList.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pszPropertyValue - the matching string value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindSzProperty( pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pszPropertyValue ) );
|
|
|
|
} // ResUtilFindSzProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindExpandSzProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPWSTR * pszPropertyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified EXPAND_SZ string property in the Property List buffer
|
|
pointed at by pPropertyList.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pszPropertyValue - the matching string value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindExpandSzProperty(
|
|
pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pszPropertyValue ) );
|
|
|
|
} // ResUtilFindExpandSzProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindExpandedSzProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPWSTR * pszPropertyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified string property in the Property List buffer pointed at
|
|
by pPropertyList and returns it's expanded value.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pszPropertyValue - the matching string value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindExpandedSzProperty(
|
|
pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pszPropertyValue ) );
|
|
|
|
} // ResUtilFindExpandedSzProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindDwordProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPDWORD pdwPropertyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified DWORD property in the Property List buffer pointed at
|
|
by pPropertyList.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pdwPropertyValue - the matching DWORD value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindDwordProperty( pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pdwPropertyValue ) );
|
|
|
|
} // ResUtilFindDwordProperty
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindLongProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPLONG plPropertyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified string in the Value List buffer pointed at by Buffer.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
plPropertyValue - the matching long value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindLongProperty( pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
plPropertyValue ) );
|
|
} // ResUtilFindLongProperty
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindBinaryProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPBYTE * pbPropertyValue,
|
|
OUT LPDWORD pcbPropertyValueSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified binary property in the Property List buffer pointed at
|
|
by pPropertyList.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pbPropertyValue - the matching binary value found.
|
|
|
|
pcbPropertyValueSize - the length of the matching binary value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindBinaryProperty( pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pbPropertyValue,
|
|
pcbPropertyValueSize ) );
|
|
|
|
} // ResUtilFindBinaryProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilFindMultiSzProperty(
|
|
IN PVOID pPropertyList,
|
|
IN DWORD cbPropertyListSize,
|
|
IN LPCWSTR pszPropertyName,
|
|
OUT LPWSTR * pszPropertyValue,
|
|
OUT LPDWORD pcbPropertyValueSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds the specified multiple string property in the Proprety List buffer
|
|
pointed at by pPropertyList.
|
|
|
|
Arguments:
|
|
|
|
pPropertyList - a property list.
|
|
|
|
cbPropertyListSize - the size in bytes of the data in pPropertyList.
|
|
|
|
pszPropertyName - the property name to look for in the buffer.
|
|
|
|
pszPropertyValue - the matching multiple string value found.
|
|
|
|
pcbPropertyValueSize - the length of the matching multiple string value found.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return( ClRtlFindMultiSzProperty( pPropertyList,
|
|
cbPropertyListSize,
|
|
pszPropertyName,
|
|
pszPropertyValue,
|
|
pcbPropertyValueSize ) );
|
|
|
|
} // ResUtilFindMultiSzProperty
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilDupParameterBlock(
|
|
OUT LPBYTE pOutParams,
|
|
IN const LPBYTE pInParams,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocates any buffers allocated for a parameter block that are
|
|
different than the buffers used for the input parameter block.
|
|
|
|
Arguments:
|
|
|
|
pOutParams - Parameter block to return.
|
|
|
|
pInParams - Reference parameter block.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Parameter block duplicated successfully.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD status;
|
|
|
|
status = ClRtlDupParameterBlock( pOutParams, pInParams, pPropertyTable );
|
|
|
|
return(status);
|
|
|
|
} // ResUtilDupParameterBlock
|
|
|
|
|
|
|
|
void
|
|
WINAPI
|
|
ResUtilFreeParameterBlock(
|
|
IN OUT LPBYTE pOutParams,
|
|
IN const LPBYTE pInParams,
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocates any buffers allocated for a parameter block that are
|
|
different than the buffers used for the input parameter block.
|
|
|
|
Arguments:
|
|
|
|
pOutParams - Parameter block to free.
|
|
|
|
pInParams - Reference parameter block.
|
|
|
|
pPropertyTable - Pointer to the property table to process.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ClRtlFreeParameterBlock( pOutParams, pInParams, pPropertyTable );
|
|
|
|
} // ResUtilFreeParameterBlock
|
|
|
|
|
|
#define __INITIAL_NAME_LENGTH 256
|
|
|
|
BOOL
|
|
WINAPI
|
|
ResUtilResourceTypesEqual(
|
|
IN LPCWSTR lpszResourceTypeName,
|
|
IN HRESOURCE hResource
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Checks to see if the resource names type matches
|
|
|
|
Arguments:
|
|
lpszResourceTypeName - The type of resource to check for
|
|
|
|
hResource - A handle to the resource to check
|
|
|
|
Return Value:
|
|
TRUE - the resource type matches
|
|
FALSE - the resource types do not match
|
|
|
|
--*/
|
|
{
|
|
BOOL bIsEqual = FALSE;
|
|
DWORD dwError;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR pszName = szName;
|
|
DWORD cbNameBufSize = __INITIAL_NAME_LENGTH * sizeof( szName[ 0 ] );
|
|
DWORD cbRetSize;
|
|
|
|
// Get the resource type name
|
|
dwError = ClusterResourceControl(
|
|
hResource, //Handle to the resource
|
|
NULL, //Don't care about node
|
|
CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, //Get the type
|
|
0, // &InBuffer
|
|
0, // nInBufferSize,
|
|
pszName, // &OutBuffer
|
|
cbNameBufSize, // nOutBufferSize,
|
|
&cbRetSize ); // returned size
|
|
|
|
if ( dwError == ERROR_MORE_DATA )
|
|
{
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cbNameBufSize = cbRetSize + sizeof( WCHAR );
|
|
pszName = LocalAlloc( LMEM_FIXED, cbNameBufSize );
|
|
if ( pszName == NULL )
|
|
{
|
|
goto Cleanup;
|
|
} // if: error allocating buffer
|
|
dwError = ClusterResourceControl(
|
|
hResource, //Handle to the resource
|
|
NULL, //Don't care about node
|
|
CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, //Get the type
|
|
0, // &InBuffer
|
|
0, // nInBufferSize,
|
|
pszName, // &OutBuffer
|
|
cbNameBufSize, // nOutBufferSize,
|
|
&cbRetSize ); // returned size
|
|
} // if: name buffer too small
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// See if it's like US
|
|
if ( lstrcmpiW( lpszResourceTypeName, pszName ) == 0 )
|
|
{
|
|
bIsEqual = TRUE;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( pszName != szName )
|
|
{
|
|
LocalFree( pszName );
|
|
} // if: we allocated the output name buffer
|
|
|
|
return bIsEqual;
|
|
|
|
} //*** ResUtilResourceTypesEqual()
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
ResUtilResourcesEqual(
|
|
IN HRESOURCE hSelf,
|
|
IN HRESOURCE hResource
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Check to See if the resources are the same
|
|
|
|
Arguments:
|
|
IN hSelf - a handle to the callee, or NULL to indicate not equal.
|
|
|
|
IN hResource - a handle to the resource to compare
|
|
|
|
Return Value:
|
|
|
|
TRUE - Resource are equal
|
|
FALSE - otherwise
|
|
|
|
--*/
|
|
{
|
|
BOOL bIsEqual = FALSE;
|
|
DWORD sc;
|
|
LPWSTR pwszSelfName = NULL;
|
|
DWORD cbSelfName = 0;
|
|
LPWSTR pwszResName = NULL;
|
|
DWORD cbResName = 0;
|
|
DWORD cbRetSize = 0;
|
|
|
|
if ( ( hSelf == NULL ) || ( hResource == NULL ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// "Self" - Get the resource name
|
|
sc = ClusterResourceControl(
|
|
hSelf, //Handle to the resource
|
|
NULL, //Don't care about node
|
|
CLUSCTL_RESOURCE_GET_NAME, //Get the name
|
|
NULL, // &InBuffer
|
|
0, // nInBufferSize,
|
|
NULL, // &OutBuffer
|
|
0, // OutBufferSize,
|
|
&cbRetSize // returned size
|
|
);
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Allocate the necessary buffer.
|
|
//
|
|
cbSelfName = cbRetSize + sizeof( WCHAR ); // Add one for NULL.
|
|
pwszSelfName = LocalAlloc( LMEM_FIXED, cbSelfName );
|
|
if ( pwszSelfName == NULL )
|
|
{
|
|
goto Cleanup;
|
|
} // if: error allocating buffer
|
|
|
|
sc = ClusterResourceControl(
|
|
hSelf, // Handle to the resource
|
|
NULL, // Don't care about node
|
|
CLUSCTL_RESOURCE_GET_NAME, // Get the name
|
|
0, // &InBuffer
|
|
0, // nInBufferSize,
|
|
pwszSelfName, // &OutBuffer
|
|
cbSelfName, // OutBufferSize,
|
|
&cbRetSize // returned size
|
|
);
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// "Res" - Get the resource type name
|
|
sc = ClusterResourceControl(
|
|
hResource, //Handle to the resource
|
|
NULL, //Don't care about node
|
|
CLUSCTL_RESOURCE_GET_NAME, //Get the name
|
|
NULL, // &InBuffer
|
|
0, // nInBufferSize,
|
|
NULL, // &OutBuffer
|
|
0, // OutBufferSize,
|
|
&cbRetSize // returned size
|
|
);
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cbResName = cbRetSize + sizeof( WCHAR ); // Add one for NULL.
|
|
pwszResName = LocalAlloc( LMEM_FIXED, cbResName );
|
|
if ( pwszResName == NULL )
|
|
{
|
|
goto Cleanup;
|
|
} // if: error allocating buffer
|
|
|
|
sc = ClusterResourceControl(
|
|
hResource, // Handle to the resource
|
|
NULL, // Don't care about node
|
|
CLUSCTL_RESOURCE_GET_NAME, // Get the name
|
|
NULL, // &InBuffer
|
|
0, // nInBufferSize,
|
|
pwszResName, // &OutBuffer
|
|
cbResName , // OutBufferSize,
|
|
&cbRetSize // returned size
|
|
);
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// See if were looking in a mirror
|
|
if ( ClRtlStrNICmp( pwszResName, pwszSelfName, cbResName ) == 0 )
|
|
{
|
|
bIsEqual = TRUE;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
LocalFree( pwszSelfName );
|
|
LocalFree( pwszResName );
|
|
|
|
return bIsEqual;
|
|
|
|
} //*** ResUtilResourcesEqual()
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
ResUtilIsResourceClassEqual(
|
|
IN PCLUS_RESOURCE_CLASS_INFO prci,
|
|
IN HRESOURCE hResource
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Checks to see if the resource names type matches
|
|
|
|
Arguments:
|
|
prci - The resource class info to check for.
|
|
|
|
hResource - A handle to the resource to check.
|
|
|
|
Return Value:
|
|
TRUE - the resource type matches
|
|
FALSE - the resource types do not match
|
|
|
|
--*/
|
|
{
|
|
BOOL bIsEqual = FALSE;
|
|
DWORD sc;
|
|
DWORD cbRetSize;
|
|
CLUS_RESOURCE_CLASS_INFO rci;
|
|
|
|
// Get the resource class info
|
|
sc = ClusterResourceControl(
|
|
hResource, // Handle to the resource
|
|
NULL, // Don't care about node
|
|
CLUSCTL_RESOURCE_GET_CLASS_INFO, // Get the class info
|
|
0, // &InBuffer
|
|
0, // nInBufferSize,
|
|
&rci, // &OutBuffer
|
|
sizeof( rci ), // nOutBufferSize,
|
|
&cbRetSize ); // returned size
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// See if it's like US
|
|
if ( rci.rc == prci->rc )
|
|
{
|
|
bIsEqual = TRUE;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
return bIsEqual;
|
|
|
|
} //*** ResUtilIsResourceClassEqual()
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilEnumResources(
|
|
IN HRESOURCE hSelf,
|
|
IN LPCWSTR lpszResTypeName,
|
|
IN LPRESOURCE_CALLBACK pResCallBack,
|
|
IN PVOID pParameter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This is a generic resource walking routine. It enumerates all resources in
|
|
the cluster and invokes the callback function for each resource.
|
|
|
|
|
|
Arguments:
|
|
|
|
IN [OPTIONAL] hSelf
|
|
- A handle to the resource. When enumerating resources do
|
|
not invoke the callback when the enumerated resource is
|
|
hSelf.
|
|
IF NULL then invoke the callback for all resources
|
|
|
|
IN [OPTIONAL] lpszResTypeName
|
|
- This is an optional resource type name. If specified the
|
|
callback function will only be invoked for resources of
|
|
this type.
|
|
|
|
IN pResCallBack - Pointer to function that gets called for each enumerated
|
|
resource in the cluster
|
|
|
|
IN pParameter - An Opaque callback parameter
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HCLUSTER hCluster = NULL;
|
|
HCLUSENUM hClusEnum = NULL;
|
|
HRESOURCE hResource = NULL;
|
|
BOOL fExecuteCallBack;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR lpszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwIndex;
|
|
DWORD dwType;
|
|
|
|
//
|
|
// Open the cluster
|
|
//
|
|
hCluster = OpenCluster( NULL );
|
|
if( hCluster == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get a resource enumeration handle
|
|
//
|
|
hClusEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
|
|
if ( hClusEnum == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Enumerate each resource in the cluster
|
|
//
|
|
dwIndex = 0;
|
|
|
|
do
|
|
{
|
|
cchRetSize = cchSize;
|
|
dwStatus = ClusterEnum(
|
|
hClusEnum, //handle to enum
|
|
dwIndex, //Index
|
|
&dwType, //Type
|
|
lpszName, //Name
|
|
&cchRetSize //Size of name (in characters)
|
|
);
|
|
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating NULL
|
|
if ( lpszName != szName )
|
|
{
|
|
LocalFree( lpszName );
|
|
}
|
|
lpszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( lpszName == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
break;
|
|
}
|
|
cchRetSize = cchSize;
|
|
dwStatus = ClusterEnum(
|
|
hClusEnum, //handle to enum
|
|
dwIndex, //Index
|
|
&dwType, //Type
|
|
lpszName, //Name
|
|
&cchRetSize //Size of name
|
|
);
|
|
}
|
|
if ( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// Try to open this resource
|
|
//
|
|
hResource = OpenClusterResource( hCluster, lpszName );
|
|
|
|
if ( hResource == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
if ( dwStatus == ERROR_RESOURCE_NOT_FOUND )
|
|
{
|
|
//
|
|
// If the resource cannot be found, assume it got deleted after
|
|
// you opened the enumeration. So, skip the resource and proceed.
|
|
//
|
|
dwIndex ++;
|
|
dwStatus = ERROR_SUCCESS;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Indicate that will invoke the callback
|
|
//
|
|
fExecuteCallBack = TRUE;
|
|
|
|
// Determine if we need to check the type
|
|
//
|
|
if ( lpszResTypeName != NULL )
|
|
{
|
|
fExecuteCallBack = ResUtilResourceTypesEqual( lpszResTypeName, hResource );
|
|
|
|
} //if lpszResTypeName
|
|
|
|
|
|
if ( fExecuteCallBack && ( hSelf != NULL ) )
|
|
{
|
|
// Don't execute callback if hResource is callee (i.e., hSelf)
|
|
fExecuteCallBack = !(ResUtilResourcesEqual( hSelf, hResource ));
|
|
|
|
} //if fExecuteCallBack && hSelf
|
|
|
|
if ( fExecuteCallBack )
|
|
{
|
|
dwStatus = pResCallBack( hSelf, hResource, pParameter );
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
} //if fExecuteCallBack
|
|
|
|
CloseClusterResource( hResource );
|
|
hResource = NULL;
|
|
|
|
} // If ERROR_SUCCESS
|
|
|
|
dwIndex++;
|
|
} while ( dwStatus == ERROR_SUCCESS );
|
|
|
|
Cleanup:
|
|
|
|
if ( hClusEnum != NULL )
|
|
{
|
|
ClusterCloseEnum( hClusEnum );
|
|
}
|
|
|
|
if ( hCluster != NULL )
|
|
{
|
|
CloseCluster( hCluster );
|
|
}
|
|
|
|
if ( hResource != NULL )
|
|
{
|
|
CloseClusterResource( hResource );
|
|
}
|
|
|
|
if ( lpszName != szName )
|
|
{
|
|
LocalFree( lpszName );
|
|
}
|
|
|
|
if ( dwStatus == ERROR_NO_MORE_ITEMS )
|
|
{
|
|
dwStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return dwStatus;
|
|
|
|
} //*** ResUtilEnumResources()
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilEnumResourcesEx(
|
|
IN HCLUSTER hCluster,
|
|
IN HRESOURCE hSelf,
|
|
IN LPCWSTR lpszResTypeName,
|
|
IN LPRESOURCE_CALLBACK_EX pResCallBack,
|
|
IN PVOID pParameter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This is a generic resource walking routine. It enumerates all resources in
|
|
the cluster and invokes the callback function for each resource.
|
|
|
|
|
|
Arguments:
|
|
|
|
IN hCluster - A handle to the cluster to enumerate resources on.
|
|
|
|
IN [OPTIONAL] hSelf
|
|
- A handle to the resource. When enumerating resources do
|
|
not invoke the callback when the enumerated resource is
|
|
hSelf.
|
|
IF NULL then invoke the callback for all resources
|
|
|
|
IN [OPTIONAL] lpszResTypeName
|
|
- This is an optional resource type name. If specified the
|
|
callback function will only be invoked for resources of
|
|
this type.
|
|
|
|
IN pResCallBack - Pointer to function that gets called for each enumerated
|
|
resource in the cluster
|
|
|
|
IN pParameter - An Opaque callback parameter
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HCLUSENUM hClusEnum = NULL;
|
|
HRESOURCE hResource = NULL;
|
|
BOOL fExecuteCallBack;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR lpszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwIndex;
|
|
DWORD dwType;
|
|
|
|
//
|
|
// Get a resource enumeration handle
|
|
//
|
|
hClusEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
|
|
if ( hClusEnum == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Enumerate each resource in the cluster
|
|
//
|
|
dwIndex = 0;
|
|
|
|
do
|
|
{
|
|
cchRetSize = cchSize;
|
|
dwStatus = ClusterEnum(
|
|
hClusEnum, //handle to enum
|
|
dwIndex, //Index
|
|
&dwType, //Type
|
|
lpszName, //Name
|
|
&cchRetSize //Size of name
|
|
);
|
|
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( lpszName != szName )
|
|
{
|
|
LocalFree( lpszName );
|
|
}
|
|
lpszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( lpszName == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
break;
|
|
}
|
|
cchRetSize = cchSize;
|
|
dwStatus = ClusterEnum(
|
|
hClusEnum, //handle to enum
|
|
dwIndex, //Index
|
|
&dwType, //Type
|
|
lpszName, //Name
|
|
&cchRetSize //Size of name
|
|
);
|
|
}
|
|
if ( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// Try to open this resource
|
|
//
|
|
hResource = OpenClusterResource( hCluster, lpszName );
|
|
|
|
if ( hResource == NULL )
|
|
{
|
|
dwStatus = GetLastError();
|
|
if ( dwStatus == ERROR_RESOURCE_NOT_FOUND )
|
|
{
|
|
//
|
|
// If the resource cannot be found, assume it got deleted after
|
|
// you opened the enumeration. So, skip the resource and proceed.
|
|
//
|
|
dwIndex ++;
|
|
dwStatus = ERROR_SUCCESS;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Indicate that will invoke the callback
|
|
//
|
|
fExecuteCallBack = TRUE;
|
|
|
|
// Determine if we need to check the type
|
|
//
|
|
if ( lpszResTypeName != NULL )
|
|
{
|
|
fExecuteCallBack = ResUtilResourceTypesEqual( lpszResTypeName, hResource );
|
|
|
|
} //if lpszResTypeName
|
|
|
|
|
|
if ( fExecuteCallBack && ( hSelf != NULL ) )
|
|
{
|
|
// Don't execute callback if hResource is callee (i.e., hSelf)
|
|
fExecuteCallBack = !(ResUtilResourcesEqual( hSelf, hResource ));
|
|
|
|
} //if fExecuteCallBack && hSelf
|
|
|
|
if ( fExecuteCallBack )
|
|
{
|
|
dwStatus = pResCallBack( hCluster, hSelf, hResource, pParameter );
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
} //if fExecuteCallBack
|
|
|
|
CloseClusterResource( hResource );
|
|
hResource = NULL;
|
|
|
|
} // If ERROR_SUCCESS
|
|
|
|
dwIndex++;
|
|
} while ( dwStatus == ERROR_SUCCESS );
|
|
|
|
Cleanup:
|
|
|
|
if ( hClusEnum != NULL )
|
|
{
|
|
ClusterCloseEnum( hClusEnum );
|
|
}
|
|
|
|
if ( hResource != NULL )
|
|
{
|
|
CloseClusterResource( hResource );
|
|
}
|
|
|
|
if ( lpszName != szName )
|
|
{
|
|
LocalFree( lpszName );
|
|
}
|
|
|
|
if ( dwStatus == ERROR_NO_MORE_ITEMS )
|
|
{
|
|
dwStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return dwStatus;
|
|
|
|
} //*** ResUtilEnumResourcesEx()
|
|
|
|
|
|
|
|
HRESOURCE
|
|
WINAPI
|
|
ResUtilGetResourceDependency(
|
|
IN HANDLE hSelf,
|
|
IN LPCWSTR lpszResourceType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a dependent resource for the local cluster.
|
|
|
|
Arguments:
|
|
|
|
hSelf - A handle to the original resource.
|
|
|
|
lpszResourceType - the type of resource that it depends on
|
|
|
|
|
|
Return Value:
|
|
|
|
NULL - error (use GetLastError() to get further info)
|
|
|
|
NON-NULL - Handle to a resource of type ResourceType
|
|
|
|
--*/
|
|
{
|
|
HRESOURCE hResDepends = NULL;
|
|
HCLUSTER hCluster = NULL;
|
|
HRESENUM hResEnum = NULL;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR pszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwType = 0;
|
|
DWORD dwIndex = 0;
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
|
|
hCluster = OpenCluster( NULL );
|
|
if ( hCluster == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
|
|
if ( hResEnum == NULL ) {
|
|
status = GetLastError();
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
do {
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Determine the type of resource found
|
|
//
|
|
hResDepends = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( hResDepends != NULL ) {
|
|
//
|
|
// Valid resource now open the reg and get it's type
|
|
//
|
|
if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
|
|
break;
|
|
}
|
|
|
|
} //if !hResDepends
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends != NULL ) {
|
|
CloseClusterResource( hResDepends );
|
|
hResDepends = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while ( status == ERROR_SUCCESS );
|
|
|
|
error_exit:
|
|
//
|
|
// At this point hResDepends is NULL if no match or non-null (success)
|
|
//
|
|
if ( hCluster != NULL ) {
|
|
CloseCluster( hCluster );
|
|
}
|
|
|
|
if ( hResEnum != NULL ) {
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
}
|
|
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS ) {
|
|
SetLastError( status );
|
|
}
|
|
return(hResDepends);
|
|
|
|
} //*** ResUtilGetResourceDependency()
|
|
|
|
|
|
HRESOURCE
|
|
WINAPI
|
|
ResUtilGetResourceDependencyByName(
|
|
IN HCLUSTER hCluster,
|
|
IN HANDLE hSelf,
|
|
IN LPCWSTR lpszResourceType,
|
|
IN BOOL bRecurse
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a dependent resource for a specified cluster based on the resource
|
|
type name.
|
|
|
|
Arguments:
|
|
|
|
hCluster - Cluster to query.
|
|
|
|
hSelf - A handle to the original resource.
|
|
|
|
lpszResourceType - The name of the resource type of the resource that the
|
|
specified resource depends on.
|
|
|
|
bRecurse - TRUE = check dependents of dependents. An immediate dependency
|
|
will be returned if there is one.
|
|
|
|
Return Value:
|
|
|
|
NULL - error (use GetLastError() to get further info)
|
|
|
|
NON-NULL - Handle to a resource of type lpszResourceType
|
|
|
|
--*/
|
|
{
|
|
HRESOURCE hResDepends = NULL;
|
|
HRESOURCE hResDepends2 = NULL;
|
|
HRESENUM hResEnum = NULL;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR pszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwType = 0;
|
|
DWORD dwIndex = 0;
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
if ( ( hCluster == NULL ) || ( lpszResourceType == NULL ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return NULL;
|
|
} // if: no cluster handle or resource type name specified
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
|
|
if ( hResEnum == NULL ) {
|
|
status = GetLastError();
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
do {
|
|
//
|
|
// Get the next dependent resource.
|
|
//
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Open the resource.
|
|
//
|
|
hResDepends = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Resource is valid. Now see if it is the right type.
|
|
//
|
|
if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends != NULL ) {
|
|
CloseClusterResource( hResDepends );
|
|
hResDepends = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while ( status == ERROR_SUCCESS );
|
|
|
|
//
|
|
// If a match was not found, recurse the dependencies again looking for a
|
|
// dependency of the dependencies if the bDeep argument was specified.
|
|
//
|
|
if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) && bRecurse ) {
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
|
|
if ( hResEnum == NULL ) {
|
|
status = GetLastError();
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
dwIndex = 0;
|
|
do {
|
|
//
|
|
// Get the next dependent resource.
|
|
//
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Open the resource.
|
|
//
|
|
hResDepends2 = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends2 == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Recursively call ourselves with this resource.
|
|
//
|
|
hResDepends = ResUtilGetResourceDependencyByName(
|
|
hCluster,
|
|
hResDepends2,
|
|
lpszResourceType,
|
|
bRecurse
|
|
);
|
|
if ( hResDepends != NULL ) {
|
|
break;
|
|
}
|
|
status = GetLastError();
|
|
if ( status != ERROR_RESOURCE_NOT_FOUND ) {
|
|
break;
|
|
}
|
|
status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends2 != NULL ) {
|
|
CloseClusterResource( hResDepends2 );
|
|
hResDepends2 = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while ( status == ERROR_SUCCESS );
|
|
}
|
|
|
|
error_exit:
|
|
if ( hResEnum != NULL ) {
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
}
|
|
|
|
if ( hResDepends2 != NULL ) {
|
|
CloseClusterResource( hResDepends2 );
|
|
}
|
|
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
|
|
if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) ) {
|
|
status = ERROR_RESOURCE_NOT_FOUND;
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
SetLastError( status );
|
|
}
|
|
|
|
return hResDepends;
|
|
|
|
} //*** ResUtilGetResourceDependencyByName()
|
|
|
|
|
|
HRESOURCE
|
|
WINAPI
|
|
ResUtilGetResourceDependencyByClass(
|
|
IN HCLUSTER hCluster,
|
|
IN HANDLE hSelf,
|
|
IN PCLUS_RESOURCE_CLASS_INFO prci,
|
|
IN BOOL bRecurse
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a dependent resource for a specified cluster based on the resource
|
|
type class information.
|
|
|
|
Arguments:
|
|
|
|
hCluster - Cluster to query.
|
|
|
|
hSelf - A handle to the original resource.
|
|
|
|
prci - The resource class info of the resource type of the resource that
|
|
the specified resource depends on.
|
|
|
|
bRecurse - TRUE = check dependents of dependents. An immediate dependency
|
|
will be returned if there is one.
|
|
|
|
Return Value:
|
|
|
|
NULL - error (use GetLastError() to get further info)
|
|
|
|
NON-NULL - Handle to a resource whose class is specified by prci.
|
|
|
|
--*/
|
|
{
|
|
HRESOURCE hResDepends = NULL;
|
|
HRESOURCE hResDepends2 = NULL;
|
|
HRESENUM hResEnum = NULL;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR pszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwType = 0;
|
|
DWORD dwIndex = 0;
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
if ( ( hCluster == NULL ) || ( prci == NULL ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return NULL;
|
|
} // if: no cluster handle or class info specified
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
|
|
if ( hResEnum == NULL ) {
|
|
status = GetLastError();
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
do {
|
|
//
|
|
// Get the next dependent resource.
|
|
//
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Determine the type of resource found
|
|
//
|
|
hResDepends = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Resource is valid. Now see if it is the right class.
|
|
//
|
|
if ( ResUtilIsResourceClassEqual( prci, hResDepends ) ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends != NULL ) {
|
|
CloseClusterResource( hResDepends );
|
|
hResDepends = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while ( status == ERROR_SUCCESS );
|
|
|
|
//
|
|
// If a match was not found, recurse the dependencies again looking for a
|
|
// dependency of the dependencies if the bDeep argument was specified.
|
|
//
|
|
if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) && bRecurse ) {
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
|
|
if ( hResEnum == NULL ) {
|
|
status = GetLastError();
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
dwIndex = 0;
|
|
do {
|
|
//
|
|
// Get the next dependent resource.
|
|
//
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating null
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Open the resource.
|
|
//
|
|
hResDepends2 = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends2 == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Recursively call ourselves with this resource.
|
|
//
|
|
hResDepends = ResUtilGetResourceDependencyByClass(
|
|
hCluster,
|
|
hResDepends2,
|
|
prci,
|
|
bRecurse
|
|
);
|
|
if ( hResDepends != NULL ) {
|
|
break;
|
|
}
|
|
status = GetLastError();
|
|
if ( status != ERROR_RESOURCE_NOT_FOUND ) {
|
|
break;
|
|
}
|
|
status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends2 != NULL ) {
|
|
CloseClusterResource( hResDepends2 );
|
|
hResDepends2 = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while ( status == ERROR_SUCCESS );
|
|
}
|
|
|
|
error_exit:
|
|
if ( hResEnum != NULL ) {
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
}
|
|
|
|
if ( hResDepends2 != NULL ) {
|
|
CloseClusterResource( hResDepends2 );
|
|
}
|
|
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
|
|
if ( ( status == ERROR_SUCCESS ) && ( hResDepends == NULL ) ) {
|
|
status = ERROR_RESOURCE_NOT_FOUND;
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
SetLastError( status );
|
|
}
|
|
|
|
return hResDepends;
|
|
|
|
} //*** ResUtilGetResourceDependencyByClass()
|
|
|
|
|
|
HRESOURCE
|
|
WINAPI
|
|
ResUtilGetResourceNameDependency(
|
|
IN LPCWSTR lpszResourceName,
|
|
IN LPCWSTR lpszResourceType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a dependent resource
|
|
|
|
Arguments:
|
|
|
|
lpszResourceName - the name of the resource
|
|
|
|
lpszResourceType - the type of the resource that it depends on
|
|
|
|
|
|
Return Value:
|
|
|
|
NULL - error (use GetLastError() to get further info)
|
|
|
|
NON-NULL - Handle to a resource of type ResourceType
|
|
|
|
--*/
|
|
{
|
|
HRESOURCE hResDepends = NULL;
|
|
HCLUSTER hCluster = NULL;
|
|
HRESOURCE hSelf = NULL;
|
|
HRESENUM hResEnum = NULL;
|
|
WCHAR szName[ __INITIAL_NAME_LENGTH ];
|
|
LPWSTR pszName = szName;
|
|
DWORD cchSize = __INITIAL_NAME_LENGTH;
|
|
DWORD cchRetSize;
|
|
DWORD dwType = 0;
|
|
DWORD dwIndex = 0;
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
if ( lpszResourceName == NULL ) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return( NULL );
|
|
}
|
|
|
|
hCluster = OpenCluster( NULL );
|
|
if ( hCluster == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// Open a handle to the passed in resource name.
|
|
//
|
|
hSelf = OpenClusterResource( hCluster, lpszResourceName );
|
|
if ( hSelf == NULL ) {
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Open the depends on enum (get resource dependencies)
|
|
//
|
|
hResEnum = ClusterResourceOpenEnum( hSelf, CLUSTER_RESOURCE_ENUM_DEPENDS );
|
|
if ( hResEnum == NULL ) {
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the depends on keys
|
|
//
|
|
do {
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// Output name buffer is too small. Allocate a new one.
|
|
//
|
|
cchSize = cchRetSize + 1; // Add room for terminating NULL
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
pszName = LocalAlloc( LMEM_FIXED, cchSize * sizeof(WCHAR) );
|
|
if ( pszName == NULL ) {
|
|
status = GetLastError();
|
|
break;
|
|
} // if: error allocating memory
|
|
cchRetSize = cchSize;
|
|
status = ClusterResourceEnum( hResEnum, dwIndex, &dwType, pszName, &cchRetSize );
|
|
}
|
|
if ( status != ERROR_SUCCESS ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Determine the type of resource found
|
|
//
|
|
hResDepends = OpenClusterResource( hCluster, pszName );
|
|
if ( hResDepends == NULL ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Valid resource now open the reg and get it's type
|
|
//
|
|
if ( ResUtilResourceTypesEqual( lpszResourceType, hResDepends ) ) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Close all handles, key's
|
|
//
|
|
if ( hResDepends != NULL ) {
|
|
CloseClusterResource( hResDepends );
|
|
hResDepends = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
} while (status == ERROR_SUCCESS);
|
|
|
|
error_exit:
|
|
//
|
|
// At this point hResDepends is NULL if no match or non-null (success)
|
|
//
|
|
if ( hCluster != NULL ) {
|
|
CloseCluster( hCluster );
|
|
}
|
|
|
|
if ( hSelf != NULL ) {
|
|
CloseClusterResource( hSelf );
|
|
}
|
|
|
|
if ( hResEnum != NULL ) {
|
|
ClusterResourceCloseEnum( hResEnum );
|
|
}
|
|
|
|
if ( pszName != szName ) {
|
|
LocalFree( pszName );
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS ) {
|
|
SetLastError( status );
|
|
}
|
|
|
|
return hResDepends;
|
|
|
|
} //*** ResUtilGetResourceNameDependency()
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
ResUtilGetPropertyFormats(
|
|
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
|
OUT PVOID pOutPropertyFormatList,
|
|
IN DWORD cbPropertyFormatListSize,
|
|
OUT LPDWORD pcbBytesReturned,
|
|
OUT LPDWORD pcbRequired
|
|
)
|
|
{
|
|
return( ClRtlGetPropertyFormats( pPropertyTable,
|
|
pOutPropertyFormatList,
|
|
cbPropertyFormatListSize,
|
|
pcbBytesReturned,
|
|
pcbRequired ) );
|
|
|
|
} // ResUtilGetPropertyFormats()
|
|
|