7999 lines
281 KiB
C++
7999 lines
281 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rtlprop.c
|
||
|
||
Abstract:
|
||
|
||
Implements the management of properties.
|
||
|
||
Author:
|
||
|
||
Rod Gamache (rodga) 7-Jan-1996
|
||
|
||
Revision History:
|
||
|
||
David Potter (davidp) 12-Mar-1997
|
||
Moved to CLUSRTL.
|
||
|
||
--*/
|
||
|
||
#define UNICODE 1
|
||
#define _UNICODE 1
|
||
|
||
#include "clusrtlp.h"
|
||
#include "stdio.h"
|
||
#include "stdlib.h"
|
||
#include "RegistryValueName.h"
|
||
|
||
#define CLRTL_NULL_STRING L"\0"
|
||
|
||
//
|
||
// Data alignment notes
|
||
//
|
||
// All data (including embedded pointers) are aligned on 32b boundaries (64b
|
||
// platforms where not a consideration when this code was originally
|
||
// written). This makes some of the typecasting a bit tricky since the
|
||
// embedded pointers are really pointers to pointers. All double star pointers
|
||
// (i.e., LPBYTE *) have to use UNALIGNED since it is possible that the
|
||
// starting address of the pointer, i.e., the value contained in the variable,
|
||
// could end in a 4 (which on 64b. platforms is unaligned). (LPBYTE *) becomes
|
||
// (LPBYTE UNALIGNED *) or BYTE * UNALIGNED *.
|
||
//
|
||
// Consider these statements from below:
|
||
//
|
||
// LPWSTR UNALIGNED * ppszOutValue;
|
||
// ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
//
|
||
// ppszOutValue is an automatic variable so its address is guaranteed to be
|
||
// aligned. pOutParams is essentially an array of DWORDS (though we make no
|
||
// effort to enforce this. If that changed, property lists would be broken in
|
||
// many different places). It is possible that when we take the address of
|
||
// pOutParams + Offset, the offset may be on a DWORD boundary and not a QUAD
|
||
// boundary. Therefore we have to treat ppszOutValue's value (a pointer to
|
||
// WCHAR) as unaligned (the data itself is properly aligned). You can read the
|
||
// typecast as "an aligned pointer (ppszOutValue) to an unaligned pointer
|
||
// (address of pOutParams[Offset]) to an aligned WCHAR."
|
||
//
|
||
// LARGE_INTEGER allows us to "cheat" in that we can leverage the internal
|
||
// struct definition of LARGER_INTEGER to do 2 DWORD copies instead of
|
||
// treating the data for worst-case alignment.
|
||
//
|
||
// ISSUE-01/03/16 charlwi CLUSPROP_BUFFER_HELPER might not be correctly aligned
|
||
//
|
||
// still unsure about this but seeing how the whole property thing is
|
||
// 32b. aligned and this structure is used copiously for casting (at DWORD
|
||
// boundaries), the potential exists to have a pointer that is not QUADWORD
|
||
// aligned. When we go to deref it, we get an alignment fault.
|
||
//
|
||
|
||
//
|
||
// Static function prototypes.
|
||
//
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetDwordProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_DWORD pInDwordValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetLongProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_LONG pInLongValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetULargeIntegerProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_ULARGE_INTEGER pInULargeIntegerValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetLargeIntegerProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_LARGE_INTEGER pInLargeIntegerValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetStringProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_SZ pInStringValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetMultiStringProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_MULTI_SZ pInMultiStringValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetBinaryProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_BINARY pInBinaryValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
);
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlEnumProperties(
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD totalBufferLength = 0;
|
||
PRESUTIL_PROPERTY_ITEM property;
|
||
LPWSTR psz = pszOutProperties;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
if ( pPropertyTable == NULL ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlEnumProperties: pPropertyTable == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pszOutProperties != NULL ) {
|
||
ZeroMemory( pszOutProperties, cbOutPropertiesSize );
|
||
}
|
||
|
||
//
|
||
// Get the size of all property names for this object.
|
||
//
|
||
for ( property = pPropertyTable ; property->Name != NULL ; property++ ) {
|
||
totalBufferLength += (lstrlenW( property->Name ) + 1) * sizeof(WCHAR);
|
||
}
|
||
|
||
totalBufferLength += sizeof(UNICODE_NULL);
|
||
|
||
//
|
||
// If the output buffer is big enough, copy the property names.
|
||
//
|
||
if ( totalBufferLength > cbOutPropertiesSize ) {
|
||
*pcbRequired = totalBufferLength;
|
||
totalBufferLength = 0;
|
||
if ( pszOutProperties == NULL ) {
|
||
status = ERROR_SUCCESS;
|
||
} else {
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
} else {
|
||
DWORD cchCurrentNameSize;
|
||
for ( property = pPropertyTable ; property->Name != NULL ; property++ ) {
|
||
lstrcpyW( psz, property->Name );
|
||
cchCurrentNameSize = lstrlenW( psz ) + 1;
|
||
*pcbBytesReturned += cchCurrentNameSize * sizeof(WCHAR);
|
||
psz += cchCurrentNameSize;
|
||
}
|
||
|
||
*psz = L'\0';
|
||
*pcbBytesReturned += sizeof(WCHAR);
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlEnumProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlEnumPrivateProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD totalBufferLength = 0;
|
||
LPWSTR psz = pszOutProperties;
|
||
DWORD ival;
|
||
DWORD currentNameLength = 20;
|
||
DWORD nameLength;
|
||
DWORD dataLength;
|
||
DWORD type;
|
||
LPWSTR pszName;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
//
|
||
// Validate inputs
|
||
//
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis == NULL) ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlEnumPrivateProperties: hkeyClusterKey or pClusterRegApis == NULL. "
|
||
"Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pszOutProperties != NULL ) {
|
||
ZeroMemory( pszOutProperties, cbOutPropertiesSize );
|
||
}
|
||
|
||
//
|
||
// Allocate a property name buffer.
|
||
//
|
||
pszName = static_cast< LPWSTR >( LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) ) );
|
||
if ( pszName == NULL ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
//
|
||
// Enumerate all properties to find the total size.
|
||
//
|
||
ival = 0;
|
||
while ( TRUE ) {
|
||
//
|
||
// Read the next property.
|
||
//
|
||
nameLength = currentNameLength;
|
||
dataLength = 0;
|
||
status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
|
||
ival,
|
||
pszName,
|
||
&nameLength,
|
||
&type,
|
||
NULL,
|
||
&dataLength );
|
||
if ( status == ERROR_NO_MORE_ITEMS ) {
|
||
status = ERROR_SUCCESS;
|
||
break;
|
||
} else if ( status == ERROR_MORE_DATA ) {
|
||
|
||
CL_ASSERT( (nameLength+1) > currentNameLength );
|
||
|
||
LocalFree( pszName );
|
||
|
||
currentNameLength = nameLength + 1; // returned value doesn't include terminating NULL
|
||
pszName = static_cast< LPWSTR >( LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) ) );
|
||
if ( pszName == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
|
||
continue; // retry
|
||
|
||
} else if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
totalBufferLength += (nameLength + 1) * sizeof(WCHAR);
|
||
++ival;
|
||
}
|
||
|
||
//
|
||
// Continue only if the operations so far have been successful.
|
||
//
|
||
if ( status == ERROR_SUCCESS ) {
|
||
|
||
if ( totalBufferLength != 0 ) {
|
||
totalBufferLength += sizeof(UNICODE_NULL);
|
||
}
|
||
|
||
//
|
||
// If the output buffer is big enough, copy the property names.
|
||
//
|
||
if ( totalBufferLength > cbOutPropertiesSize ) {
|
||
*pcbRequired = totalBufferLength;
|
||
totalBufferLength = 0;
|
||
if ( (pszOutProperties == NULL) ||
|
||
(cbOutPropertiesSize == 0) ) {
|
||
status = ERROR_SUCCESS;
|
||
} else {
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
} else if ( totalBufferLength != 0 ) {
|
||
//
|
||
// Enumerate all properties for copying
|
||
//
|
||
for ( ival = 0; ; ival++ ) {
|
||
//
|
||
// Read the next property.
|
||
//
|
||
nameLength = currentNameLength;
|
||
dataLength = 0;
|
||
status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
|
||
ival,
|
||
pszName,
|
||
&nameLength,
|
||
&type,
|
||
NULL,
|
||
&dataLength );
|
||
|
||
if ( status == ERROR_NO_MORE_ITEMS ) {
|
||
status = ERROR_SUCCESS;
|
||
break;
|
||
} else if ( status == ERROR_MORE_DATA ) {
|
||
CL_ASSERT( 0 ); // THIS SHOULDN'T HAPPEN
|
||
} else if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//CL_ASSERT( (DWORD)lstrlenW( name ) == nameLength );
|
||
lstrcpyW( psz, pszName );
|
||
psz += nameLength + 1;
|
||
*pcbBytesReturned += (nameLength + 1) * sizeof(WCHAR);
|
||
}
|
||
|
||
*psz = L'\0';
|
||
*pcbBytesReturned += sizeof(WCHAR);
|
||
}
|
||
}
|
||
|
||
LocalFree( pszName );
|
||
|
||
return(status);
|
||
|
||
} // ClRtlEnumPrivateProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
OUT PVOID pOutPropertyList,
|
||
IN DWORD cbOutPropertyListSize,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property list to process.
|
||
|
||
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_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 = ERROR_SUCCESS;
|
||
DWORD itemCount = 0;
|
||
DWORD totalBufferLength = 0;
|
||
PVOID outBuffer = pOutPropertyList;
|
||
DWORD bufferLength = cbOutPropertyListSize;
|
||
PRESUTIL_PROPERTY_ITEM property;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis == NULL) ||
|
||
(pPropertyTable == NULL) ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetProperties: hkeyClusterKey, pClusterRegApis, or "
|
||
"pPropertyTable == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pOutPropertyList != NULL ) {
|
||
ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
|
||
}
|
||
|
||
//
|
||
// Get the size of all properties for this object.
|
||
//
|
||
property = pPropertyTable;
|
||
while ( property->Name != NULL ) {
|
||
status = ClRtlGetPropertySize( hkeyClusterKey,
|
||
pClusterRegApis,
|
||
property,
|
||
&totalBufferLength,
|
||
&itemCount );
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
property++;
|
||
}
|
||
|
||
|
||
//
|
||
// Continue only if the operations so far have been successful.
|
||
//
|
||
if ( status == ERROR_SUCCESS ) {
|
||
//
|
||
// Count for item count at front of return data and endmark.
|
||
//
|
||
totalBufferLength += sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
|
||
|
||
//
|
||
// Verify the size of all the properties
|
||
//
|
||
if ( totalBufferLength > cbOutPropertyListSize ) {
|
||
*pcbRequired = totalBufferLength;
|
||
totalBufferLength = 0;
|
||
if ( pOutPropertyList == NULL ) {
|
||
status = ERROR_SUCCESS;
|
||
} else {
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
}
|
||
else {
|
||
*(LPDWORD)outBuffer = itemCount;
|
||
outBuffer = (PVOID)( (PUCHAR)outBuffer + sizeof(itemCount) );
|
||
bufferLength -= sizeof(itemCount);
|
||
|
||
//
|
||
// Now fetch all of the properties.
|
||
//
|
||
property = pPropertyTable;
|
||
while ( property->Name != NULL ) {
|
||
status = ClRtlGetProperty( hkeyClusterKey,
|
||
pClusterRegApis,
|
||
property,
|
||
&outBuffer,
|
||
&bufferLength );
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
property++;
|
||
}
|
||
|
||
// Don't forget the ENDMARK
|
||
*(LPDWORD)outBuffer = CLUSPROP_SYNTAX_ENDMARK;
|
||
|
||
if ( (status != ERROR_SUCCESS) &&
|
||
(status != ERROR_MORE_DATA) ) {
|
||
totalBufferLength = 0;
|
||
}
|
||
}
|
||
|
||
*pcbBytesReturned = totalBufferLength;
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetAllProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
OUT PVOID pOutPropertyList,
|
||
IN DWORD cbOutPropertyListSize,
|
||
OUT LPDWORD pcbReturned,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
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_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER cbhKnownPropBuffer;
|
||
CLUSPROP_BUFFER_HELPER cbhUnknownPropBuffer;
|
||
DWORD cbKnownPropBufferSize;
|
||
DWORD cbUnknownPropBufferSize;
|
||
DWORD sc = ERROR_SUCCESS;
|
||
DWORD scUnknown;
|
||
DWORD dwSavedData;
|
||
DWORD cbUnknownRequired = 0;
|
||
DWORD cbUnknownReturned = 0;
|
||
|
||
|
||
cbhKnownPropBuffer.pb = static_cast< LPBYTE >( pOutPropertyList );
|
||
cbKnownPropBufferSize = cbOutPropertyListSize;
|
||
|
||
//
|
||
// First get the 'known' properties.
|
||
//
|
||
sc = ClRtlGetProperties(
|
||
hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
cbhKnownPropBuffer.pb,
|
||
cbKnownPropBufferSize,
|
||
pcbReturned,
|
||
pcbRequired
|
||
);
|
||
|
||
if ( sc != ERROR_SUCCESS )
|
||
{
|
||
*pcbReturned = 0;
|
||
|
||
if ( sc != ERROR_MORE_DATA )
|
||
{
|
||
*pcbRequired = 0;
|
||
return sc;
|
||
}
|
||
|
||
// We already know that there is insufficient space.
|
||
scUnknown = ClRtlGetUnknownProperties(
|
||
hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
NULL,
|
||
0,
|
||
&cbUnknownReturned,
|
||
&cbUnknownRequired
|
||
);
|
||
|
||
if ( ( scUnknown != ERROR_SUCCESS ) &&
|
||
( scUnknown != ERROR_MORE_DATA ) )
|
||
{
|
||
*pcbRequired = 0;
|
||
return scUnknown;
|
||
}
|
||
|
||
//
|
||
// If both known and unknown properties exist, only one endmark
|
||
// is required. So, subtract endmark size from total required size.
|
||
//
|
||
if ( ( *pcbRequired > sizeof(DWORD) ) &&
|
||
( cbUnknownRequired > sizeof(DWORD) ) )
|
||
{
|
||
*pcbRequired -= sizeof(CLUSPROP_SYNTAX);
|
||
}
|
||
|
||
//
|
||
// Subtract off the size of the property count for the
|
||
// unknown property list.
|
||
//
|
||
*pcbRequired += cbUnknownRequired - sizeof(DWORD);
|
||
return sc;
|
||
} // if: call to ClRtlGetProperties failed
|
||
|
||
// If we are here then the call to ClRtlGetProperties succeeded.
|
||
|
||
//
|
||
// Calculate the position in the output buffer where unknown properties
|
||
// should be stored. Subtract off the size of the property count for
|
||
// the unknown property list. These calculations will cause the buffer
|
||
// pointer to overlap the known property list buffer by one DWORD.
|
||
//
|
||
cbhUnknownPropBuffer.pb = cbhKnownPropBuffer.pb + *pcbReturned - sizeof(DWORD);
|
||
cbUnknownPropBufferSize = cbKnownPropBufferSize - *pcbReturned + sizeof(DWORD);
|
||
|
||
// If there are known properties, move the unknown property list
|
||
// buffer pointer to overlap that as well.
|
||
if ( *pcbReturned > sizeof(DWORD) )
|
||
{
|
||
cbhUnknownPropBuffer.pb -= sizeof(CLUSPROP_SYNTAX);
|
||
cbUnknownPropBufferSize += sizeof(CLUSPROP_SYNTAX);
|
||
} // if: a nonzero number of properties has been returned.
|
||
|
||
//
|
||
// Save the DWORD we are about to overlap.
|
||
//
|
||
dwSavedData = *(cbhUnknownPropBuffer.pdw);
|
||
|
||
scUnknown = ClRtlGetUnknownProperties(
|
||
hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
cbhUnknownPropBuffer.pb,
|
||
cbUnknownPropBufferSize,
|
||
&cbUnknownReturned,
|
||
&cbUnknownRequired
|
||
);
|
||
|
||
if ( scUnknown == ERROR_SUCCESS )
|
||
{
|
||
//
|
||
// The order of the next three statements is very important
|
||
// since the known and the unknown property buffers can overlap.
|
||
//
|
||
DWORD nUnknownPropCount = cbhUnknownPropBuffer.pList->nPropertyCount;
|
||
*(cbhUnknownPropBuffer.pdw) = dwSavedData;
|
||
cbhKnownPropBuffer.pList->nPropertyCount += nUnknownPropCount;
|
||
|
||
//
|
||
// If both known and unknown properties exist, only one endmark
|
||
// is required. So, subtract endmark size from total returned size.
|
||
//
|
||
if ( ( *pcbReturned > sizeof(DWORD) ) &&
|
||
( cbUnknownReturned > sizeof(DWORD) ) )
|
||
{
|
||
*pcbReturned -= sizeof(CLUSPROP_SYNTAX);
|
||
}
|
||
|
||
//
|
||
// Add in the size of the unknown property list minus the
|
||
// size of the unknown property list property count.
|
||
//
|
||
*pcbReturned += cbUnknownReturned - sizeof(DWORD);
|
||
*pcbRequired = 0;
|
||
|
||
} // if: call to ClRtlGetUnknownProperties succeeded
|
||
else
|
||
{
|
||
if ( scUnknown == ERROR_MORE_DATA )
|
||
{
|
||
*pcbRequired = *pcbReturned;
|
||
*pcbReturned = 0;
|
||
|
||
//
|
||
// Both known and unknown properties exist. Only one endmark
|
||
// is required. So, subtract endmark size from total required size.
|
||
//
|
||
if ( ( *pcbRequired > sizeof(DWORD) ) &&
|
||
( cbUnknownRequired > sizeof(DWORD) ) )
|
||
{
|
||
*pcbRequired -= sizeof(CLUSPROP_SYNTAX);
|
||
}
|
||
|
||
//
|
||
// Add in the size of the unknown property list minus the
|
||
// size of the unknown property list property count.
|
||
//
|
||
*pcbRequired += cbUnknownRequired - sizeof(DWORD);
|
||
|
||
} // if: ClRtlGetUnknownProperties returned ERROR_MORE_DATA
|
||
else
|
||
{
|
||
*pcbRequired = 0;
|
||
*pcbReturned = 0;
|
||
|
||
} // else: ClRtlGetUnknownProperties failed for some unknown reason.
|
||
|
||
} // else: Call to ClRtlGetUnknownProperties failed.
|
||
|
||
return scUnknown;
|
||
|
||
} //*** ClRtlGetAllProperties()
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPropertiesToParameterBlock(
|
||
IN HKEY hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
IN OUT LPBYTE pOutParams,
|
||
IN BOOL bCheckForRequiredProperties,
|
||
OUT OPTIONAL LPWSTR * pszNameOfPropInError
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Read properties based on a property table.
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - Supplies the cluster key where the properties are stored.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
pOutParams - Parameter block to read into.
|
||
|
||
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 - Properties read successfully.
|
||
|
||
ERROR_INVALID_DATA - Required property not present.
|
||
|
||
ERROR_INVALID_PARAMETER -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
|
||
HKEY key;
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD valueType;
|
||
DWORD valueSize;
|
||
LPWSTR pszInValue;
|
||
LPBYTE pbInValue;
|
||
DWORD dwInValue;
|
||
LPWSTR UNALIGNED * ppszOutValue;
|
||
LPBYTE UNALIGNED * ppbOutValue;
|
||
DWORD * pdwOutValue;
|
||
LONG * plOutValue;
|
||
ULARGE_INTEGER * pullOutValue;
|
||
LARGE_INTEGER * pllOutValue;
|
||
CRegistryValueName rvn;
|
||
|
||
|
||
if ( pszNameOfPropInError != NULL ) {
|
||
*pszNameOfPropInError = NULL;
|
||
}
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pPropertyTable == NULL) ||
|
||
(pOutParams == NULL) ||
|
||
(pClusterRegApis == NULL) ||
|
||
(pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ||
|
||
(pClusterRegApis->pfnQueryValue == NULL) ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetPropertiesToParameterBlock: hkeyClusterKey, pPropertyTable, "
|
||
"pOutParams, pClusterRegApis, or required pfns == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
while ( propertyItem->Name != NULL ) {
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
|
||
DWORD disposition;
|
||
|
||
status = (*pClusterRegApis->pfnOpenKey)(
|
||
hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_ALL_ACCESS,
|
||
(void **) &key
|
||
);
|
||
|
||
// If key could not be opened, then we may need to put the default value
|
||
// for the property item.
|
||
if ( status != ERROR_SUCCESS ) {
|
||
status = ERROR_FILE_NOT_FOUND;
|
||
}
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
switch ( propertyItem->Format ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
|
||
valueSize = sizeof(DWORD);
|
||
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE) pdwOutValue,
|
||
&valueSize );
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( valueType != REG_DWORD ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
|
||
"expected to be REG_DWORD (%2!d!), was %3!d!.\n",
|
||
propertyItem->Name, REG_DWORD, valueType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
}
|
||
} else if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
! bCheckForRequiredProperties) ) {
|
||
*pdwOutValue = propertyItem->Default;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_LONG:
|
||
plOutValue = (LONG *) &pOutParams[propertyItem->Offset];
|
||
valueSize = sizeof(LONG);
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE) plOutValue,
|
||
&valueSize );
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( valueType != REG_DWORD ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
|
||
"expected to be REG_DWORD (%2!d!), was %3!d!.\n",
|
||
propertyItem->Name, REG_DWORD, valueType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
}
|
||
} else if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
!bCheckForRequiredProperties) ) {
|
||
*plOutValue = propertyItem->Default;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
|
||
valueSize = sizeof(ULARGE_INTEGER);
|
||
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE) pullOutValue,
|
||
&valueSize );
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( valueType != REG_QWORD ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
|
||
"expected to be REG_QWORD (%2!d!), was %3!d!.\n",
|
||
propertyItem->Name, REG_QWORD, valueType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
}
|
||
} else if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
! bCheckForRequiredProperties) ) {
|
||
pullOutValue->u = propertyItem->ULargeIntData->Default.u;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
pllOutValue = (LARGE_INTEGER *) &pOutParams[propertyItem->Offset];
|
||
valueSize = sizeof(LARGE_INTEGER);
|
||
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE) pllOutValue,
|
||
&valueSize );
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( valueType != REG_QWORD ) {
|
||
|
||
ClRtlDbgPrint( LOG_CRITICAL,
|
||
"ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
|
||
"expected to be REG_QWORD (%2!d!), was %3!d!.\n",
|
||
propertyItem->Name, REG_QWORD, valueType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
}
|
||
} else if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
! bCheckForRequiredProperties) )
|
||
{
|
||
pllOutValue->u = propertyItem->LargeIntData->Default.u;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
pszInValue = ClRtlGetSzValue( key,
|
||
rvn.PszName(),
|
||
pClusterRegApis );
|
||
}
|
||
else {
|
||
pszInValue = NULL;
|
||
SetLastError(status);
|
||
}
|
||
|
||
if ( pszInValue == NULL ) {
|
||
status = GetLastError();
|
||
if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
! bCheckForRequiredProperties) ) {
|
||
|
||
status = ERROR_SUCCESS;
|
||
|
||
// Deallocate old value.
|
||
if ( *ppszOutValue != NULL ) {
|
||
LocalFree( *ppszOutValue );
|
||
*ppszOutValue = NULL;
|
||
}
|
||
|
||
// If a default is specified, copy it.
|
||
if ( propertyItem->lpDefault != NULL ) {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( (LPCWSTR) propertyItem->lpDefault ) + 1) * sizeof(WCHAR) );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
} else {
|
||
lstrcpyW( *ppszOutValue, (LPCWSTR) propertyItem->lpDefault );
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if ( *ppszOutValue != NULL ) {
|
||
LocalFree( *ppszOutValue );
|
||
}
|
||
*ppszOutValue = pszInValue;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
ppbOutValue = (LPBYTE UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(LPBYTE*)];
|
||
// If OpenKey has succeeded.
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = ClRtlGetBinaryValue( key,
|
||
rvn.PszName(),
|
||
&pbInValue,
|
||
&dwInValue,
|
||
pClusterRegApis );
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( *ppbOutValue != NULL ) {
|
||
LocalFree( *ppbOutValue );
|
||
}
|
||
*ppbOutValue = pbInValue;
|
||
*pdwOutValue = dwInValue;
|
||
} else if ( (status == ERROR_FILE_NOT_FOUND) &&
|
||
(!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
|
||
! bCheckForRequiredProperties) ) {
|
||
|
||
status = ERROR_SUCCESS;
|
||
|
||
// Deallocate old value.
|
||
if ( *ppbOutValue != NULL ) {
|
||
LocalFree( *ppbOutValue );
|
||
*ppbOutValue = NULL;
|
||
}
|
||
|
||
*pdwOutValue = 0;
|
||
|
||
// If a default is specified, copy it.
|
||
if ( propertyItem->lpDefault != NULL ) {
|
||
*ppbOutValue = (LPBYTE) LocalAlloc( LMEM_FIXED, propertyItem->Minimum );
|
||
if ( *ppbOutValue == NULL ) {
|
||
status = GetLastError();
|
||
} else {
|
||
CopyMemory( *ppbOutValue, (const PVOID) propertyItem->lpDefault, propertyItem->Minimum );
|
||
*pdwOutValue = propertyItem->Minimum;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
//
|
||
// Handle any errors that occurred.
|
||
//
|
||
if ( status != ERROR_SUCCESS ) {
|
||
if ( pszNameOfPropInError != NULL ) {
|
||
*pszNameOfPropInError = propertyItem->Name;
|
||
}
|
||
if ( propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED ) {
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_INVALID_DATA;
|
||
}
|
||
break;
|
||
} else {
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Advance to the next property.
|
||
//
|
||
propertyItem++;
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetPropertiesToParameterBlock
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlPropertyListFromParameterBlock(
|
||
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.
|
||
|
||
ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD bytesReturned;
|
||
DWORD required;
|
||
DWORD nameSize;
|
||
DWORD dataSize;
|
||
DWORD bufferIncrement;
|
||
DWORD totalBufferSize = 0;
|
||
LPDWORD ptrItemCount;
|
||
WORD propertyFormat;
|
||
BOOL copying = TRUE;
|
||
PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR UNALIGNED * ppszValue;
|
||
PBYTE UNALIGNED * ppbValue;
|
||
DWORD * pdwValue;
|
||
ULARGE_INTEGER * pullValue;
|
||
LPWSTR pszUnexpanded;
|
||
LPWSTR pszExpanded = NULL;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
if ( (pPropertyTable == NULL) ||
|
||
(pInParams == NULL) ||
|
||
(pcbOutPropertyListSize == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlPropertyListFromParameterBlock: pPropertyTable, pInParams, or pcbOutPropertyListSize == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer.
|
||
//
|
||
if ( pOutPropertyList != NULL ) {
|
||
ZeroMemory( pOutPropertyList, *pcbOutPropertyListSize );
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Need a DWORD of item count.
|
||
//
|
||
props.pb = (LPBYTE) pOutPropertyList;
|
||
ptrItemCount = props.pdw++;
|
||
|
||
totalBufferSize += sizeof(DWORD);
|
||
if ( totalBufferSize > *pcbOutPropertyListSize ) {
|
||
copying = FALSE;
|
||
}
|
||
|
||
while ( propertyItem->Name != NULL ) {
|
||
//
|
||
// Copy the property name.
|
||
//
|
||
nameSize = (lstrlenW( propertyItem->Name ) + 1) * sizeof(WCHAR);
|
||
bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME) + ALIGN_CLUSPROP( nameSize );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
|
||
props.pName->cbLength = nameSize;
|
||
lstrcpyW( props.pName->sz, propertyItem->Name );
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Copy the property value.
|
||
//
|
||
propertyFormat = (WORD) propertyItem->Format;
|
||
switch ( propertyItem->Format ) {
|
||
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
pdwValue = (DWORD *) &pInParams[propertyItem->Offset];
|
||
bufferIncrement = sizeof(CLUSPROP_DWORD);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = propertyFormat;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pDwordValue->cbLength = sizeof(DWORD);
|
||
props.pDwordValue->dw = *pdwValue;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
pullValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
|
||
bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = propertyFormat;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
|
||
props.pULargeIntegerValue->li.u = pullValue->u;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
ppszValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pszUnexpanded = *ppszValue;
|
||
if ( *ppszValue != NULL ) {
|
||
dataSize = (lstrlenW( *ppszValue ) + 1) * sizeof(WCHAR);
|
||
} else {
|
||
dataSize = sizeof(WCHAR);
|
||
}
|
||
bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( dataSize );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = propertyFormat;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pStringValue->cbLength = dataSize;
|
||
if ( *ppszValue != NULL ) {
|
||
lstrcpyW( props.pStringValue->sz, *ppszValue );
|
||
} else {
|
||
props.pStringValue->sz[0] = L'\0';
|
||
}
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// See if there is a different expanded string and, if so,
|
||
// return it as an additional value in the value list.
|
||
//
|
||
if ( pszUnexpanded != NULL ) {
|
||
pszExpanded = ClRtlExpandEnvironmentStrings( pszUnexpanded );
|
||
if ( pszExpanded == NULL ) {
|
||
status = GetLastError();
|
||
break;
|
||
}
|
||
if ( lstrcmpW( pszExpanded, pszUnexpanded ) != 0 ) {
|
||
dataSize = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
|
||
bufferIncrement = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataSize );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( totalBufferSize <= *pcbOutPropertyListSize ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
|
||
props.pStringValue->cbLength = dataSize;
|
||
lstrcpyW( props.pStringValue->sz, pszExpanded );
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
}
|
||
LocalFree( pszExpanded );
|
||
pszExpanded = NULL;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
ppszValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pdwValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
|
||
if ( *ppszValue != NULL ) {
|
||
bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( *pdwValue );
|
||
} else {
|
||
bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( sizeof(WCHAR) );
|
||
}
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = propertyFormat;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
if ( *ppszValue != NULL ) {
|
||
props.pStringValue->cbLength = *pdwValue;
|
||
CopyMemory( props.pStringValue->sz, *ppszValue, *pdwValue );
|
||
} else {
|
||
props.pStringValue->cbLength = sizeof(WCHAR);
|
||
props.pStringValue->sz[0] = L'\0';
|
||
}
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
ppbValue = (PBYTE UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pdwValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(PBYTE*)];
|
||
if ( *ppbValue != NULL ) {
|
||
bufferIncrement = sizeof(CLUSPROP_BINARY) + ALIGN_CLUSPROP( *pdwValue );
|
||
} else {
|
||
bufferIncrement = sizeof(CLUSPROP_BINARY);
|
||
}
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = propertyFormat;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
if ( *ppbValue != NULL ) {
|
||
props.pBinaryValue->cbLength = *pdwValue;
|
||
CopyMemory( props.pBinaryValue->rgb, *ppbValue, *pdwValue );
|
||
} else {
|
||
props.pBinaryValue->cbLength = 0;
|
||
}
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Add the value-closing endmark.
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_SYNTAX);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += bufferIncrement;
|
||
(*ptrItemCount)++;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Advance to the next property.
|
||
//
|
||
propertyItem++;
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
// Don't forget the ENDMARK.
|
||
totalBufferSize += sizeof(CLUSPROP_SYNTAX);
|
||
if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Return size of data.
|
||
//
|
||
if ( copying == FALSE ) {
|
||
*pcbRequired = totalBufferSize;
|
||
*pcbBytesReturned = 0;
|
||
status = ERROR_MORE_DATA;
|
||
} else {
|
||
*pcbRequired = 0;
|
||
*pcbBytesReturned = totalBufferSize;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlPropertyListFromParameterBlock
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPrivateProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
OUT PVOID pOutPropertyList,
|
||
IN DWORD cbOutPropertyListSize,
|
||
OUT LPDWORD pcbBytesReturned,
|
||
OUT LPDWORD pcbRequired
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the private properties for a given object.
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
||
to read from.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
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_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
||
|
||
ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD ival;
|
||
DWORD currentNameLength = 80;
|
||
DWORD currentDataLength = 80;
|
||
DWORD nameLength;
|
||
DWORD dataLength;
|
||
DWORD dataLengthExpanded;
|
||
DWORD type;
|
||
LPWSTR name;
|
||
PUCHAR data;
|
||
LPDWORD ptrItemCount;
|
||
DWORD itemCount = 0;
|
||
BOOL copying = TRUE;
|
||
DWORD totalBufferSize = 0;
|
||
DWORD bufferIncrement;
|
||
DWORD bufferIncrementExpanded;
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR pszExpanded = NULL;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis->pfnEnumValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPrivateProperties: hkeyClusterKey or pClusterRegApis->pfnEnumValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pOutPropertyList != NULL ) {
|
||
ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Need a DWORD of item count.
|
||
//
|
||
props.pb = (LPBYTE) pOutPropertyList;
|
||
ptrItemCount = props.pdw++;
|
||
|
||
totalBufferSize += sizeof(DWORD);
|
||
if ( totalBufferSize > cbOutPropertyListSize ) {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Allocate a property name buffer.
|
||
//
|
||
name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
|
||
if ( name == NULL ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
//
|
||
// Allocate a property value data buffer.
|
||
//
|
||
data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
|
||
if ( data == NULL ) {
|
||
LocalFree( name );
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
//
|
||
// Enumerate all properties and return them!
|
||
//
|
||
for ( ival = 0; ; ival++ ) {
|
||
retry:
|
||
//
|
||
// Read the next property.
|
||
//
|
||
nameLength = currentNameLength;
|
||
dataLength = currentDataLength;
|
||
status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
|
||
ival,
|
||
name,
|
||
&nameLength,
|
||
&type,
|
||
data,
|
||
&dataLength );
|
||
|
||
if ( status == ERROR_MORE_DATA ) {
|
||
if ( (nameLength+1) > currentNameLength ) {
|
||
currentNameLength = nameLength+1;
|
||
LocalFree( name );
|
||
name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
|
||
if ( name == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
}
|
||
if ( dataLength > currentDataLength ) {
|
||
currentDataLength = dataLength;
|
||
LocalFree( data );
|
||
data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
|
||
if ( data == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
}
|
||
goto retry;
|
||
} else if ( status == ERROR_NO_MORE_ITEMS ) {
|
||
status = ERROR_SUCCESS;
|
||
break;
|
||
} else if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Skip this property if it isn't of a known type.
|
||
//
|
||
if ( (type != REG_SZ) &&
|
||
(type != REG_EXPAND_SZ) &&
|
||
(type != REG_MULTI_SZ) &&
|
||
(type != REG_BINARY) &&
|
||
(type != REG_DWORD) &&
|
||
(type != REG_QWORD) ) {
|
||
continue;
|
||
}
|
||
|
||
itemCount++;
|
||
|
||
//
|
||
// Copy the property name.
|
||
// Need a DWORD for the next name Syntax + DWORD for name byte count +
|
||
// the namelength (in bytes? + NULL?)... must be rounded!
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ALIGN_CLUSPROP( (nameLength + 1) * sizeof(WCHAR) );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
|
||
props.pName->cbLength = (nameLength + 1) * sizeof(WCHAR);
|
||
lstrcpyW( props.pName->sz, name);
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
switch ( type ) {
|
||
|
||
case REG_SZ:
|
||
case REG_EXPAND_SZ:
|
||
case REG_MULTI_SZ:
|
||
case REG_BINARY:
|
||
bufferIncrement = sizeof(CLUSPROP_BINARY)
|
||
+ ALIGN_CLUSPROP( dataLength );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( ( type == REG_SZ )
|
||
|| ( type == REG_EXPAND_SZ ) ) {
|
||
pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) data );
|
||
if ( pszExpanded == NULL ) {
|
||
status = GetLastError();
|
||
break;
|
||
}
|
||
if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
|
||
dataLengthExpanded = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
|
||
bufferIncrementExpanded = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataLengthExpanded );
|
||
totalBufferSize += bufferIncrementExpanded;
|
||
}
|
||
}
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
if ( type == REG_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_SZ;
|
||
} else if ( type == REG_EXPAND_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_EXPAND_SZ;
|
||
} else if ( type == REG_MULTI_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_MULTI_SZ;
|
||
} else {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_BINARY;
|
||
}
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pBinaryValue->cbLength = dataLength;
|
||
CopyMemory( props.pBinaryValue->rgb, data, dataLength );
|
||
props.pb += bufferIncrement;
|
||
|
||
//
|
||
// For SZ or EXPAND_SZ, see if there is a different
|
||
// expanded string and, if so, return it as an additional
|
||
// value in the value list.
|
||
//
|
||
if ( ( type == REG_SZ )
|
||
|| ( type == REG_EXPAND_SZ ) ) {
|
||
if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
|
||
props.pStringValue->cbLength = dataLengthExpanded;
|
||
lstrcpyW( props.pStringValue->sz, pszExpanded );
|
||
props.pb += bufferIncrementExpanded;
|
||
}
|
||
}
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
if ( ( ( type == REG_SZ ) || ( type == REG_EXPAND_SZ ) )
|
||
&& ( pszExpanded != NULL ) )
|
||
{
|
||
LocalFree( pszExpanded );
|
||
pszExpanded = NULL;
|
||
}
|
||
break;
|
||
|
||
case REG_DWORD:
|
||
bufferIncrement = sizeof(CLUSPROP_DWORD);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_DWORD;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pDwordValue->cbLength = sizeof(DWORD);
|
||
props.pDwordValue->dw = *(LPDWORD)data;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
case REG_QWORD:
|
||
bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
|
||
props.pULargeIntegerValue->li.u = ((ULARGE_INTEGER *)data)->u;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Add the closing endmark.
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_SYNTAX);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
//
|
||
// Add the closing endmark.
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_SYNTAX);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
}
|
||
|
||
LocalFree( name );
|
||
LocalFree( data );
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
if ( !copying ) {
|
||
*pcbRequired = totalBufferSize;
|
||
status = ERROR_MORE_DATA;
|
||
} else {
|
||
*ptrItemCount = itemCount;
|
||
*pcbBytesReturned = totalBufferSize;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetPrivateProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetUnknownProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
OUT PVOID pOutPropertyList,
|
||
IN DWORD cbOutPropertyListSize,
|
||
OUT LPDWORD pcbBytesReturned,
|
||
OUT LPDWORD pcbRequired
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the unknown properties for a given object.
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - Supplies the handle to the key in the cluster database
|
||
to read from.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
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_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
|
||
|
||
ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD ival;
|
||
DWORD currentNameLength = 80;
|
||
DWORD currentDataLength = 80;
|
||
DWORD nameLength;
|
||
DWORD dataLength;
|
||
DWORD dataLengthExpanded;
|
||
DWORD type;
|
||
LPWSTR name;
|
||
PUCHAR data;
|
||
LPDWORD ptrItemCount;
|
||
DWORD itemCount = 0;
|
||
BOOL copying = TRUE;
|
||
DWORD totalBufferSize = 0;
|
||
DWORD bufferIncrement;
|
||
DWORD bufferIncrementExpanded;
|
||
BOOL found;
|
||
LPWSTR pszExpanded = NULL;
|
||
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
PRESUTIL_PROPERTY_ITEM property;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis->pfnEnumValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPrivateProperties: hkeyClusterKey or pClusterRegApis->pfnEnumValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pOutPropertyList != NULL ) {
|
||
ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Need a DWORD of item count.
|
||
//
|
||
props.pb = (LPBYTE) pOutPropertyList;
|
||
ptrItemCount = props.pdw++;
|
||
|
||
totalBufferSize += sizeof(DWORD);
|
||
if ( totalBufferSize > cbOutPropertyListSize ) {
|
||
copying = FALSE;
|
||
}
|
||
|
||
//
|
||
// Allocate a property name buffer.
|
||
//
|
||
name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
|
||
if ( name == NULL ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
//
|
||
// Allocate a property value data buffer.
|
||
//
|
||
data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
|
||
if ( data == NULL ) {
|
||
LocalFree( name );
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
|
||
//
|
||
// Enumerate all properties and return them!
|
||
//
|
||
for ( ival = 0; ; ival++ ) {
|
||
retry:
|
||
//
|
||
// Read the next property.
|
||
//
|
||
nameLength = currentNameLength;
|
||
dataLength = currentDataLength;
|
||
status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
|
||
ival,
|
||
name,
|
||
&nameLength,
|
||
&type,
|
||
data,
|
||
&dataLength );
|
||
|
||
if ( status == ERROR_MORE_DATA ) {
|
||
if ( (nameLength+1) > currentNameLength ) {
|
||
currentNameLength = nameLength+1;
|
||
LocalFree( name );
|
||
name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
|
||
if ( name == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
}
|
||
if ( dataLength > currentDataLength ) {
|
||
currentDataLength = dataLength;
|
||
LocalFree( data );
|
||
data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
|
||
if ( data == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
}
|
||
goto retry;
|
||
} else if ( status == ERROR_NO_MORE_ITEMS ) {
|
||
status = ERROR_SUCCESS;
|
||
break;
|
||
} else if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Skip this property if it isn't of a known type.
|
||
//
|
||
if ( (type != REG_SZ) &&
|
||
(type != REG_EXPAND_SZ) &&
|
||
(type != REG_MULTI_SZ) &&
|
||
(type != REG_BINARY) &&
|
||
(type != REG_DWORD) &&
|
||
(type != REG_QWORD) ) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Check if this property item is 'known'. If so, continue.
|
||
//
|
||
found = FALSE;
|
||
property = pPropertyTable;
|
||
while ( property->Name != NULL ) {
|
||
if ( lstrcmpiW( property->Name, name ) == 0 ) {
|
||
found = TRUE;
|
||
break;
|
||
}
|
||
property++;
|
||
}
|
||
if ( found ) {
|
||
continue;
|
||
}
|
||
|
||
itemCount++;
|
||
|
||
//
|
||
// Copy the property name.
|
||
// Need a DWORD for the next name Syntax + DWORD for name byte count +
|
||
// the namelength (in bytes? + NULL?)... must be rounded!
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ALIGN_CLUSPROP( (nameLength + 1) * sizeof(WCHAR) );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
|
||
props.pName->cbLength = (nameLength + 1) * sizeof(WCHAR);
|
||
lstrcpyW( props.pName->sz, name);
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
switch ( type ) {
|
||
|
||
case REG_SZ:
|
||
case REG_EXPAND_SZ:
|
||
case REG_MULTI_SZ:
|
||
case REG_BINARY:
|
||
bufferIncrement = sizeof(CLUSPROP_BINARY)
|
||
+ ALIGN_CLUSPROP( dataLength );
|
||
totalBufferSize += bufferIncrement;
|
||
if ( type == REG_EXPAND_SZ ) {
|
||
pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) data );
|
||
if ( pszExpanded == NULL ) {
|
||
status = GetLastError();
|
||
break;
|
||
}
|
||
if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
|
||
dataLengthExpanded = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
|
||
bufferIncrementExpanded = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataLengthExpanded );
|
||
totalBufferSize += bufferIncrementExpanded;
|
||
}
|
||
}
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
if ( type == REG_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_SZ;
|
||
} else if ( type == REG_EXPAND_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_EXPAND_SZ;
|
||
} else if ( type == REG_MULTI_SZ ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_MULTI_SZ;
|
||
} else {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_BINARY;
|
||
}
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pBinaryValue->cbLength = dataLength;
|
||
CopyMemory( props.pBinaryValue->rgb, data, dataLength );
|
||
props.pb += bufferIncrement;
|
||
|
||
//
|
||
// For SZ or EXPAND_SZ, see if there is a different
|
||
// expanded string and, if so, return it as an additional
|
||
// value in the value list.
|
||
//
|
||
if ( ( type == REG_SZ )
|
||
|| ( type == REG_EXPAND_SZ ) )
|
||
{
|
||
if ( pszExpanded != NULL ) {
|
||
if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
|
||
props.pStringValue->cbLength = dataLengthExpanded;
|
||
lstrcpyW( props.pStringValue->sz, pszExpanded );
|
||
props.pb += bufferIncrementExpanded;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
if ( type == REG_EXPAND_SZ ) {
|
||
LocalFree( pszExpanded );
|
||
pszExpanded = NULL;
|
||
}
|
||
break;
|
||
|
||
case REG_DWORD:
|
||
bufferIncrement = sizeof(CLUSPROP_DWORD);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_DWORD;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pDwordValue->cbLength = sizeof(DWORD);
|
||
props.pDwordValue->dw = *(LPDWORD)data;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
case REG_QWORD:
|
||
bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->wFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
|
||
props.pULargeIntegerValue->li.u = ((ULARGE_INTEGER *)data)->u;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Add the closing endmark.
|
||
//
|
||
bufferIncrement = sizeof(CLUSPROP_SYNTAX);
|
||
totalBufferSize += bufferIncrement;
|
||
if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += bufferIncrement;
|
||
} else {
|
||
copying = FALSE;
|
||
}
|
||
|
||
}
|
||
|
||
LocalFree( name );
|
||
LocalFree( data );
|
||
|
||
if ( !copying ) {
|
||
*pcbRequired = totalBufferSize;
|
||
status = ERROR_MORE_DATA;
|
||
} else {
|
||
*ptrItemCount = itemCount;
|
||
*pcbBytesReturned = totalBufferSize;
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetUnknownProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlAddUnknownProperties(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
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;
|
||
CLUSPROP_BUFFER_HELPER copyBuffer;
|
||
CLUSPROP_BUFFER_HELPER outBuffer;
|
||
DWORD bufferLength;
|
||
DWORD bytesReturned;
|
||
DWORD required;
|
||
|
||
//
|
||
// Allocate a buffer for getting 'unknown' properties.
|
||
//
|
||
if ( (cbOutPropertyListSize > *pcbBytesReturned) &&
|
||
(*pcbRequired == 0) )
|
||
{
|
||
bufferLength = cbOutPropertyListSize + (2 * sizeof(DWORD)) - *pcbBytesReturned;
|
||
outBuffer.pb = (LPBYTE) LocalAlloc( LMEM_FIXED, bufferLength );
|
||
if ( outBuffer.pb == NULL ) {
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
} else {
|
||
bufferLength = 0;
|
||
outBuffer.pb = NULL;
|
||
}
|
||
|
||
//
|
||
// Get the 'unknown' properties.
|
||
//
|
||
status = ClRtlGetUnknownProperties( hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
outBuffer.pb,
|
||
bufferLength,
|
||
&bytesReturned,
|
||
&required );
|
||
if ( status == ERROR_SUCCESS ) {
|
||
//
|
||
// Copy properties if any were found.
|
||
//
|
||
if ( bytesReturned > sizeof(DWORD) ) {
|
||
//
|
||
// Copy the unknown property data to the end of the property list.
|
||
//
|
||
CL_ASSERT( bytesReturned <= bufferLength );
|
||
copyBuffer.pb = (LPBYTE) pOutPropertyList;
|
||
copyBuffer.pList->nPropertyCount += outBuffer.pList->nPropertyCount;
|
||
copyBuffer.pb += *pcbBytesReturned - sizeof(CLUSPROP_SYNTAX);
|
||
CopyMemory( copyBuffer.pb, outBuffer.pb + sizeof(DWORD), bytesReturned - sizeof(DWORD) );
|
||
*pcbBytesReturned += bytesReturned - sizeof(DWORD) - sizeof(CLUSPROP_SYNTAX);
|
||
}
|
||
} else if ( ( status == ERROR_MORE_DATA )
|
||
&& ( required == sizeof(DWORD) ) ) {
|
||
required = 0;
|
||
status = ERROR_SUCCESS;
|
||
} else {
|
||
if ( *pcbRequired == 0 ) {
|
||
*pcbRequired = *pcbBytesReturned;
|
||
}
|
||
*pcbBytesReturned = 0;
|
||
}
|
||
|
||
//
|
||
// If there are any properties, the number of bytes required will include
|
||
// both a property count (DWORD) and an endmark (CLUSPROP_SYNTAX).
|
||
// Subtract these off because these appear in both lists.
|
||
//
|
||
if ( required > sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX) ) {
|
||
required -= sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
|
||
}
|
||
|
||
//
|
||
// Free the out buffer (which may be NULL)
|
||
//
|
||
LocalFree( outBuffer.pb );
|
||
|
||
//
|
||
// Adjust lengths
|
||
//
|
||
*pcbRequired += required;
|
||
|
||
return(status);
|
||
|
||
} // ClRtlAddUnknownProperties
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPropertySize(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
|
||
pPropertyTableItem - Supplies the property table item for the property
|
||
whose size is to be returned.
|
||
|
||
pcbOutPropertyListSize - Supplies the size of the output buffer
|
||
required to add this property to a property list.
|
||
|
||
pnPropertyCount - The count of properties is incremented.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS - Operation was successful.
|
||
|
||
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_INVALID_PARAMETER -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD valueType;
|
||
DWORD bytesReturned;
|
||
DWORD headerLength;
|
||
PVOID key;
|
||
LPWSTR pszValue = NULL;
|
||
LPWSTR pszExpanded = NULL;
|
||
CRegistryValueName rvn;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis->pfnQueryValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: hkeyClusterKey or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pPropertyTableItem->Name, pPropertyTableItem->KeyName );
|
||
if ( status != ERROR_SUCCESS )
|
||
{
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
if ( (pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: pClusterRegApis->pfnOpenValue or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_READ,
|
||
&key);
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
//
|
||
// Read the value size.
|
||
//
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
NULL,
|
||
&bytesReturned );
|
||
}
|
||
|
||
//
|
||
// If the value is not present, return the default value.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
|
||
switch ( pPropertyTableItem->Format ) {
|
||
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(DWORD);
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(ULARGE_INTEGER);
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
} else {
|
||
bytesReturned = sizeof(WCHAR);
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
|
||
} else {
|
||
bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
} else {
|
||
bytesReturned = 0;
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
default:
|
||
valueType = CLUSPROP_FORMAT_UNKNOWN;
|
||
break;
|
||
}
|
||
} else if ( status == ERROR_SUCCESS ) {
|
||
switch ( valueType ) {
|
||
case REG_DWORD:
|
||
if ((pPropertyTableItem->Format == CLUSPROP_FORMAT_DWORD) ||
|
||
(pPropertyTableItem->Format == CLUSPROP_FORMAT_LONG))
|
||
{
|
||
valueType = pPropertyTableItem->Format;
|
||
} else {
|
||
valueType = CLUSPROP_FORMAT_UNKNOWN;
|
||
}
|
||
break;
|
||
|
||
case REG_QWORD:
|
||
if ((pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER) ||
|
||
(pPropertyTableItem->Format == CLUSPROP_FORMAT_LARGE_INTEGER))
|
||
{
|
||
valueType = pPropertyTableItem->Format;
|
||
} else {
|
||
valueType = CLUSPROP_FORMAT_UNKNOWN;
|
||
}
|
||
break;
|
||
|
||
case REG_MULTI_SZ:
|
||
valueType = CLUSPROP_FORMAT_MULTI_SZ;
|
||
break;
|
||
|
||
case REG_SZ:
|
||
case REG_EXPAND_SZ:
|
||
//
|
||
// Include the size of the expanded string in both REG_SZ and REG_EXPAND_SZ
|
||
//
|
||
pszValue = ClRtlGetSzValue( (HKEY) key,
|
||
rvn.PszName(),
|
||
pClusterRegApis );
|
||
if ( pszValue != NULL ) {
|
||
pszExpanded = ClRtlExpandEnvironmentStrings( pszValue );
|
||
if ( pszExpanded == NULL ) {
|
||
status = GetLastError();
|
||
} else if ( lstrcmpW( pszValue, pszExpanded ) != 0 ) {
|
||
bytesReturned += ALIGN_CLUSPROP( (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR ) );
|
||
bytesReturned += sizeof(CLUSPROP_SZ);
|
||
}
|
||
LocalFree( pszValue );
|
||
LocalFree( pszExpanded );
|
||
}
|
||
|
||
if ( valueType == REG_SZ ) {
|
||
valueType = CLUSPROP_FORMAT_SZ;
|
||
}
|
||
else {
|
||
valueType = CLUSPROP_FORMAT_EXPAND_SZ;
|
||
}
|
||
break;
|
||
|
||
case REG_BINARY:
|
||
valueType = CLUSPROP_FORMAT_BINARY;
|
||
break;
|
||
|
||
default:
|
||
valueType = CLUSPROP_FORMAT_UNKNOWN;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} else if ( status == ERROR_SUCCESS ) {
|
||
if ( pPropertyTableItem->Format != valueType ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: Property '%1!ls!' format %2!d! expected, was %3!d!.\n", rvn.PszKeyName(), pPropertyTableItem->Format, valueType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
} else {
|
||
//assume that the size of dword and long
|
||
//is fixed to 32 bits
|
||
if (( valueType == CLUSPROP_FORMAT_DWORD ) ||
|
||
( valueType == CLUSPROP_FORMAT_LONG ))
|
||
{
|
||
headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
|
||
+ sizeof(CLUSPROP_DWORD)
|
||
- 4 // CLUSPROP_DWORD.dw (specified by bytesReturned)
|
||
+ sizeof(CLUSPROP_SYNTAX); // for endmark
|
||
} else
|
||
if (( valueType == CLUSPROP_FORMAT_ULARGE_INTEGER ) ||
|
||
( valueType == CLUSPROP_FORMAT_LARGE_INTEGER ))
|
||
{
|
||
headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
|
||
+ sizeof(CLUSPROP_ULARGE_INTEGER)
|
||
- 8 // CLUSPROP_ULARGE_INTEGER.li (specified by bytesReturned)
|
||
+ sizeof(CLUSPROP_SYNTAX); // for endmark
|
||
} else {
|
||
// NOTE: This assumes SZ, EXPAND_SZ, MULTI_SZ, and BINARY are the same size
|
||
headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
|
||
+ sizeof(CLUSPROP_BINARY)
|
||
+ sizeof(CLUSPROP_SYNTAX); // for endmark
|
||
}
|
||
|
||
headerLength = ALIGN_CLUSPROP( headerLength );
|
||
bytesReturned = ALIGN_CLUSPROP( bytesReturned );
|
||
*pcbOutPropertyListSize += (bytesReturned + headerLength);
|
||
*pnPropertyCount += 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( ( rvn.PszKeyName() != NULL ) &&
|
||
( key != NULL ) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetPropertySize
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetProperty(
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
|
||
OUT PVOID * pOutPropertyItem,
|
||
IN OUT LPDWORD pcbOutPropertyItemSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS -
|
||
|
||
ERROR_BAD_ARGUMENTS -
|
||
|
||
ERROR_MORE_DATA -
|
||
|
||
Notes:
|
||
|
||
The buffer size has already been determined to be large enough to hold
|
||
the return data.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD valueType;
|
||
DWORD bytesReturned;
|
||
DWORD bufferSize;
|
||
PVOID dataBuffer;
|
||
DWORD nameLength;
|
||
PVOID key = NULL;
|
||
CLUSTER_PROPERTY_FORMAT format;
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR pszExpanded = NULL;
|
||
CRegistryValueName rvn;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis->pfnQueryValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetProperty: hkeyClusterKey or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pPropertyTableItem->Name, pPropertyTableItem->KeyName );
|
||
if ( status != ERROR_SUCCESS )
|
||
{
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
if ( (pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetProperty: pClusterRegApis->pfnOpenValue or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_READ,
|
||
&key);
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
//
|
||
// Find out if this property is available
|
||
//
|
||
if ( status == ERROR_SUCCESS ) {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
NULL,
|
||
&bytesReturned );
|
||
}
|
||
|
||
//
|
||
// If the value is not present, return the default value.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
switch ( pPropertyTableItem->Format ) {
|
||
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(DWORD);
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(ULARGE_INTEGER);
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
} else {
|
||
bytesReturned = sizeof(WCHAR);
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
|
||
} else {
|
||
bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
} else {
|
||
bytesReturned = 0;
|
||
}
|
||
valueType = pPropertyTableItem->Format;
|
||
break;
|
||
|
||
default:
|
||
valueType = CLUSPROP_FORMAT_UNKNOWN;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
//
|
||
// Get the property format
|
||
//
|
||
switch ( pPropertyTableItem->Format ) {
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
format = (enum CLUSTER_PROPERTY_FORMAT) pPropertyTableItem->Format;
|
||
break;
|
||
|
||
default:
|
||
format = CLUSPROP_FORMAT_UNKNOWN;
|
||
break;
|
||
|
||
}
|
||
|
||
props.pb = (LPBYTE) *pOutPropertyItem;
|
||
|
||
//
|
||
// Copy the property name, which includes its syntax and length.
|
||
//
|
||
nameLength = (lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR);
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_NAME;
|
||
props.pName->cbLength = nameLength;
|
||
lstrcpyW( props.pName->sz, pPropertyTableItem->Name );
|
||
bytesReturned = sizeof(*props.pName) + ALIGN_CLUSPROP( nameLength );
|
||
*pcbOutPropertyItemSize -= bytesReturned;
|
||
props.pb += bytesReturned;
|
||
|
||
//
|
||
// Copy the property value header.
|
||
//
|
||
props.pSyntax->wFormat = (USHORT)format;
|
||
props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
|
||
//
|
||
// Read the property value.
|
||
//
|
||
if ( pPropertyTableItem->Format == CLUSPROP_FORMAT_DWORD ||
|
||
pPropertyTableItem->Format == CLUSPROP_FORMAT_LONG )
|
||
{
|
||
bufferSize = *pcbOutPropertyItemSize
|
||
- (sizeof(*props.pDwordValue) - sizeof(props.pDwordValue->dw));
|
||
dataBuffer = &props.pDwordValue->dw;
|
||
} else
|
||
if ( pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER ||
|
||
pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER )
|
||
{
|
||
bufferSize = *pcbOutPropertyItemSize
|
||
- (sizeof(*props.pULargeIntegerValue) - sizeof(props.pULargeIntegerValue->li));
|
||
dataBuffer = &props.pULargeIntegerValue->li;
|
||
} else {
|
||
// NOTE: This assumes SZ, MULTI_SZ, and BINARY are the same size
|
||
bufferSize = *pcbOutPropertyItemSize - sizeof(*props.pBinaryValue);
|
||
dataBuffer = props.pBinaryValue->rgb;
|
||
}
|
||
bytesReturned = bufferSize;
|
||
if ( key == NULL ) {
|
||
status = ERROR_FILE_NOT_FOUND;
|
||
} else {
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE) dataBuffer,
|
||
&bytesReturned );
|
||
}
|
||
|
||
//
|
||
// If the value is not present, return the default value.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
switch ( pPropertyTableItem->Format ) {
|
||
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
//assume size of dword and long is the same
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(DWORD);
|
||
props.pDwordValue->dw = pPropertyTableItem->Default;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
status = ERROR_SUCCESS;
|
||
bytesReturned = sizeof(ULARGE_INTEGER);
|
||
props.pULargeIntegerValue->li.u = pPropertyTableItem->ULargeIntData->Default.u;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
if ( bufferSize < bytesReturned ) {
|
||
CopyMemory( dataBuffer, (LPCWSTR)pPropertyTableItem->lpDefault, bytesReturned );
|
||
}
|
||
} else {
|
||
bytesReturned = sizeof(WCHAR);
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
|
||
if ( bufferSize < bytesReturned ) {
|
||
lstrcpyW( (LPWSTR) dataBuffer, (LPCWSTR)pPropertyTableItem->lpDefault );
|
||
}
|
||
} else {
|
||
bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
status = ERROR_SUCCESS;
|
||
if ( pPropertyTableItem->Default != 0 ) {
|
||
bytesReturned = pPropertyTableItem->Minimum;
|
||
if ( bufferSize < bytesReturned ) {
|
||
CopyMemory( dataBuffer, (LPBYTE)pPropertyTableItem->lpDefault, bytesReturned );
|
||
}
|
||
} else {
|
||
bytesReturned = 0;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( bufferSize < bytesReturned ) {
|
||
status = ERROR_MORE_DATA;
|
||
} else if ( status == ERROR_SUCCESS ) {
|
||
props.pValue->cbLength = bytesReturned;
|
||
|
||
// Round the bytes used up to the next DWORD boundary.
|
||
bytesReturned = ALIGN_CLUSPROP( bytesReturned );
|
||
|
||
bytesReturned += sizeof(*props.pValue);
|
||
props.pb += bytesReturned;
|
||
|
||
//
|
||
// If this is an SZ or EXPAND_SZ, see if the expanded value should
|
||
// be added to the value list.
|
||
//
|
||
if ( ( pPropertyTableItem->Format == CLUSPROP_FORMAT_SZ )
|
||
|| ( pPropertyTableItem->Format == CLUSPROP_FORMAT_EXPAND_SZ ) ) {
|
||
pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) dataBuffer );
|
||
if ( pszExpanded == NULL ) {
|
||
status = GetLastError();
|
||
} else {
|
||
if ( lstrcmpiW( pszExpanded, (LPCWSTR) dataBuffer ) != 0 ) {
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
|
||
bufferSize = ALIGN_CLUSPROP( (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR ) );
|
||
props.pStringValue->cbLength = bufferSize;
|
||
lstrcpyW( props.pStringValue->sz, pszExpanded );
|
||
bytesReturned += sizeof( *props.pStringValue ) + bufferSize;
|
||
props.pb += sizeof( *props.pStringValue ) + bufferSize;
|
||
}
|
||
LocalFree( pszExpanded );
|
||
}
|
||
}
|
||
|
||
if ( status == ERROR_SUCCESS ) {
|
||
// Add the value list endmark.
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += sizeof(*props.pSyntax);
|
||
bytesReturned += sizeof(*props.pSyntax);
|
||
|
||
*pcbOutPropertyItemSize -= bytesReturned;
|
||
*pOutPropertyItem = (PVOID)props.pb;
|
||
} // if: ERROR_SUCCESS
|
||
} // else if: ERROR_SUCCESS
|
||
} // if: ERROR_SUCCESS
|
||
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetProperty
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetPropertyTable(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
IN PVOID Reserved,
|
||
IN BOOL bAllowUnknownProperties,
|
||
IN const PVOID pInPropertyList,
|
||
IN DWORD cbInPropertyListSize,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - The opened cluster database key where properties are to
|
||
be written. If not specified, the property list will only be
|
||
validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
Reserved - Reserved for future use.
|
||
|
||
bAllowUnknownProperties - Don't fail if unknown properties are found.
|
||
|
||
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 - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input buffer and the parameter block.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_BAD_ARGUMENTS - hkeyClusterKey is specified but proper cluster
|
||
registry APIs are not specified, or no property table is specified.
|
||
|
||
ERROR_INVALID_DATA - No property list is specified or the format of the
|
||
property list is invalid.
|
||
|
||
ERROR_INSUFFICIENT_BUFFER - The property list buffer isn't large enough to
|
||
contain all the data it indicates it should contain.
|
||
|
||
ERROR_INVALID_PARAMETER - The property list isn't formatted properly.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
PRESUTIL_PROPERTY_ITEM propertyItem;
|
||
DWORD inBufferSize;
|
||
DWORD itemCount;
|
||
DWORD dataSize;
|
||
PVOID key;
|
||
CLUSPROP_BUFFER_HELPER buf;
|
||
PCLUSPROP_PROPERTY_NAME pName;
|
||
CRegistryValueName rvn;
|
||
|
||
if ( ( (hkeyClusterKey != NULL) &&
|
||
(pClusterRegApis->pfnSetValue == NULL) ) ||
|
||
( pPropertyTable == NULL ) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: hkeyClusterKey or pClusterRegApis->pfnSetValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
if ( pInPropertyList == NULL ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
buf.pb = (LPBYTE) pInPropertyList;
|
||
inBufferSize = cbInPropertyListSize;
|
||
|
||
//
|
||
// Get the number of items in this list
|
||
//
|
||
if ( inBufferSize < sizeof(DWORD) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
itemCount = buf.pList->nPropertyCount;
|
||
buf.pdw++;
|
||
inBufferSize -= sizeof(*buf.pdw);
|
||
|
||
//
|
||
// Parse the rest of the items in the buffer.
|
||
//
|
||
while ( itemCount-- ) {
|
||
//
|
||
// Verify that the buffer is big enough to contain the
|
||
// property name and a value.
|
||
//
|
||
pName = buf.pName;
|
||
if ( inBufferSize < sizeof(*pName) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
|
||
if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax of the property name is correct.
|
||
//
|
||
if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: not a name syntax.\n" );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Verify that the length is correct for the string.
|
||
//
|
||
if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: name is not a valid C string.\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// Move the buffer pointer to the property value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
//
|
||
// Find the property name in the list of known properties.
|
||
//
|
||
propertyItem = pPropertyTable;
|
||
while ( propertyItem->Name != NULL ) {
|
||
|
||
if ( lstrcmpiW( pName->sz, propertyItem->Name ) == 0 ) {
|
||
//
|
||
// Verify that the buffer is big enough to contain the value.
|
||
//
|
||
dataSize = sizeof(*buf.pValue)
|
||
+ ALIGN_CLUSPROP( buf.pValue->cbLength )
|
||
+ sizeof(CLUSPROP_SYNTAX); // endmark
|
||
if ( inBufferSize < dataSize ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax type is LIST_VALUE.
|
||
//
|
||
if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' type CLUSPROP_TYPE_LIST_VALUE (%2!d!) expected, was %3!d!.\n", pName->sz, CLUSPROP_TYPE_LIST_VALUE, buf.pSyntax->wType );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Verify that this property should be of this format.
|
||
//
|
||
if ( buf.pSyntax->wFormat != propertyItem->Format ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' format %2!d! expected, was %3!d!.\n", pName->sz, propertyItem->Format, buf.pSyntax->wType );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Make sure we are allowed to set this item.
|
||
//
|
||
if ( propertyItem->Flags & RESUTIL_PROPITEM_READ_ONLY ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' is non-writable.\n", pName->sz );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, create the key.
|
||
//
|
||
if ( (hkeyClusterKey != NULL) &&
|
||
(rvn.PszKeyName() != NULL) ) {
|
||
|
||
DWORD disposition;
|
||
|
||
if ( (pClusterRegApis->pfnCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pClusterRegApis->pfnCreateKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
if ( hXsaction != NULL ) {
|
||
if ( pClusterRegApis->pfnLocalCreateKey == NULL ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pClusterRegApis->pfnLocalCreateKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
status = (*pClusterRegApis->pfnLocalCreateKey)(hXsaction,
|
||
hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition );
|
||
}
|
||
|
||
else {
|
||
status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition );
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
return(status);
|
||
}
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
//
|
||
// Validate, write, and save the property data.
|
||
//
|
||
switch ( buf.pSyntax->wFormat ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
status = ClRtlpSetDwordProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pDwordValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_LONG:
|
||
status = ClRtlpSetLongProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pLongValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
status = ClRtlpSetULargeIntegerProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pULargeIntegerValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
status = ClRtlpSetLargeIntegerProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pLargeIntegerValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
status = ClRtlpSetStringProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pStringValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
status = ClRtlpSetMultiStringProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pStringValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
status = ClRtlpSetBinaryProperty(
|
||
hXsaction,
|
||
key,
|
||
pClusterRegApis,
|
||
propertyItem,
|
||
rvn,
|
||
buf.pBinaryValue,
|
||
bForceWrite,
|
||
pOutParams );
|
||
break;
|
||
|
||
default:
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", pName->sz, buf.pSyntax->wFormat );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
|
||
} // switch: value data format
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (hkeyClusterKey != NULL) &&
|
||
(rvn.PszKeyName() != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
//
|
||
// If an error occurred processing the property, cleanup and return.
|
||
//
|
||
if ( status != ERROR_SUCCESS ) {
|
||
return(status);
|
||
}
|
||
|
||
//
|
||
// Move the buffer past the value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
break;
|
||
|
||
} else {
|
||
propertyItem++;
|
||
//
|
||
// If we reached the end of the list, then return failure
|
||
// if we do not allow unknown properties.
|
||
//
|
||
if ( (propertyItem->Name == NULL) &&
|
||
! bAllowUnknownProperties ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' not found.\n", pName->sz );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// If no property name was found, this is an invalid parameter if
|
||
// we don't allow unknown properties. Otherwise advance past the
|
||
// property value.
|
||
//
|
||
if ( propertyItem->Name == NULL) {
|
||
if ( ! bAllowUnknownProperties ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' not found.\n", pName->sz );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Advance the buffer pointer past the value in the value list.
|
||
//
|
||
while ( (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(inBufferSize > 0) ) {
|
||
// ASSERT(inBufferSize > sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength));
|
||
buf.pb += sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength);
|
||
inBufferSize -= sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength);
|
||
} // while: more values in the list
|
||
|
||
//
|
||
// Advance the buffer pointer past the value list endmark.
|
||
//
|
||
// ASSERT(inBufferSize >= sizeof(*buf.pSyntax));
|
||
buf.pb += sizeof(*buf.pSyntax); // endmark
|
||
inBufferSize -= sizeof(*buf.pSyntax);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now find any parameters that are not represented in the property
|
||
// table. All of these extra properties will just be set without validation.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pInPropertyList != NULL) &&
|
||
bAllowUnknownProperties ) {
|
||
status = ClRtlpSetNonPropertyTable( hXsaction,
|
||
hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
NULL,
|
||
pInPropertyList,
|
||
cbInPropertyListSize );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlpSetPropertyTable
|
||
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetDwordProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_DWORD pInDwordValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a DWORD property, write it to the cluster database (or delete it
|
||
if it is zero length), and save it in the specified parameter block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInDwordValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
DWORD * pdwValue;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInDwordValue->cbLength == 0 );
|
||
|
||
//
|
||
// Validate the property data if not zero length.
|
||
//
|
||
if ( ! bZeroLengthData ) {
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( pInDwordValue->cbLength != sizeof(DWORD) ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' length %2!d! not DWORD length.\n", rrvnModifiedNames.PszName(), pInDwordValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: data in value not size of DWORD
|
||
|
||
//
|
||
// Verify that the value is within the valid range.
|
||
//
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONG) pInDwordValue->dw > (LONG) pPropertyItem->Maximum))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInDwordValue->dw > pPropertyItem->Maximum)) ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' value %2!u! too large.\n", rrvnModifiedNames.PszName(), pInDwordValue->dw );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value too high
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONG) pInDwordValue->dw < (LONG) pPropertyItem->Minimum))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInDwordValue->dw < pPropertyItem->Minimum)) ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' value %2!u! too small.\n", rrvnModifiedNames.PszName(), pInDwordValue->dw );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value to low
|
||
} // if: non-zero length data
|
||
|
||
pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE *) &pInDwordValue->dw,
|
||
sizeof(DWORD) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE *) &pInDwordValue->dw,
|
||
sizeof(DWORD) );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS)
|
||
&& (pOutParams != NULL) ) {
|
||
if ( bZeroLengthData ) {
|
||
*pdwValue = pPropertyItem->Default;
|
||
} else {
|
||
*pdwValue = pInDwordValue->dw;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetDwordProperty
|
||
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetLongProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_LONG pInLongValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a LONG property, write it to the cluster database (or delete it
|
||
if it is zero length), and save it in the specified parameter block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInLongValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
LONG * plValue;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInLongValue->cbLength == 0 );
|
||
|
||
//
|
||
// Validate the property data if not zero length.
|
||
//
|
||
if ( ! bZeroLengthData ) {
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( pInLongValue->cbLength != sizeof(LONG) ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' length %2!d! not LONG length.\n", rrvnModifiedNames.PszName(), pInLongValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: data in value not size of LONG
|
||
|
||
//
|
||
// Verify that the value is within the valid range.
|
||
//
|
||
if ( pInLongValue->l > (LONG) pPropertyItem->Maximum ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' value %2!d! too large.\n", rrvnModifiedNames.PszName(), pInLongValue->l );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value too high
|
||
if ( pInLongValue->l < (LONG) pPropertyItem->Minimum ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' value %2!d! too small.\n", rrvnModifiedNames.PszName(), pInLongValue->l );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value too small
|
||
} // if: non-zero length data
|
||
|
||
plValue = (LONG *) &pOutParams[pPropertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE *) &pInLongValue->l,
|
||
sizeof(LONG) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE *) &pInLongValue->l,
|
||
sizeof(LONG) );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS)
|
||
&& (pOutParams != NULL) ) {
|
||
if ( bZeroLengthData ) {
|
||
*plValue = (LONG) pPropertyItem->Default;
|
||
} else {
|
||
*plValue = pInLongValue->l;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetLongProperty
|
||
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetULargeIntegerProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_ULARGE_INTEGER pInULargeIntegerValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a ULARGE_INTEGER property, write it to the cluster database (or
|
||
delete it if it is zero length), and save it in the specified parameter
|
||
block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInULargeIntegerValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
ULARGE_INTEGER * pullValue;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInULargeIntegerValue->cbLength == 0 );
|
||
|
||
//
|
||
// Validate the property data if not zero length.
|
||
//
|
||
if ( ! bZeroLengthData ) {
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( pInULargeIntegerValue->cbLength != sizeof(ULARGE_INTEGER) ) {
|
||
ClRtlDbgPrint(LOG_UNUSUAL,
|
||
"ClRtlpSetULargeIntegerProperty: Property '%1!ls!' length %2!d! "
|
||
"not ULARGE_INTEGER length.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInULargeIntegerValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: data in value not size of DWORD
|
||
|
||
//
|
||
// Verify that the value is within the valid range.
|
||
//
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONGLONG)pInULargeIntegerValue->li.QuadPart > (LONGLONG)pPropertyItem->ULargeIntData->Maximum.QuadPart))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInULargeIntegerValue->li.QuadPart > pPropertyItem->ULargeIntData->Maximum.QuadPart)) )
|
||
{
|
||
ClRtlDbgPrint(
|
||
LOG_UNUSUAL,
|
||
"ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value %2!I64u! "
|
||
"too large.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInULargeIntegerValue->li.QuadPart );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value too high
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONGLONG)pInULargeIntegerValue->li.QuadPart < (LONGLONG)pPropertyItem->ULargeIntData->Minimum.QuadPart))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInULargeIntegerValue->li.QuadPart < pPropertyItem->ULargeIntData->Minimum.QuadPart)) )
|
||
{
|
||
ClRtlDbgPrint(LOG_UNUSUAL,
|
||
"ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value "
|
||
"%2!I64u! too small.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInULargeIntegerValue->li.QuadPart );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value to low
|
||
} // if: non-zero length data
|
||
|
||
pullValue = (ULARGE_INTEGER *) &pOutParams[pPropertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE *) &pInULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE *) &pInULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER) );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
|
||
if ( bZeroLengthData ) {
|
||
pullValue->u = pPropertyItem->ULargeIntData->Default.u;
|
||
} else {
|
||
pullValue->u = pInULargeIntegerValue->li.u;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetULargeIntegerProperty
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetLargeIntegerProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_LARGE_INTEGER pInLargeIntegerValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a LARGE_INTEGER property, write it to the cluster database (or
|
||
delete it if it is zero length), and save it in the specified parameter
|
||
block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInLargeIntegerValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
LARGE_INTEGER * pllValue;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInLargeIntegerValue->cbLength == 0 );
|
||
|
||
//
|
||
// Validate the property data if not zero length.
|
||
//
|
||
if ( ! bZeroLengthData ) {
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( pInLargeIntegerValue->cbLength != sizeof(LARGE_INTEGER) ) {
|
||
ClRtlDbgPrint(LOG_UNUSUAL,
|
||
"ClRtlpSetLargeIntegerProperty: Property '%1!ls!' length %2!d! "
|
||
"not LARGE_INTEGER length.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInLargeIntegerValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: data in value not size of DWORD
|
||
|
||
//
|
||
// Verify that the value is within the valid range.
|
||
//
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONGLONG)pInLargeIntegerValue->li.QuadPart > (LONGLONG)pPropertyItem->LargeIntData->Maximum.QuadPart))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInLargeIntegerValue->li.QuadPart > pPropertyItem->LargeIntData->Maximum.QuadPart)) )
|
||
{
|
||
ClRtlDbgPrint(LOG_UNUSUAL,
|
||
"ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value %2!I64d! "
|
||
"too large.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInLargeIntegerValue->li.QuadPart );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value too high
|
||
if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& ((LONGLONG)pInLargeIntegerValue->li.QuadPart < (LONGLONG)pPropertyItem->LargeIntData->Minimum.QuadPart))
|
||
|| ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
|
||
&& (pInLargeIntegerValue->li.QuadPart < pPropertyItem->LargeIntData->Minimum.QuadPart)) )
|
||
{
|
||
ClRtlDbgPrint(LOG_UNUSUAL,
|
||
"ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value "
|
||
"%2!I64d! too small.\n",
|
||
rrvnModifiedNames.PszName(),
|
||
pInLargeIntegerValue->li.QuadPart );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: value to low
|
||
} // if: non-zero length data
|
||
|
||
pllValue = (LARGE_INTEGER *) &pOutParams[pPropertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE *) &pInLargeIntegerValue->li.QuadPart,
|
||
sizeof(LARGE_INTEGER) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE *) &pInLargeIntegerValue->li.QuadPart,
|
||
sizeof(LARGE_INTEGER) );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
|
||
if ( bZeroLengthData ) {
|
||
pllValue->u = pPropertyItem->LargeIntData->Default.u;
|
||
} else {
|
||
pllValue->u = pInLargeIntegerValue->li.u;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetLargeIntegerProperty
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetStringProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_SZ pInStringValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a string property (SZ or EXPAND_SZ), write it to the cluster
|
||
database (or delete it if it is zero length), and save it in the
|
||
specified parameter block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInStringValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
LPWSTR UNALIGNED * ppszValue;
|
||
DWORD dwType;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInStringValue->cbLength == 0 );
|
||
|
||
//
|
||
// Validate the property data if not zero length.
|
||
//
|
||
if ( ! bZeroLengthData ) {
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( pInStringValue->cbLength != (lstrlenW( pInStringValue->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetStringProperty: Property '%1!ls!' length %2!d! doesn't match zero-term. length.\n", rrvnModifiedNames.PszName(), pInStringValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
} // if: string length doesn't match length in property
|
||
} // if: non-zero length data
|
||
|
||
ppszValue = (LPWSTR UNALIGNED *) &pOutParams[pPropertyItem->Offset];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
// Do this even if only the case of the data changed.
|
||
//
|
||
if ( (pOutParams == NULL)
|
||
|| (*ppszValue == NULL)
|
||
|| bZeroLengthData
|
||
|| bForceWrite
|
||
|| (lstrcmpW( *ppszValue, pInStringValue->sz ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( pPropertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ ) {
|
||
dwType = REG_EXPAND_SZ;
|
||
} else {
|
||
dwType = REG_SZ;
|
||
} // if/else: property format is EXPAND_SZ
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
dwType,
|
||
(CONST BYTE *) &pInStringValue->sz,
|
||
pInStringValue->cbLength );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
dwType,
|
||
(CONST BYTE *) &pInStringValue->sz,
|
||
pInStringValue->cbLength );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS)
|
||
&& (pOutParams != NULL) ) {
|
||
|
||
if ( *ppszValue != NULL ) {
|
||
LocalFree( *ppszValue );
|
||
} // if: previous value in parameter block
|
||
|
||
if ( bZeroLengthData ) {
|
||
// If a default is specified, copy it.
|
||
if ( pPropertyItem->lpDefault != NULL ) {
|
||
*ppszValue = (LPWSTR) LocalAlloc(
|
||
LMEM_FIXED,
|
||
(lstrlenW( (LPCWSTR) pPropertyItem->lpDefault ) + 1) * sizeof(WCHAR)
|
||
);
|
||
if ( *ppszValue == NULL ) {
|
||
status = GetLastError();
|
||
ClRtlDbgPrint(
|
||
LOG_CRITICAL,
|
||
"ClRtlpSetStringProperty: error allocating memory for default "
|
||
"SZ value '%1!ls!' in parameter block for property '%2!ls!'.\n",
|
||
pPropertyItem->lpDefault,
|
||
rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
lstrcpyW( *ppszValue, (LPCWSTR) pPropertyItem->lpDefault );
|
||
} else {
|
||
*ppszValue = NULL;
|
||
} // if/else: default value specified
|
||
} else {
|
||
*ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pInStringValue->cbLength );
|
||
if ( *ppszValue == NULL ) {
|
||
status = GetLastError();
|
||
ClRtlDbgPrint(
|
||
LOG_CRITICAL,
|
||
"ClRtlpSetStringProperty: error allocating memory for SZ "
|
||
"value '%1!ls!' in parameter block for property '%2!ls!'.\n",
|
||
pInStringValue->cbLength,
|
||
rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
lstrcpyW( *ppszValue, pInStringValue->sz );
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} // if: value changed or zero-length value
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetStringProperty
|
||
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetMultiStringProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_MULTI_SZ pInMultiStringValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a MULTI_SZ property, write it to the cluster database (or delete
|
||
it if it is zero length), and save it in the specified parameter block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInMultiStringValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
LPWSTR UNALIGNED * ppszValue;
|
||
DWORD * pdwValue;
|
||
DWORD dwType;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInMultiStringValue->cbLength == 0 );
|
||
|
||
ppszValue = (LPWSTR UNALIGNED *) &pOutParams[pPropertyItem->Offset];
|
||
pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset + sizeof(LPWSTR *)];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
// Do this even if only the case of the data changed.
|
||
//
|
||
if ( (pOutParams == NULL)
|
||
|| (*ppszValue == NULL)
|
||
|| (*pdwValue != pInMultiStringValue->cbLength)
|
||
|| bZeroLengthData
|
||
|| bForceWrite
|
||
|| (memcmp( *ppszValue, pInMultiStringValue->sz, *pdwValue ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( pPropertyItem->Format == CLUSPROP_FORMAT_MULTI_SZ ) {
|
||
dwType = REG_MULTI_SZ;
|
||
} else {
|
||
dwType = REG_SZ;
|
||
} // if/else: property format is EXPAND_SZ
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
dwType,
|
||
(CONST BYTE *) &pInMultiStringValue->sz,
|
||
pInMultiStringValue->cbLength );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
dwType,
|
||
(CONST BYTE *) &pInMultiStringValue->sz,
|
||
pInMultiStringValue->cbLength );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS)
|
||
&& (pOutParams != NULL) ) {
|
||
|
||
if ( *ppszValue != NULL ) {
|
||
LocalFree( *ppszValue );
|
||
} // if: previous value in parameter block
|
||
|
||
if ( bZeroLengthData ) {
|
||
// If a default is specified, copy it.
|
||
if ( pPropertyItem->lpDefault != NULL ) {
|
||
*ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pPropertyItem->Minimum );
|
||
if ( *ppszValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwValue = 0;
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetMultiStringProperty: error allocating memory for default MULTI_SZ value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
CopyMemory( *ppszValue, pPropertyItem->lpDefault, pPropertyItem->Minimum );
|
||
*pdwValue = pPropertyItem->Minimum;
|
||
} else {
|
||
*ppszValue = NULL;
|
||
*pdwValue = 0;
|
||
} // if/else: default value specified
|
||
} else {
|
||
*ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pInMultiStringValue->cbLength );
|
||
if ( *ppszValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwValue = 0;
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetMultiStringProperty: error allocating memory for MULTI_SZ value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
CopyMemory( *ppszValue, pInMultiStringValue->sz, pInMultiStringValue->cbLength );
|
||
*pdwValue = pInMultiStringValue->cbLength;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} // if: value changed or zero-length value
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetMultiStringProperty
|
||
|
||
|
||
|
||
static
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetBinaryProperty(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
|
||
IN const CRegistryValueName & rrvnModifiedNames,
|
||
IN PCLUSPROP_BINARY pInBinaryValue,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate a BINARY property, write it to the cluster database (or delete
|
||
it if it is zero length), and save it in the specified parameter block.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction handle.
|
||
|
||
hkey - The opened cluster database key where the property is to be written.
|
||
If not specified, the property will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyItem - The property from a property table to set/validate.
|
||
|
||
rrvnModifiedNames - If the name of the property contains a backslash
|
||
this object contains the modified name and keyname.
|
||
|
||
pInBinaryValue - The value from the property list to set/validate.
|
||
|
||
bForceWrite - TRUE = always write the properties to the cluster database.
|
||
FALSE = only write the properties if they changed.
|
||
|
||
pOutParams - Parameter block in which to return the data. If specified,
|
||
parameters will only be written if they are different between
|
||
the input data and the parameter block, unless bForceWrite == TRUE.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA - The format of the data is invalid for a property
|
||
list value.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
BOOL bZeroLengthData;
|
||
PBYTE UNALIGNED * ppbValue;
|
||
DWORD * pdwValue;
|
||
|
||
// Loop to avoid goto's.
|
||
do
|
||
{
|
||
bZeroLengthData = ( pInBinaryValue->cbLength == 0 );
|
||
|
||
ppbValue = (PBYTE UNALIGNED *) &pOutParams[pPropertyItem->Offset];
|
||
pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset + sizeof(PBYTE *)];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
// Do this even if only the case of the data changed.
|
||
//
|
||
if ( (pOutParams == NULL)
|
||
|| (*ppbValue == NULL)
|
||
|| (*pdwValue != pInBinaryValue->cbLength)
|
||
|| bZeroLengthData
|
||
|| bForceWrite
|
||
|| (memcmp( *ppbValue, pInBinaryValue->rgb, *pdwValue ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
// If the data length is zero, delete the value.
|
||
//
|
||
if ( hkey != NULL ) {
|
||
if ( bZeroLengthData ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName() );
|
||
} // if/else: doing/not doing a transaction
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
} else {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE *) &pInBinaryValue->rgb,
|
||
pInBinaryValue->cbLength );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
hkey,
|
||
rrvnModifiedNames.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE *) &pInBinaryValue->rgb,
|
||
pInBinaryValue->cbLength );
|
||
} // if/else: doing/not doing a transaction
|
||
} // if/else: zero length data
|
||
} // if: writing data
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
// If the data length is zero, set to the default.
|
||
//
|
||
if ( (status == ERROR_SUCCESS)
|
||
&& (pOutParams != NULL) ) {
|
||
|
||
if ( *ppbValue != NULL ) {
|
||
LocalFree( *ppbValue );
|
||
} // if: previous value in parameter block
|
||
|
||
if ( bZeroLengthData ) {
|
||
// If a default is specified, copy it.
|
||
if ( pPropertyItem->lpDefault != NULL ) {
|
||
*ppbValue = (LPBYTE) LocalAlloc( LMEM_FIXED, pPropertyItem->Minimum );
|
||
if ( *ppbValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwValue = 0;
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetBinaryProperty: error allocating memory for default BINARY value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
CopyMemory( *ppbValue, pPropertyItem->lpDefault, pPropertyItem->Minimum );
|
||
*pdwValue = pPropertyItem->Minimum;
|
||
} else {
|
||
*ppbValue = NULL;
|
||
*pdwValue = 0;
|
||
} // if/else: default value specified
|
||
} else {
|
||
*ppbValue = (LPBYTE) LocalAlloc( LMEM_FIXED, pInBinaryValue->cbLength );
|
||
if ( *ppbValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwValue = 0;
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetBinaryProperty: error allocating memory for BINARY value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
|
||
break;
|
||
} // if: error allocating memory
|
||
CopyMemory( *ppbValue, pInBinaryValue->rgb, pInBinaryValue->cbLength );
|
||
*pdwValue = pInBinaryValue->cbLength;
|
||
} // if/else: zero length data
|
||
} // if: data written successfully and parameter block specified
|
||
} // if: value changed or zero-length value
|
||
} while ( 0 );
|
||
|
||
return status;
|
||
|
||
} // ClRtlpSetBinaryProperty
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetNonPropertyTable(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
IN PVOID Reserved,
|
||
IN const PVOID pInPropertyList,
|
||
IN DWORD cbInPropertyListSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Set items that are not in the property table list.
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Local Transaction handle.
|
||
|
||
hkeyClusterKey - The opened registry key for this object's parameters.
|
||
If not specified, the property list will only be validated.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
pInPropertyList - The input buffer.
|
||
|
||
cbInPropertyListSize - The input buffer size.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
PRESUTIL_PROPERTY_ITEM propertyItem;
|
||
DWORD inBufferSize;
|
||
DWORD itemCount;
|
||
DWORD dataSize;
|
||
CLUSPROP_BUFFER_HELPER buf;
|
||
PCLUSPROP_PROPERTY_NAME pName;
|
||
BOOL bZeroLengthData;
|
||
CRegistryValueName rvn;
|
||
|
||
//
|
||
// If hKeyClusterKey is present then 'normal' functions must be present.
|
||
//
|
||
if ( ( (hkeyClusterKey != NULL) &&
|
||
((pClusterRegApis->pfnSetValue == NULL) ||
|
||
(pClusterRegApis->pfnCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL)
|
||
)) ||
|
||
( pPropertyTable == NULL ) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pClusterRegApis->pfnSetValue, pfnCreateKey, pfnOpenKey, or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// If hKeyClusterKey and hXsaction are present
|
||
// then 'local' functions must be present.
|
||
//
|
||
if ( ((hkeyClusterKey != NULL) &&
|
||
(hXsaction != NULL )) &&
|
||
((pClusterRegApis->pfnLocalCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnLocalDeleteValue == NULL)
|
||
) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pClusterRegApis->pfnpfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
if ( pInPropertyList == NULL ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
buf.pb = (LPBYTE) pInPropertyList;
|
||
inBufferSize = cbInPropertyListSize;
|
||
|
||
//
|
||
// Get the number of items in this list
|
||
//
|
||
if ( inBufferSize < sizeof(DWORD) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
itemCount = buf.pList->nPropertyCount;
|
||
buf.pdw++;
|
||
|
||
//
|
||
// Parse the rest of the items in the buffer.
|
||
//
|
||
while ( itemCount-- ) {
|
||
//
|
||
// Verify that the buffer is big enough to contain the
|
||
// property name and a value.
|
||
//
|
||
pName = buf.pName;
|
||
if ( inBufferSize < sizeof(*pName) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
|
||
if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax of the property name is correct.
|
||
//
|
||
if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: syntax %1!d! not a name syntax.\n", pName->Syntax.dw );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Verify that the length is correct for the string.
|
||
//
|
||
if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: name is not a valid C string.\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// Move the buffer pointer to the property value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
//
|
||
// Find the property name in the list of known properties.
|
||
//
|
||
propertyItem = pPropertyTable;
|
||
while ( propertyItem->Name != NULL ) {
|
||
|
||
if ( lstrcmpiW( pName->sz, propertyItem->Name ) == 0 ) {
|
||
//
|
||
// Verify that the buffer is big enough to contain the value.
|
||
//
|
||
do {
|
||
dataSize = sizeof(*buf.pValue)
|
||
+ ALIGN_CLUSPROP( buf.pValue->cbLength );
|
||
if ( inBufferSize < dataSize ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Skip this value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
} while ( buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
|
||
|
||
//
|
||
// Skip the endmark.
|
||
//
|
||
dataSize = sizeof( CLUSPROP_SYNTAX );
|
||
if ( inBufferSize < dataSize ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
break;
|
||
|
||
} else {
|
||
propertyItem++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// If no property name was found, just save this item.
|
||
//
|
||
if ( propertyItem->Name == NULL) {
|
||
//
|
||
// Verify that the buffer is big enough to contain the value.
|
||
//
|
||
dataSize = sizeof(*buf.pValue)
|
||
+ ALIGN_CLUSPROP( buf.pValue->cbLength );
|
||
if ( inBufferSize < dataSize + sizeof( CLUSPROP_SYNTAX ) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax type is LIST_VALUE.
|
||
//
|
||
if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' type CLUSPROP_TYPE_LIST_VALUE (%2!d!) expected, was %3!d!.\n", pName->sz, CLUSPROP_TYPE_LIST_VALUE, buf.pSyntax->wType );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// If the value is not specified, delete the property.
|
||
//
|
||
bZeroLengthData = ( buf.pValue->cbLength == 0 );
|
||
if ( bZeroLengthData ) {
|
||
|
||
if ( hkeyClusterKey != NULL ) {
|
||
PVOID key = NULL;
|
||
DWORD disposition;
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pName->sz, NULL );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_ALL_ACCESS,
|
||
&key);
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
key,
|
||
rvn.PszName() );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
key,
|
||
rvn.PszName() );
|
||
}
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
} // if: key specified
|
||
} else {
|
||
PVOID key = NULL;
|
||
DWORD disposition;
|
||
|
||
if ( hkeyClusterKey != NULL ) {
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pName->sz, NULL );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalCreateKey)( hXsaction,
|
||
hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition);
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition);
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
}
|
||
|
||
switch ( buf.pSyntax->wFormat ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pDwordValue->cbLength != sizeof(DWORD) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not DWORD length.\n", pName->sz, buf.pDwordValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pDwordValue->dw,
|
||
sizeof(DWORD) );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pDwordValue->dw,
|
||
sizeof(DWORD) );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_LONG:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pLongValue->cbLength != sizeof(LONG) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not LONG length.\n", pName->sz, buf.pLongValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pLongValue->l,
|
||
sizeof(LONG) );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pLongValue->l,
|
||
sizeof(LONG) );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER));
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER));
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_EXPAND_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_EXPAND_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)buf.pBinaryValue->rgb,
|
||
buf.pStringValue->cbLength );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)buf.pBinaryValue->rgb,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", pName->sz, buf.pSyntax->wFormat );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
|
||
} // switch
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
} // if/else: zero length data
|
||
|
||
//
|
||
// Move the buffer past the value.
|
||
//
|
||
do {
|
||
dataSize = sizeof(*buf.pValue)
|
||
+ ALIGN_CLUSPROP( buf.pValue->cbLength );
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
} while ( buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
|
||
dataSize = sizeof( CLUSPROP_SYNTAX );
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlpSetNonPropertyTable
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlSetPropertyParameterBlock(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
IN PVOID Reserved,
|
||
IN const LPBYTE pInParams,
|
||
IN const PVOID pInPropertyList,
|
||
IN DWORD cbInPropertyListSize,
|
||
IN BOOL bForceWrite,
|
||
IN OUT OPTIONAL LPBYTE pOutParams
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
hXsaction - Transaction key used when called from the cluster service.
|
||
|
||
hkeyClusterKey - The opened registry key for this object's parameters.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
pInParams - Parameter 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. If specified,
|
||
parameters will only be written if they are different between
|
||
the two parameter blocks.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
PRESUTIL_PROPERTY_ITEM propertyItem;
|
||
DWORD itemCount;
|
||
DWORD dataSize;
|
||
PVOID key;
|
||
LPWSTR UNALIGNED * ppszInValue;
|
||
LPWSTR UNALIGNED * ppszOutValue;
|
||
PBYTE UNALIGNED * ppbInValue;
|
||
PBYTE UNALIGNED * ppbOutValue;
|
||
DWORD * pdwInValue;
|
||
DWORD * pdwOutValue;
|
||
ULARGE_INTEGER * pullInValue;
|
||
ULARGE_INTEGER * pullOutValue;
|
||
CRegistryValueName rvn;
|
||
|
||
//
|
||
// If hKeyClusterKey is present then 'normal' functions must be present.
|
||
//
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis->pfnCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnSetValue == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ||
|
||
(pPropertyTable == NULL) ||
|
||
(pInParams == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: hkeyClusterKey, pClusterRegApis->pfnCreateKey, pfnSetValue, or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// If hXsaction is present then 'local' functions must be present.
|
||
//
|
||
if ( (hXsaction != NULL ) &&
|
||
((pClusterRegApis->pfnLocalCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnLocalSetValue == NULL) ) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: pClusterRegApis->pfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Parse the property table.
|
||
//
|
||
propertyItem = pPropertyTable;
|
||
while ( propertyItem->Name != NULL ) {
|
||
//
|
||
// Make sure we are allowed to set this item.
|
||
//
|
||
if ( propertyItem->Flags & RESUTIL_PROPITEM_READ_ONLY ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: Property '%1!ls!' is non-writable.\n", propertyItem->Name );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, create the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
|
||
DWORD disposition;
|
||
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalCreateKey)( hXsaction,
|
||
hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition );
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
return(status);
|
||
}
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
switch ( propertyItem->Format ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
pdwInValue = (DWORD *) &pInParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)pdwInValue,
|
||
sizeof(DWORD) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)pdwInValue,
|
||
sizeof(DWORD) );
|
||
}
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pOutParams != NULL) ) {
|
||
*pdwOutValue = *pdwInValue;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
pullInValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
|
||
pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)pullInValue,
|
||
sizeof(ULARGE_INTEGER) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)pullInValue,
|
||
sizeof(ULARGE_INTEGER) );
|
||
}
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
|
||
pullOutValue->u = pullInValue->u;
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
// Do this even if only the case of the data changed.
|
||
//
|
||
if ( bForceWrite ||
|
||
(pOutParams == NULL) ||
|
||
(*ppszOutValue == NULL) ||
|
||
(lstrcmpW( *ppszInValue, *ppszOutValue ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( *ppszInValue != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
(propertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ
|
||
? REG_EXPAND_SZ
|
||
: REG_SZ),
|
||
(CONST BYTE*)*ppszInValue,
|
||
(lstrlenW(*ppszInValue) + 1) * sizeof(WCHAR) );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
(propertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ
|
||
? REG_EXPAND_SZ
|
||
: REG_SZ),
|
||
(CONST BYTE*)*ppszInValue,
|
||
(lstrlenW(*ppszInValue) + 1) * sizeof(WCHAR) );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pOutParams != NULL) ) {
|
||
if ( *ppszOutValue != NULL ) {
|
||
LocalFree( *ppszOutValue );
|
||
}
|
||
if ( *ppszInValue == NULL ) {
|
||
*ppszOutValue = NULL;
|
||
} else {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( *ppszInValue )+1) * sizeof(WCHAR) );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
ClRtlDbgPrint(
|
||
LOG_CRITICAL,
|
||
"ClRtlSetPropertyParameterBlock: error allocating memory for "
|
||
"SZ value '%1!ls!' in parameter block for property '%2!ls!'.\n",
|
||
*ppszInValue,
|
||
propertyItem->Name );
|
||
break;
|
||
}
|
||
lstrcpyW( *ppszOutValue, *ppszInValue );
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pdwInValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(LPWSTR*)];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
//
|
||
if ( bForceWrite ||
|
||
(pOutParams == NULL) ||
|
||
(*ppszOutValue == NULL) ||
|
||
(*pdwInValue != *pdwOutValue) ||
|
||
(memcmp( *ppszInValue, *ppszOutValue, *pdwInValue ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( *ppszInValue != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)*ppszInValue,
|
||
*pdwInValue );
|
||
} else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)*ppszInValue,
|
||
*pdwInValue );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pOutParams != NULL) ) {
|
||
if ( *ppszOutValue != NULL ) {
|
||
LocalFree( *ppszOutValue );
|
||
}
|
||
if ( *ppszInValue == NULL ) {
|
||
*ppszOutValue = NULL;
|
||
} else {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, *pdwInValue );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwOutValue = 0;
|
||
ClRtlDbgPrint(
|
||
LOG_CRITICAL,
|
||
"ClRtlSetPropertyParameterBlock: error allocating memory for "
|
||
"MULTI_SZ value in parameter block for property '%1!ls!'.\n",
|
||
propertyItem->Name );
|
||
break;
|
||
}
|
||
CopyMemory( *ppszOutValue, *ppszInValue, *pdwInValue );
|
||
*pdwOutValue = *pdwInValue;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
ppbInValue = (PBYTE UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pdwInValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
|
||
ppbOutValue = (PBYTE UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(PBYTE*)];
|
||
|
||
//
|
||
// If the data changed, write it and save it.
|
||
//
|
||
if ( bForceWrite ||
|
||
(pOutParams == NULL) ||
|
||
(*ppbOutValue == NULL) ||
|
||
(*pdwInValue != *pdwOutValue) ||
|
||
(memcmp( *ppbInValue, *ppbOutValue, *pdwInValue ) != 0) ) {
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( *ppbInValue != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)*ppbInValue,
|
||
*pdwInValue );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)*ppbInValue,
|
||
*pdwInValue );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save the value to the output Parameter block.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pOutParams != NULL) ) {
|
||
if ( *ppbOutValue != NULL ) {
|
||
LocalFree( *ppbOutValue );
|
||
}
|
||
if ( *ppbInValue == NULL ) {
|
||
*ppbOutValue = NULL;
|
||
} else {
|
||
*ppbOutValue = (LPBYTE) LocalAlloc( LMEM_FIXED, *pdwInValue );
|
||
if ( *ppbOutValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwOutValue = 0;
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: error allocating memory for BINARY value in parameter block for property '%1!ls!'.\n", propertyItem->Name );
|
||
break;
|
||
}
|
||
CopyMemory( *ppbOutValue, *ppbInValue, *pdwInValue );
|
||
*pdwOutValue = *pdwInValue;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: Property '%1!ls!' unknown format %2!d! specified.\n", propertyItem->Name, propertyItem->Format );
|
||
status = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
//
|
||
// If an error occurred processing the property, cleanup and return.
|
||
//
|
||
if ( status != ERROR_SUCCESS ) {
|
||
return(status);
|
||
}
|
||
|
||
propertyItem++;
|
||
|
||
}
|
||
|
||
//
|
||
// Now find any parameters that are not represented in the property
|
||
// table. All of these extra properties will just be set without validation.
|
||
//
|
||
if ( (status == ERROR_SUCCESS) &&
|
||
(pInPropertyList != NULL) ) {
|
||
status = ClRtlpSetNonPropertyTable( hXsaction,
|
||
hkeyClusterKey,
|
||
pClusterRegApis,
|
||
pPropertyTable,
|
||
NULL,
|
||
pInPropertyList,
|
||
cbInPropertyListSize );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlSetPropertyParameterBlock
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpSetPrivatePropertyList(
|
||
IN HANDLE hXsaction,
|
||
IN PVOID hkeyClusterKey,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis,
|
||
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.
|
||
|
||
pClusterRegApis - Supplies a structure of function pointers for accessing
|
||
the cluster database.
|
||
|
||
pInPropertyList - The input buffer.
|
||
|
||
cbInPropertyListSize - The input buffer size.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
A Win32 Error on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status = ERROR_SUCCESS;
|
||
DWORD inBufferSize;
|
||
DWORD itemCount;
|
||
DWORD dataSize;
|
||
DWORD valueSize;
|
||
CLUSPROP_BUFFER_HELPER bufSizeTest;
|
||
CLUSPROP_BUFFER_HELPER buf;
|
||
PCLUSPROP_PROPERTY_NAME pName;
|
||
BOOL bZeroLengthData;
|
||
CRegistryValueName rvn;
|
||
|
||
if ( (hkeyClusterKey != NULL) &&
|
||
( (pClusterRegApis->pfnSetValue == NULL) ||
|
||
(pClusterRegApis->pfnCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ||
|
||
(pClusterRegApis->pfnDeleteValue == NULL)
|
||
) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pClusterRegApis->pfnCreateKey, pfnOpenKey, pfnSetValue, pfnCloseKey, or pfnDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
if ( pInPropertyList == NULL ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If hXsaction is present then 'local' functions must be present.
|
||
//
|
||
if ( (hXsaction != NULL ) &&
|
||
( (pClusterRegApis->pfnLocalCreateKey == NULL) ||
|
||
(pClusterRegApis->pfnLocalDeleteValue == NULL)
|
||
) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pClusterRegApis->pfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
buf.pb = (LPBYTE) pInPropertyList;
|
||
inBufferSize = cbInPropertyListSize;
|
||
|
||
//
|
||
// Get the number of items in this list
|
||
//
|
||
if ( inBufferSize < sizeof(DWORD) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
itemCount = buf.pList->nPropertyCount;
|
||
buf.pdw++;
|
||
|
||
//
|
||
// Parse the rest of the items in the buffer.
|
||
//
|
||
while ( itemCount-- ) {
|
||
pName = buf.pName;
|
||
if ( inBufferSize < sizeof(*pName) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
|
||
if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax of the property name is correct.
|
||
//
|
||
if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: syntax %1!d! not a name syntax.\n", pName->Syntax.dw );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Verify that the length is correct for the string.
|
||
//
|
||
if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "SetPrivatePropertyList: name is not a valid C string.\n" );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// Move the buffer pointer to the property value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
//
|
||
// Verify that the buffer is big enough to contain the value.
|
||
//
|
||
bufSizeTest.pb = buf.pb;
|
||
dataSize = 0;
|
||
do {
|
||
valueSize = sizeof( *bufSizeTest.pValue )
|
||
+ ALIGN_CLUSPROP( bufSizeTest.pValue->cbLength );
|
||
bufSizeTest.pb += valueSize;
|
||
dataSize += valueSize;
|
||
} while ( bufSizeTest.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
|
||
dataSize += sizeof( CLUSPROP_SYNTAX );
|
||
if ( inBufferSize < dataSize ) {
|
||
return(ERROR_INSUFFICIENT_BUFFER);
|
||
}
|
||
|
||
//
|
||
// Verify that the syntax type is SPECIAL.
|
||
//
|
||
if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: Property '%1!ls!' type CLUSPROP_TYPE_LIST_VALUE (%2!d!) expected, was %3!d!.\n", pName->sz, CLUSPROP_TYPE_LIST_VALUE, buf.pSyntax->wType );
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// If the value is not specified, delete the property.
|
||
//
|
||
bZeroLengthData = ( buf.pValue->cbLength == 0 );
|
||
if ( bZeroLengthData ) {
|
||
if ( hkeyClusterKey != NULL ) {
|
||
PVOID key = NULL;
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pName->sz, NULL );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_ALL_ACCESS,
|
||
&key);
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalDeleteValue)(
|
||
hXsaction,
|
||
key,
|
||
rvn.PszName() );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnDeleteValue)(
|
||
key,
|
||
rvn.PszName() );
|
||
}
|
||
|
||
//
|
||
// If the property doesn't exist in the
|
||
// cluster database, fix the status.
|
||
//
|
||
if ( status == ERROR_FILE_NOT_FOUND ) {
|
||
status = ERROR_SUCCESS;
|
||
} // if: property already doesn't exist
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
} // if: key specified
|
||
} else {
|
||
PVOID key = NULL;
|
||
DWORD disposition;
|
||
|
||
if ( hkeyClusterKey != NULL ) {
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pName->sz, NULL );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalCreateKey)(
|
||
hXsaction,
|
||
hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition);
|
||
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&key,
|
||
&disposition);
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Parse the property and set it in the cluster database
|
||
//
|
||
switch ( buf.pSyntax->wFormat ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pDwordValue->cbLength != sizeof(DWORD) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: Property '%1!ls!' length %2!d! not DWORD or LONG length.\n", pName->sz, buf.pDwordValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pDwordValue->dw,
|
||
sizeof(DWORD) );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_DWORD,
|
||
(CONST BYTE*)&buf.pDwordValue->dw,
|
||
sizeof(DWORD));
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pULargeIntegerValue->cbLength != sizeof(ULARGE_INTEGER) ) {
|
||
ClRtlDbgPrint(LOG_CRITICAL,
|
||
"ClRtlpSetPrivatePropertyList: Property '%1!ls!' length "
|
||
"%2!d! not ULARGE_INTEGER or LARGE_INTEGER length.\n",
|
||
pName->sz,
|
||
buf.pULargeIntegerValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)(
|
||
hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER) );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)(
|
||
key,
|
||
rvn.PszName(),
|
||
REG_QWORD,
|
||
(CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
|
||
sizeof(ULARGE_INTEGER));
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
//
|
||
// Verify the length of the value.
|
||
//
|
||
if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
|
||
status = ERROR_INVALID_DATA;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
(buf.pSyntax->wFormat == CLUSPROP_FORMAT_EXPAND_SZ
|
||
? REG_EXPAND_SZ
|
||
: REG_SZ),
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength);
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
(buf.pSyntax->wFormat == CLUSPROP_FORMAT_EXPAND_SZ
|
||
? REG_EXPAND_SZ
|
||
: REG_SZ),
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_MULTI_SZ,
|
||
(CONST BYTE*)buf.pStringValue->sz,
|
||
buf.pStringValue->cbLength );
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
//
|
||
// Write the value to the cluster database.
|
||
//
|
||
if ( key != NULL ) {
|
||
if ( hXsaction != NULL ) {
|
||
status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
|
||
key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)buf.pBinaryValue->rgb,
|
||
buf.pBinaryValue->cbLength );
|
||
}
|
||
else {
|
||
status = (*pClusterRegApis->pfnSetValue)( key,
|
||
rvn.PszName(),
|
||
REG_BINARY,
|
||
(CONST BYTE*)buf.pBinaryValue->rgb,
|
||
buf.pBinaryValue->cbLength );
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
status = ERROR_INVALID_PARAMETER; // not tested
|
||
|
||
} // switch
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
} // if/else: zero length data
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Move the buffer past the value.
|
||
//
|
||
buf.pb += dataSize;
|
||
inBufferSize -= dataSize;
|
||
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlpSetPrivatePropertyList
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlpFindSzProperty(
|
||
IN const PVOID pPropertyList,
|
||
IN DWORD cbPropertyListSize,
|
||
IN LPCWSTR pszPropertyName,
|
||
OUT LPWSTR * pszPropertyValue,
|
||
IN BOOL bReturnExpandedValue
|
||
)
|
||
|
||
/*++
|
||
|
||
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.
|
||
|
||
bReturnExpandedValue - TRUE = return expanded value if one is present,
|
||
FALSE = return the first value.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
LPWSTR listValueData;
|
||
DWORD listByteLength;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a string property.
|
||
//
|
||
if ( (props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_SZ) &&
|
||
(props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_EXPAND_SZ) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpFindSzProperty: Property '%1!ls!' syntax (%2!d!, %3!d!) not proper list string syntax.\n", pszPropertyName, props.pSyntax->wType, props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it
|
||
// and copy the value in.
|
||
//
|
||
if ( pszPropertyValue != NULL ) {
|
||
//
|
||
// If caller wants the expanded value, look at any
|
||
// additional values in the value list to see if one
|
||
// was returned.
|
||
//
|
||
listValueData = props.pStringValue->sz;
|
||
listByteLength = props.pStringValue->cbLength;
|
||
if ( bReturnExpandedValue ) {
|
||
//
|
||
// Skip past values in the value list looking for
|
||
// an expanded string value.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = sizeof(*props.pValue) + ALIGN_CLUSPROP(listByteLength);
|
||
cbPropertyListSize -= byteCount;
|
||
props.pb += byteCount;
|
||
if ( props.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ ) {
|
||
listValueData = props.pStringValue->sz;
|
||
listByteLength = props.pStringValue->cbLength;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate a buffer for the string value and
|
||
// copy the value from the property list.
|
||
//
|
||
valueData = (LPWSTR) LocalAlloc( LMEM_FIXED, listByteLength );
|
||
if ( valueData == NULL ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
CopyMemory( valueData, listValueData, listByteLength );
|
||
*pszPropertyValue = valueData;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list (one or more values + endmark).
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= byteCount;
|
||
props.pb += byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlpFindSzProperty
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindDwordProperty(
|
||
IN const 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.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a dword property.
|
||
//
|
||
if ( props.pDwordValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_DWORD ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlFindDwordProperty: Property '%1!ls!' syntax (%2!d!, %3!d!) not proper list DWORD syntax.\n", pszPropertyName, props.pSyntax->wType, props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( pdwPropertyValue ) {
|
||
*pdwPropertyValue = props.pDwordValue->dw;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindDwordProperty
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindLongProperty(
|
||
IN const PVOID pPropertyList,
|
||
IN DWORD cbPropertyListSize,
|
||
IN LPCWSTR pszPropertyName,
|
||
OUT LPLONG plPropertyValue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the specified dword 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.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
(cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a long property.
|
||
//
|
||
if ( props.pLongValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_DWORD ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlFindLongProperty: Property '%1!ls!' syntax (%2!d!, %3!d!) not proper list LONG syntax.\n", pszPropertyName, props.pSyntax->wType, props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( plPropertyValue) {
|
||
*plPropertyValue = props.pLongValue->l;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindLongProperty
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindULargeIntegerProperty(
|
||
IN const PVOID pPropertyList,
|
||
IN DWORD cbPropertyListSize,
|
||
IN LPCWSTR pszPropertyName,
|
||
OUT PULARGE_INTEGER pullPropertyValue
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the specified ULARGE_INTEGER 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.
|
||
|
||
pullPropertyValue - the matching ULARGE_INTEGER value found.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a LARGE INT property.
|
||
//
|
||
if ( props.pULargeIntegerValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_LARGE_INTEGER ) {
|
||
ClRtlDbgPrint(LOG_CRITICAL,
|
||
"ClRtlFindULargeIntegerProperty: Property '%1!ls!' syntax "
|
||
"(%2!d!, %3!d!) not proper list ULARGE_INTEGER syntax.\n",
|
||
pszPropertyName,
|
||
props.pSyntax->wType,
|
||
props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( pullPropertyValue ) {
|
||
pullPropertyValue->QuadPart = props.pULargeIntegerValue->li.QuadPart;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) )
|
||
{
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindULargeIntegerProperty
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindLargeIntegerProperty(
|
||
IN const PVOID pPropertyList,
|
||
IN DWORD cbPropertyListSize,
|
||
IN LPCWSTR pszPropertyName,
|
||
OUT PLARGE_INTEGER pllPropertyValue
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the specified LARGE_INTEGER 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.
|
||
|
||
pllPropertyValue - the matching ULARGE_INTEGER value found.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a large int property.
|
||
//
|
||
if ( props.pLargeIntegerValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_LARGE_INTEGER ) {
|
||
ClRtlDbgPrint(LOG_CRITICAL,
|
||
"ClRtlFindLargeIntegerProperty: Property '%1!ls!' syntax "
|
||
"(%2!d!, %3!d!) not proper list ULARGE_INTEGER syntax.\n",
|
||
pszPropertyName,
|
||
props.pSyntax->wType,
|
||
props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( pllPropertyValue ) {
|
||
pllPropertyValue->QuadPart = props.pLargeIntegerValue->li.QuadPart;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) )
|
||
{
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindLargeIntegerProperty
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindBinaryProperty(
|
||
IN const 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.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
PBYTE valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a binary property.
|
||
//
|
||
if ( props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_BINARY ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpFindBinaryProperty: Property '%1!ls!' syntax (%2!d!, %3!d!) not proper list binary syntax.\n", pszPropertyName, props.pSyntax->wType, props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( pbPropertyValue ) {
|
||
valueData = (PBYTE) LocalAlloc( LMEM_FIXED, props.pBinaryValue->cbLength );
|
||
if ( !valueData ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
CopyMemory( valueData, props.pBinaryValue->rgb, props.pBinaryValue->cbLength );
|
||
*pbPropertyValue = valueData;
|
||
}
|
||
|
||
//
|
||
// If caller wants the value size
|
||
//
|
||
if ( pcbPropertyValueSize ) {
|
||
*pcbPropertyValueSize = props.pBinaryValue->cbLength;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindBinaryProperty
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlFindMultiSzProperty(
|
||
IN const PVOID pPropertyList,
|
||
IN DWORD cbPropertyListSize,
|
||
IN LPCWSTR pszPropertyName,
|
||
OUT LPWSTR * pszPropertyValue,
|
||
OUT LPDWORD pcbPropertyValueSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the specified multiple 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 multiple string value found.
|
||
|
||
pcbPropertyValueSize - the length of the matching multiple string value found.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
|
||
ERROR_INVALID_DATA -
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY -
|
||
|
||
ERROR_FILE_NOT_FOUND -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
LPWSTR valueData;
|
||
DWORD itemCount;
|
||
DWORD byteCount;
|
||
|
||
props.pb = (LPBYTE) pPropertyList;
|
||
itemCount = *(props.pdw++);
|
||
cbPropertyListSize -= sizeof(DWORD);
|
||
|
||
while ( itemCount-- &&
|
||
((LONG)cbPropertyListSize > 0) ) {
|
||
//
|
||
// If we found the specified property, validate the entry and return
|
||
// the value to the caller.
|
||
//
|
||
if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
|
||
(lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
|
||
//
|
||
// Calculate the size of the name and move to the value.
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Make sure this is a multi-sz property.
|
||
//
|
||
if ( props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_MULTI_SZ ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpFindMultiSzProperty: Property '%1!ls!' syntax (%2!d!, %3!d!) not proper list MultiSz syntax.\n", pszPropertyName, props.pSyntax->wType, props.pSyntax->wFormat );
|
||
return(ERROR_INVALID_DATA);
|
||
}
|
||
|
||
//
|
||
// If caller wants the value, allocate a buffer for it.
|
||
//
|
||
if ( pszPropertyValue ) {
|
||
valueData = (LPWSTR) LocalAlloc( LMEM_FIXED, props.pMultiSzValue->cbLength );
|
||
if ( !valueData ) {
|
||
return(ERROR_NOT_ENOUGH_MEMORY);
|
||
}
|
||
CopyMemory( valueData, props.pBinaryValue->rgb, props.pMultiSzValue->cbLength );
|
||
*pszPropertyValue = valueData;
|
||
}
|
||
|
||
//
|
||
// If caller wants the value size
|
||
//
|
||
if ( pcbPropertyValueSize ) {
|
||
*pcbPropertyValueSize = props.pMultiSzValue->cbLength;
|
||
}
|
||
|
||
//
|
||
// We found the property so return success.
|
||
//
|
||
return(ERROR_SUCCESS);
|
||
|
||
} else {
|
||
//
|
||
// Skip the name (value header + size of data).
|
||
//
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
|
||
//
|
||
// Skip it's value list and endmark.
|
||
//
|
||
while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
|
||
(cbPropertyListSize > 0) ) {
|
||
byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
|
||
cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
|
||
props.pb += sizeof(*props.pValue) + byteCount;
|
||
}
|
||
cbPropertyListSize -= sizeof(*props.pSyntax);
|
||
props.pb += sizeof(*props.pSyntax);
|
||
}
|
||
}
|
||
|
||
return(ERROR_FILE_NOT_FOUND);
|
||
|
||
} // ClRtlFindMultiSzProperty
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetBinaryValue(
|
||
IN HKEY hkeyClusterKey,
|
||
IN LPCWSTR pszValueName,
|
||
OUT LPBYTE * ppbOutValue,
|
||
OUT LPDWORD pcbOutValueSize,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queries a REG_BINARY or REG_MULTI_SZ value out of the cluster
|
||
database and allocates the necessary storage for it.
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - Supplies the cluster key where the value is stored
|
||
|
||
pszValueName - Supplies the name of the value.
|
||
|
||
ppbOutValue - Supplies the address of a pointer in which to return the value.
|
||
|
||
pcbOutValueSize - Supplies the address of a DWORD in which to return the
|
||
size of the value.
|
||
|
||
pfnQueryValue - Address of QueryValue function.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS - The value was read successfully.
|
||
|
||
ERROR_BAD_ARGUMENTS -
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Error allocating memory for the value.
|
||
|
||
Win32 error code - The operation failed.
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE value = NULL;
|
||
DWORD valueSize;
|
||
DWORD valueType;
|
||
DWORD status;
|
||
|
||
PVOID key = NULL;
|
||
CRegistryValueName rvn;
|
||
|
||
//
|
||
// Initialize the output parameters.
|
||
//
|
||
*ppbOutValue = NULL;
|
||
*pcbOutValueSize = 0;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis == NULL) ||
|
||
(pClusterRegApis->pfnQueryValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetBinaryValue: hkeyClusterKey, pClusterRegApis, or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pszValueName, NULL );
|
||
if ( status != ERROR_SUCCESS )
|
||
{
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
if ( (pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetBinaryValue: pClusterRegApis->pfnOpenKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
|
||
return(ERROR_BAD_ARGUMENTS);
|
||
}
|
||
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_READ,
|
||
&key);
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
//
|
||
// Dummy do-while loop to avoid gotos.
|
||
//
|
||
do
|
||
{
|
||
//
|
||
// Get the size of the value so we know how much to allocate.
|
||
//
|
||
valueSize = 0;
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
NULL,
|
||
&valueSize );
|
||
if ( (status != ERROR_SUCCESS) &&
|
||
(status != ERROR_MORE_DATA) ) {
|
||
break;
|
||
}
|
||
|
||
//if the size is zero, just return
|
||
if (valueSize == 0)
|
||
{
|
||
break;
|
||
}
|
||
//
|
||
// Allocate a buffer to read the value into.
|
||
//
|
||
value = (LPBYTE) LocalAlloc( LMEM_FIXED, valueSize );
|
||
if ( value == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Read the value from the cluster database.
|
||
//
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
pszValueName,
|
||
&valueType,
|
||
(LPBYTE)value,
|
||
&valueSize );
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
LocalFree( value );
|
||
} else {
|
||
*ppbOutValue = value;
|
||
*pcbOutValueSize = valueSize;
|
||
}
|
||
|
||
}
|
||
while (FALSE);
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetBinaryValue
|
||
|
||
|
||
|
||
LPWSTR
|
||
WINAPI
|
||
ClRtlGetSzValue(
|
||
IN HKEY hkeyClusterKey,
|
||
IN LPCWSTR pszValueName,
|
||
IN const PCLUSTER_REG_APIS pClusterRegApis
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queries a REG_SZ or REG_EXPAND_SZ value out of the cluster database
|
||
and allocates the necessary storage for it.
|
||
|
||
Arguments:
|
||
|
||
hkeyClusterKey - Supplies the cluster key where the value is stored
|
||
|
||
pszValueName - Supplies the name of the value.
|
||
|
||
pfnQueryValue - Address of QueryValue function.
|
||
|
||
Return Value:
|
||
|
||
A pointer to a buffer containing the value if successful.
|
||
|
||
NULL if unsuccessful. Call GetLastError() to get more details.
|
||
|
||
--*/
|
||
|
||
{
|
||
PWSTR value;
|
||
DWORD valueSize;
|
||
DWORD valueType;
|
||
DWORD status;
|
||
PVOID key = NULL;
|
||
CRegistryValueName rvn;
|
||
|
||
if ( (hkeyClusterKey == NULL) ||
|
||
(pClusterRegApis == NULL) ||
|
||
(pClusterRegApis->pfnQueryValue == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetSzValue: hkeyClusterKey, pClusterRegApis, or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
|
||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||
return(NULL);
|
||
}
|
||
|
||
//
|
||
// Use the wrapper class CRegistryValueName to parse value name to see if it
|
||
// contains a backslash.
|
||
//
|
||
status = rvn.ScInit( pszValueName, NULL );
|
||
if ( status != ERROR_SUCCESS )
|
||
{
|
||
SetLastError(status);
|
||
return(NULL);
|
||
}
|
||
//
|
||
// If the value resides at a different location, open the key.
|
||
//
|
||
if ( rvn.PszKeyName() != NULL ) {
|
||
if ( (pClusterRegApis->pfnOpenKey == NULL) ||
|
||
(pClusterRegApis->pfnCloseKey == NULL) ) {
|
||
ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetSzValue: pClusterRegApis->pfnOpenKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
|
||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||
return(NULL);
|
||
}
|
||
|
||
status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
|
||
rvn.PszKeyName(),
|
||
KEY_READ,
|
||
&key);
|
||
|
||
} else {
|
||
key = hkeyClusterKey;
|
||
}
|
||
|
||
//
|
||
// Dummy do-while loop to avoid gotos.
|
||
//
|
||
do
|
||
{
|
||
//
|
||
// Get the size of the value so we know how much to allocate.
|
||
//
|
||
valueSize = 0;
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
NULL,
|
||
&valueSize );
|
||
if ( (status != ERROR_SUCCESS) &&
|
||
(status != ERROR_MORE_DATA) ) {
|
||
SetLastError( status );
|
||
value = NULL;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Add on the size of the null terminator.
|
||
//
|
||
valueSize += sizeof(UNICODE_NULL);
|
||
|
||
//
|
||
// Allocate a buffer to read the string into.
|
||
//
|
||
value = (PWSTR) LocalAlloc( LMEM_FIXED, valueSize );
|
||
if ( value == NULL ) {
|
||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||
value = NULL;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Read the value from the cluster database.
|
||
//
|
||
status = (*pClusterRegApis->pfnQueryValue)( key,
|
||
rvn.PszName(),
|
||
&valueType,
|
||
(LPBYTE)value,
|
||
&valueSize );
|
||
if ( status != ERROR_SUCCESS ) {
|
||
LocalFree( value );
|
||
value = NULL;
|
||
} else if ( (valueType != REG_SZ) &&
|
||
(valueType != REG_EXPAND_SZ) &&
|
||
(valueType != REG_MULTI_SZ) ) {
|
||
status = ERROR_INVALID_PARAMETER;
|
||
LocalFree( value );
|
||
SetLastError( status );
|
||
value = NULL;
|
||
}
|
||
|
||
}
|
||
while (FALSE);
|
||
|
||
//
|
||
// Close the key if we opened it.
|
||
//
|
||
if ( (rvn.PszKeyName() != NULL) &&
|
||
(key != NULL) ) {
|
||
(*pClusterRegApis->pfnCloseKey)( key );
|
||
}
|
||
|
||
return(value);
|
||
|
||
} // ClRtlGetSzValue
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlDupParameterBlock(
|
||
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 = ERROR_SUCCESS;
|
||
PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
|
||
LPWSTR UNALIGNED * ppszInValue;
|
||
DWORD * pdwInValue;
|
||
ULARGE_INTEGER * pullInValue;
|
||
LPWSTR UNALIGNED * ppszOutValue;
|
||
DWORD * pdwOutValue;
|
||
ULARGE_INTEGER * pullOutValue;
|
||
|
||
while ( propertyItem->Name != NULL ) {
|
||
switch ( propertyItem->Format ) {
|
||
case CLUSPROP_FORMAT_DWORD:
|
||
case CLUSPROP_FORMAT_LONG:
|
||
pdwInValue = (DWORD *) &pInParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
|
||
*pdwOutValue = *pdwInValue;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_ULARGE_INTEGER:
|
||
case CLUSPROP_FORMAT_LARGE_INTEGER:
|
||
pullInValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
|
||
pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
|
||
pullOutValue->u = pullInValue->u;
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
if ( *ppszInValue == NULL ) {
|
||
if ( propertyItem->lpDefault != NULL ) {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc(
|
||
LMEM_FIXED,
|
||
(lstrlenW( (LPCWSTR) propertyItem->lpDefault ) + 1) * sizeof(WCHAR)
|
||
);
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
} else {
|
||
lstrcpyW( *ppszOutValue, (LPCWSTR) propertyItem->lpDefault );
|
||
}
|
||
} else {
|
||
*ppszOutValue = NULL;
|
||
}
|
||
} else {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( *ppszInValue ) + 1) * sizeof(WCHAR) );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
} else {
|
||
lstrcpyW( *ppszOutValue, *ppszInValue );
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
pdwInValue = (DWORD *) &pInParams[propertyItem->Offset + sizeof(LPCWSTR)];
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset + sizeof(LPWSTR)];
|
||
if ( *ppszInValue == NULL ) {
|
||
if ( propertyItem->lpDefault != NULL ) {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, propertyItem->Minimum );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwOutValue = 0;
|
||
} else {
|
||
*pdwOutValue = propertyItem->Minimum;
|
||
CopyMemory( *ppszOutValue, (const PVOID) propertyItem->lpDefault, *pdwOutValue );
|
||
}
|
||
} else {
|
||
*ppszOutValue = NULL;
|
||
*pdwOutValue = 0;
|
||
}
|
||
} else {
|
||
*ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, *pdwInValue );
|
||
if ( *ppszOutValue == NULL ) {
|
||
status = GetLastError();
|
||
*pdwOutValue = 0;
|
||
} else {
|
||
CopyMemory( *ppszOutValue, *ppszInValue, *pdwInValue );
|
||
*pdwOutValue = *pdwInValue;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
propertyItem++;
|
||
}
|
||
|
||
//
|
||
// If an error occurred, make sure we don't leak memory.
|
||
//
|
||
if ( status != ERROR_SUCCESS ) {
|
||
ClRtlFreeParameterBlock( pOutParams, pInParams, pPropertyTable );
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlDupParameterBlock
|
||
|
||
|
||
|
||
void
|
||
WINAPI
|
||
ClRtlFreeParameterBlock(
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
|
||
LPCWSTR UNALIGNED * ppszInValue;
|
||
LPWSTR UNALIGNED * ppszOutValue;
|
||
|
||
while ( propertyItem->Name != NULL ) {
|
||
switch ( propertyItem->Format ) {
|
||
case CLUSPROP_FORMAT_SZ:
|
||
case CLUSPROP_FORMAT_EXPAND_SZ:
|
||
case CLUSPROP_FORMAT_MULTI_SZ:
|
||
case CLUSPROP_FORMAT_BINARY:
|
||
ppszInValue = (LPCWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
|
||
ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
|
||
|
||
if ( (pInParams == NULL) || (*ppszInValue != *ppszOutValue) ) {
|
||
LocalFree( *ppszOutValue );
|
||
}
|
||
break;
|
||
}
|
||
propertyItem++;
|
||
}
|
||
|
||
} // ClRtlFreeParameterBlock
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlMarshallPropertyTable(
|
||
IN PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
IN OUT DWORD dwSize,
|
||
IN OUT LPBYTE pBuffer,
|
||
OUT DWORD *Required
|
||
)
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Rohit (rjain) : It marshalls the pPropertyTable into a buffer so that the
|
||
buffer can be passed as an argument to the NmUpdatePerformFixups2 handler
|
||
|
||
This function assumes that the value field in all the elements of the
|
||
table is 0.
|
||
|
||
Arguments
|
||
pPropertyTable - This table is converted to buffer
|
||
|
||
dwSize - size in bytes of the pbuffer supplied
|
||
|
||
pbuffer - byte array into which pPropertyTable is copied
|
||
|
||
Required - number of bytes required
|
||
|
||
Return Value
|
||
returns
|
||
ERROR_SUCCESS on success,
|
||
ERROR_MORE_DATA if the size of pbuffer is insufficient
|
||
|
||
++*/
|
||
|
||
{
|
||
DWORD dwPosition=sizeof(DWORD);
|
||
PRESUTIL_PROPERTY_ITEM pPropertyItem=pPropertyTable;
|
||
BOOL copying = TRUE;
|
||
DWORD items=0;
|
||
DWORD dwNameLength;
|
||
DWORD dwKeyLength;
|
||
DWORD status=ERROR_SUCCESS;
|
||
|
||
*Required=sizeof(DWORD); // first DWORD will contain the number of items in PropertyTable
|
||
while(pPropertyItem->Name != NULL)
|
||
{
|
||
items++;
|
||
dwNameLength=(lstrlenW(pPropertyItem->Name)+1)*sizeof(WCHAR);
|
||
if(pPropertyItem->KeyName==NULL)
|
||
dwKeyLength=0;
|
||
else
|
||
dwKeyLength=(lstrlenW(pPropertyItem->KeyName)+1)*sizeof(WCHAR);
|
||
*Required+=(dwNameLength+dwKeyLength+8*sizeof(DWORD));
|
||
|
||
// if pbufer is smaller than needed, copying is turned off
|
||
// and only the required size is calculated
|
||
if ((copying && (dwSize < *Required)))
|
||
copying=FALSE;
|
||
|
||
if(copying)
|
||
{
|
||
|
||
// copy length of name and then the name itself
|
||
|
||
CopyMemory(pBuffer+dwPosition,&dwNameLength,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(pBuffer+dwPosition,pPropertyItem->Name,dwNameLength);
|
||
dwPosition+=dwNameLength;
|
||
|
||
//copy length of keyname and then the keyname itself
|
||
|
||
CopyMemory(pBuffer+dwPosition,&dwKeyLength,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
if(dwKeyLength!=0)
|
||
{
|
||
CopyMemory(pBuffer+dwPosition,pPropertyItem->KeyName,dwKeyLength);
|
||
dwPosition+=dwKeyLength;
|
||
}
|
||
//now copy remaining fields
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Format),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
// ISSUE-2000/11/21-charlwi
|
||
// this needs to be fixed for Large Int properties since they
|
||
// don't store their values in Default, Minimum, and Maximum
|
||
|
||
//IMP: the default value is always assumed to be a DWORD. This is
|
||
// because the values for properties in PropertyTable are stored
|
||
// in a seperate parameter list. See ClRtlSetPropertyTable
|
||
//
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Default),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Minimum),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Maximum),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Flags),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Offset),sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
}
|
||
//
|
||
// Advance to the next property.
|
||
//
|
||
pPropertyItem++;
|
||
}
|
||
if(copying)
|
||
{
|
||
CopyMemory(pBuffer,&items,sizeof(DWORD));
|
||
status=ERROR_SUCCESS;
|
||
}
|
||
else
|
||
status=ERROR_MORE_DATA;
|
||
return status;
|
||
|
||
} // MarshallPropertyTable
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlUnmarshallPropertyTable(
|
||
IN OUT PRESUTIL_PROPERTY_ITEM *ppPropertyTable,
|
||
IN LPBYTE pBuffer
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description
|
||
Rohit (rjain) : It unmarshalls the pBuffer into a RESUTIL_PROPERTY_ITEM table
|
||
|
||
Arguments
|
||
pPropertyTable - This is the resulting table
|
||
|
||
pbuffer - marshalled byte array
|
||
Return Value
|
||
returns
|
||
ERROR_SUCCESS on success,
|
||
Win32 error on error
|
||
++*/
|
||
{
|
||
PRESUTIL_PROPERTY_ITEM propertyItem;
|
||
DWORD items;
|
||
DWORD dwPosition=sizeof(DWORD);
|
||
DWORD dwLength;
|
||
DWORD i;
|
||
DWORD status=ERROR_SUCCESS;
|
||
|
||
if((pBuffer==NULL) ||(ppPropertyTable==NULL))
|
||
{
|
||
ClRtlDbgPrint( LOG_CRITICAL, "[ClRtl] Uncopy PropertyTable: Bad Argumnets\r\n");
|
||
return ERROR_BAD_ARGUMENTS;
|
||
}
|
||
|
||
CopyMemory(&items,pBuffer,sizeof(DWORD));
|
||
*ppPropertyTable=(PRESUTIL_PROPERTY_ITEM)LocalAlloc(LMEM_FIXED,(items+1)*sizeof(RESUTIL_PROPERTY_ITEM));
|
||
if(*ppPropertyTable == NULL)
|
||
{
|
||
status=GetLastError();
|
||
goto FnExit;
|
||
}
|
||
propertyItem=*ppPropertyTable;
|
||
for(i=0; i<items; i++)
|
||
{
|
||
|
||
CopyMemory(&dwLength,pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=sizeof(DWORD);
|
||
propertyItem->Name = NULL;
|
||
propertyItem->Name=(LPWSTR)LocalAlloc(LMEM_FIXED,dwLength);
|
||
if(propertyItem->Name == NULL)
|
||
{
|
||
status=GetLastError();
|
||
goto FnExit;
|
||
}
|
||
CopyMemory(propertyItem->Name,pBuffer+dwPosition,dwLength);
|
||
dwPosition+=dwLength;
|
||
|
||
CopyMemory(&dwLength,pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=sizeof(DWORD);
|
||
propertyItem->KeyName=NULL;
|
||
if (dwLength!=0)
|
||
{
|
||
propertyItem->KeyName=(LPWSTR)LocalAlloc(LMEM_FIXED,dwLength);
|
||
if(propertyItem->KeyName == NULL)
|
||
{
|
||
status=GetLastError();
|
||
goto FnExit;
|
||
}
|
||
CopyMemory(propertyItem->KeyName,pBuffer+dwPosition,dwLength);
|
||
dwPosition+=dwLength;
|
||
}
|
||
//now rest of the fields - all DWORDS
|
||
CopyMemory(&(propertyItem->Format),pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
// ISSUE-2000/11/21-charlwi
|
||
// this needs to be fixed for Large Int properties since they don't
|
||
// store their values in Default, Minimum, and Maximum
|
||
|
||
// IMP: the default value is always passed as a DWORD. This is
|
||
// because the values for properties in PropertyTable are stored
|
||
// in a seperate parameter list so the value here won't be used.
|
||
// See ClRtlSetPropertyTable
|
||
//
|
||
|
||
CopyMemory(&(propertyItem->Default),pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(&(propertyItem->Minimum),pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(&(propertyItem->Maximum),pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(&(propertyItem->Flags), pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
CopyMemory(&(propertyItem->Offset), pBuffer+dwPosition,sizeof(DWORD));
|
||
dwPosition+=(sizeof(DWORD));
|
||
|
||
propertyItem++;
|
||
}
|
||
|
||
// the last entry is marked NULL to indicate the end of table
|
||
propertyItem->Name=NULL;
|
||
FnExit:
|
||
return status;
|
||
|
||
} // UnmarshallPropertyTable
|
||
|
||
|
||
|
||
LPWSTR
|
||
WINAPI
|
||
ClRtlExpandEnvironmentStrings(
|
||
IN LPCWSTR pszSrc
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Expands environment strings and returns an allocated buffer containing
|
||
the result.
|
||
|
||
Arguments:
|
||
|
||
pszSrc - Source string to expand.
|
||
|
||
Return Value:
|
||
|
||
A pointer to a buffer containing the value if successful.
|
||
|
||
NULL if unsuccessful. Call GetLastError() to get more details.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD status;
|
||
DWORD cchDst = 0;
|
||
LPWSTR pszDst = NULL;
|
||
|
||
//
|
||
// Get the required length of the output string.
|
||
//
|
||
cchDst = ExpandEnvironmentStrings( pszSrc, NULL, 0 );
|
||
if ( cchDst == 0 ) {
|
||
status = GetLastError();
|
||
} else {
|
||
//
|
||
// Allocate a buffer for the expanded string.
|
||
//
|
||
pszDst = (LPWSTR) LocalAlloc( LMEM_FIXED, cchDst * sizeof(WCHAR) );
|
||
if ( pszDst == NULL ) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
} else {
|
||
//
|
||
// Get the expanded string.
|
||
//
|
||
cchDst = ExpandEnvironmentStrings( pszSrc, pszDst, cchDst );
|
||
if ( cchDst == 0 ) {
|
||
status = GetLastError();
|
||
LocalFree( pszDst );
|
||
pszDst = NULL;
|
||
} else {
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
SetLastError( status );
|
||
}
|
||
return(pszDst);
|
||
|
||
} // ClRtlExpandEnvironmentStrings
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPropertyFormatSize(
|
||
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 item format.
|
||
|
||
Arguments:
|
||
|
||
pPropertyTableItem - Supplies the property table item for the property
|
||
format whose size is to be returned.
|
||
|
||
pcbOutPropertyListSize - Supplies the size of the output buffer
|
||
required to add this property to a property list.
|
||
|
||
pnPropertyCount - The count of properties is incremented.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS - Operation was successful.
|
||
|
||
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_INVALID_PARAMETER -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
WORD formatType;
|
||
DWORD valueLength;
|
||
DWORD nameLength;
|
||
PCLUSPROP_SYNTAX propSyntax;
|
||
|
||
//
|
||
// We will return a name, value pair.
|
||
// each of which must be aligned.
|
||
//
|
||
// Get the format type.
|
||
//propSyntax = (PCLUSPROP_SYNTAX) &pPropertyTableItem->Format;
|
||
//formatType = propSyntax->wFormat;
|
||
|
||
nameLength = sizeof(CLUSPROP_PROPERTY_NAME)
|
||
+ ((wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
|
||
+ sizeof(CLUSPROP_SYNTAX); // for endmark
|
||
|
||
nameLength = ALIGN_CLUSPROP( nameLength );
|
||
valueLength = ALIGN_CLUSPROP( sizeof(CLUSPROP_WORD) );
|
||
*pcbOutPropertyListSize += (valueLength + nameLength);
|
||
*pnPropertyCount += 1;
|
||
|
||
return(ERROR_SUCCESS);
|
||
|
||
} // ClRtlGetPropertyFormatSize
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPropertyFormat(
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
|
||
IN OUT PVOID * pOutPropertyBuffer,
|
||
IN OUT LPDWORD pcbOutPropertyBufferSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get the total number of bytes required for this property item format.
|
||
|
||
Arguments:
|
||
|
||
pPropertyTableItem - Supplies the property table item for the property
|
||
format whose size is to be returned.
|
||
|
||
pcbOutPropertyBuffer - Supplies the size of the output buffer
|
||
required to add this property to a property list.
|
||
|
||
pcbPropertyBufferSize - The size
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS - Operation was successful.
|
||
|
||
ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
|
||
|
||
ERROR_INVALID_PARAMETER -
|
||
|
||
A Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
WORD formatType;
|
||
DWORD valueLength;
|
||
DWORD nameLength;
|
||
DWORD bytesReturned;
|
||
PCLUSPROP_SYNTAX propSyntax;
|
||
CLUSPROP_BUFFER_HELPER props;
|
||
|
||
props.pb = (LPBYTE) *pOutPropertyBuffer;
|
||
//
|
||
// We will return a name, value pair.
|
||
// each of which must be aligned.
|
||
//
|
||
// Get the format type.
|
||
propSyntax = (PCLUSPROP_SYNTAX) &pPropertyTableItem->Format;
|
||
formatType = propSyntax->wFormat;
|
||
|
||
//
|
||
// Copy the property name, which includes its syntax and length.
|
||
//
|
||
nameLength = (wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR);
|
||
props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
|
||
props.pName->cbLength = nameLength;
|
||
wcscpy( props.pName->sz, pPropertyTableItem->Name );
|
||
bytesReturned = sizeof(*props.pName) + ALIGN_CLUSPROP( nameLength );
|
||
*pcbOutPropertyBufferSize -= bytesReturned;
|
||
props.pb += bytesReturned;
|
||
|
||
//
|
||
// Copy the property value, syntax, length, and ENDMARK
|
||
//
|
||
props.pWordValue->Syntax.wFormat = CLUSPROP_FORMAT_WORD;
|
||
props.pWordValue->Syntax.wType = CLUSPROP_TYPE_LIST_VALUE;
|
||
props.pName->cbLength = sizeof(WORD);
|
||
props.pWordValue->w = formatType;
|
||
bytesReturned = sizeof(*props.pWordValue) + sizeof(CLUSPROP_SYNTAX);
|
||
props.pb += sizeof(*props.pWordValue);
|
||
props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
|
||
props.pb += sizeof(CLUSPROP_SYNTAX);
|
||
bytesReturned = sizeof(*props.pWordValue) + sizeof(CLUSPROP_SYNTAX);
|
||
*pcbOutPropertyBufferSize -= bytesReturned;
|
||
|
||
*pOutPropertyBuffer = props.pb;
|
||
|
||
return(ERROR_SUCCESS);
|
||
|
||
} // ClRtlGetPropertyFormat
|
||
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClRtlGetPropertyFormats(
|
||
IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
|
||
OUT PVOID pOutPropertyFormatList,
|
||
IN DWORD cbOutPropertyFormatListSize,
|
||
OUT LPDWORD pcbBytesReturned,
|
||
OUT LPDWORD pcbRequired
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the 'known' property formats for a given object - given its
|
||
property table.
|
||
|
||
Arguments:
|
||
|
||
pPropertyTable - Pointer to the property table to process.
|
||
|
||
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_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 = ERROR_SUCCESS;
|
||
DWORD itemCount = 0;
|
||
DWORD totalBufferLength = 0;
|
||
PVOID outBuffer = pOutPropertyFormatList;
|
||
DWORD bufferLength = cbOutPropertyFormatListSize;
|
||
PRESUTIL_PROPERTY_ITEM property;
|
||
|
||
*pcbBytesReturned = 0;
|
||
*pcbRequired = 0;
|
||
|
||
//
|
||
// Clear the output buffer
|
||
//
|
||
if ( pOutPropertyFormatList != NULL ) {
|
||
ZeroMemory( pOutPropertyFormatList, cbOutPropertyFormatListSize );
|
||
}
|
||
|
||
//
|
||
// Get the size of all properties for this object.
|
||
//
|
||
property = pPropertyTable;
|
||
while ( property->Name != NULL ) {
|
||
status = ClRtlGetPropertyFormatSize(
|
||
property,
|
||
&totalBufferLength,
|
||
&itemCount );
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
property++;
|
||
}
|
||
|
||
|
||
//
|
||
// Continue only if the operations so far have been successful.
|
||
//
|
||
if ( status == ERROR_SUCCESS ) {
|
||
//
|
||
// Count for item count at front of return data and endmark.
|
||
//
|
||
totalBufferLength += sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
|
||
|
||
//
|
||
// Verify the size of all the properties
|
||
//
|
||
if ( totalBufferLength > cbOutPropertyFormatListSize ) {
|
||
*pcbRequired = totalBufferLength;
|
||
totalBufferLength = 0;
|
||
if ( pOutPropertyFormatList == NULL ) {
|
||
status = ERROR_SUCCESS;
|
||
} else {
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
} else {
|
||
*(LPDWORD)outBuffer = itemCount;
|
||
outBuffer = (PVOID)( (PUCHAR)outBuffer + sizeof(itemCount) );
|
||
bufferLength -= sizeof(itemCount);
|
||
|
||
//
|
||
// Now fetch all of the property Formats.
|
||
//
|
||
property = pPropertyTable;
|
||
while ( property->Name != NULL ) {
|
||
status = ClRtlGetPropertyFormat(
|
||
property,
|
||
&outBuffer,
|
||
&itemCount );
|
||
|
||
if ( status != ERROR_SUCCESS ) {
|
||
break;
|
||
}
|
||
property++;
|
||
}
|
||
|
||
// Don't forget the ENDMARK
|
||
*(LPDWORD)outBuffer = CLUSPROP_SYNTAX_ENDMARK;
|
||
|
||
if ( (status != ERROR_SUCCESS) &&
|
||
(status != ERROR_MORE_DATA) ) {
|
||
totalBufferLength = 0;
|
||
}
|
||
}
|
||
|
||
*pcbBytesReturned = totalBufferLength;
|
||
}
|
||
|
||
return(status);
|
||
|
||
} // ClRtlGetPropertyFormats
|
||
|
||
|