/*++ 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 #pragma warning( push ) #include "clusrtlp.h" #include "stdio.h" #include "stdlib.h" #include "RegistryValueName.h" #include #pragma warning( pop ) #pragma warning( push, 4 ) // CL_ASSERT( 0 ) will error under W4 #pragma warning( disable : 4127 ) // conditional expression is constant #define CLRTL_NULL_STRING L"\0" // // Data alignment notes - Charlie Wickham (Q4/2000) // // All data in property lists are aligned on 32b boundaries (64b platforms // were not a consideration when this code was originally written). Quadword // data types (large ints and double star pointers in parameter tables) that // don't fall on quadword aligned boundaries will cause alignment faults when // dereferenced. Any references to a quadword data type may require that the // prop list data be copied into a properly aligned temporary structure. That // structure can then used for the duration of the // routine. ClRtlpSet{U}LargeIntProperty uses this technique. Otherwise, you // must use the UNALIGNED keyword if there is any chance the quadword could be // improperly aligned. // // Parameter blocks, which are used by resource DLLs to hold the current // property values, are expected to be naturally aligned. This means that if // the param block contains pointers, they must be correctly aligned. A number // of routines in this file use double star pointers where the value of the // double star pointer is the address of an offset into the parameter // block. If these offsets are wrong for quad data types, the resmon process // will get an alignment fault and die. // // Amazingly (or luckily depending on your point of view), the whole set of // CLUSPROP_* structures are quad aligned. All new CLUSPROP structs must be // constructed such that any member requiring quad alignment is properly // aligned. // // // 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: return the names of all properties in the specified property table as a a sequence of null terminated strings 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; DWORD cchProperties; 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); } cchProperties = cbOutPropertiesSize / sizeof( WCHAR ); // // 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 += ((DWORD) wcslen( 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; size_t cchRemaining; HRESULT hr; for ( property = pPropertyTable ; property->Name != NULL ; property++ ) { hr = StringCchCopyExW( psz, cchProperties, property->Name, NULL, &cchRemaining, 0 ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); goto Cleanup; } cchCurrentNameSize = cchProperties - (DWORD) cchRemaining + 1; *pcbBytesReturned += cchCurrentNameSize * sizeof(WCHAR); psz += cchCurrentNameSize; cchProperties -= cchCurrentNameSize; } // if: *psz = L'\0'; *pcbBytesReturned += sizeof(WCHAR); } Cleanup: 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: return the names of all private properties stored in the cluster database as a sequence of null terminated strings 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; DWORD cchProperties; LPWSTR psz = pszOutProperties; DWORD ival; DWORD currentNameLength = 20; DWORD nameLength; DWORD dataLength; DWORD type; LPWSTR pszName; HRESULT hr; *pcbBytesReturned = 0; *pcbRequired = 0; cchProperties = cbOutPropertiesSize / sizeof( WCHAR ); // // 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; for( ;; ) { // // 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; } // if: 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; } // if: continue; // retry } // else if: else if ( status != ERROR_SUCCESS ) { break; } // else if: totalBufferLength += (nameLength + 1) * sizeof(WCHAR); ++ival; } // for: // // 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; } // if: else { status = ERROR_MORE_DATA; } // else: } // if: 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; } // if: else if ( status == ERROR_MORE_DATA ) { // // but it can if a new property is added in between the // first enumeration and this one. // CL_ASSERT( 0 ); // THIS SHOULDN'T HAPPEN } // else if: else if ( status != ERROR_SUCCESS ) { break; } // else if: //CL_ASSERT( (DWORD)wcslen( name ) == nameLength ); hr = StringCchCopyW( psz, cchProperties, pszName ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); goto Cleanup; } nameLength++; psz += nameLength; cchProperties -= nameLength; *pcbBytesReturned += nameLength * sizeof(WCHAR); } // for: *psz = L'\0'; *pcbBytesReturned += sizeof(WCHAR); } // else if: } // if: Cleanup: 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: Using the specified cluster database key, build a property list of the properties identifed in the specified property table. 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++; } // while: // // 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++; } // while: // 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: Using the specified cluster database key, build a property list of the properties identifed in the specified property table as well as any other props that are not listed in the property table (the unknown props). 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 the contents of the specified property table from the cluster database and place them into the specified parameter block. 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 * ppszOutValue; LPBYTE * ppbOutValue; LPDWORD pdwOutValue; LPLONG plOutValue; ULARGE_INTEGER * pullOutValue; LARGE_INTEGER * pllOutValue; CRegistryValueName rvn; HRESULT hr; 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: // // If the value resides at a different location, open the key. // if ( rvn.PszKeyName() != NULL ) { 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 = (LPDWORD) &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 = (LPLONG) &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->QuadPart = propertyItem->ULargeIntData->Default.QuadPart; 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->QuadPart = propertyItem->LargeIntData->Default.QuadPart; status = ERROR_SUCCESS; } break; case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: ppszOutValue = (LPWSTR *) &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 ) { size_t cchTemp; cchTemp = wcslen( (LPCWSTR) propertyItem->lpDefault ) + 1; *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, cchTemp * sizeof(WCHAR) ); if ( *ppszOutValue == NULL ) { status = GetLastError(); } else { // We have no idea how big the buffer is. hr = StringCchCopyW( *ppszOutValue, cchTemp, (LPCWSTR)propertyItem->lpDefault ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } // else: } // if: } // if: } else { if ( *ppszOutValue != NULL ) { LocalFree( *ppszOutValue ); } *ppszOutValue = pszInValue; } break; case CLUSPROP_FORMAT_MULTI_SZ: case CLUSPROP_FORMAT_BINARY: ppbOutValue = (LPBYTE *) &pOutParams[propertyItem->Offset]; pdwOutValue = (PDWORD) &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++; } // while: 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 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 * ppszValue; PBYTE * ppbValue; PDWORD pdwValue; ULARGE_INTEGER * pullValue; LPWSTR pszUnexpanded; LPWSTR pszExpanded = NULL; HRESULT hr; *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 = ((DWORD) wcslen( 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; hr = StringCbCopyW( props.pName->sz, props.pName->cbLength, propertyItem->Name ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } 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 = (PDWORD) &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 maybe mis-aligned for quadword. Use the two DWORD // copy variant // props.pULargeIntegerValue->li.u = pullValue->u; props.pb += bufferIncrement; } else { copying = FALSE; } break; case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: ppszValue = (LPWSTR *) &pInParams[propertyItem->Offset]; pszUnexpanded = *ppszValue; if ( *ppszValue != NULL ) { dataSize = ((DWORD) wcslen( *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 ) { hr = StringCbCopyW( props.pStringValue->sz, dataSize, *ppszValue ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } 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 ( wcscmp( pszExpanded, pszUnexpanded ) != 0 ) { dataSize = ((DWORD) wcslen( 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; hr = StringCbCopyW( props.pStringValue->sz, dataSize, pszExpanded ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } props.pb += bufferIncrement; } else { copying = FALSE; } } LocalFree( pszExpanded ); pszExpanded = NULL; } break; case CLUSPROP_FORMAT_MULTI_SZ: ppszValue = (LPWSTR *) &pInParams[propertyItem->Offset]; pdwValue = (PDWORD) &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 *) &pInParams[propertyItem->Offset]; pdwValue = (PDWORD) &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++; } // while: 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: Read the private properties for a given object from the cluster database and build 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. 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; HRESULT hr; *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); hr = StringCbCopyW( props.pName->sz, props.pName->cbLength, name ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } 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 ( wcsncmp( pszExpanded, (LPCWSTR) data, dataLength / sizeof( WCHAR ) ) != 0 ) { dataLengthExpanded = ((DWORD) wcslen( 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 ( wcsncmp( pszExpanded, (LPCWSTR) data, dataLength / sizeof( WCHAR ) ) != 0 ) { props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ; props.pStringValue->cbLength = dataLengthExpanded; hr = StringCbCopyW( props.pStringValue->sz, props.pStringValue->cbLength, pszExpanded ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } 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); // // data (the local var) is aligned since it was // LocalAlloc'ed but props might not be. Use the two DWORD // copy variant. // props.pULargeIntegerValue->li.u = ((ULARGE_INTEGER *)data)->u; props.pb += bufferIncrement; } else { copying = FALSE; } break; default: break; } // switch: 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; } } // for: 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: Read the unknown properties for a given object from the cluster database and build a property list; unknown is defined to be anything not in the specified property table. 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; CLUSPROP_BUFFER_HELPER props; PRESUTIL_PROPERTY_ITEM property; BOOL found; LPWSTR pszExpanded = NULL; HRESULT hr; *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); hr = StringCbCopyW( props.pName->sz, props.pName->cbLength, name ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } 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 ( wcsncmp( pszExpanded, (LPCWSTR) data, dataLength ) != 0 ) { dataLengthExpanded = ((DWORD) wcslen( 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 ( wcsncmp( pszExpanded, (LPCWSTR) data, dataLength ) != 0 ) { props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ; props.pStringValue->cbLength = dataLengthExpanded; hr = StringCbCopyW( props.pStringValue->sz, props.pStringValue->cbLength, pszExpanded ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } 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); // // data (the local var) is aligned since it was // LocalAlloc'ed but props might not be. Use the two DWORD // copy variant. // 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 the specified property list. Unknown is defined to be any registry values in the cluster key that are not named in the property table. 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 the property identified by pPropertyTableItem. 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 = ((DWORD) wcslen((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR); pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR)pPropertyTableItem->lpDefault ); if ( pszExpanded == NULL ) { status = GetLastError(); } else if ( wcscmp( (LPCWSTR)pPropertyTableItem->lpDefault, pszExpanded ) != 0 ) { bytesReturned += ALIGN_CLUSPROP( ((DWORD) wcslen( pszExpanded ) + 1) * sizeof( WCHAR ) ); bytesReturned += sizeof(CLUSPROP_SZ); } LocalFree( pszExpanded ); } else { bytesReturned = ((DWORD) wcslen(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 ( wcscmp( pszValue, pszExpanded ) != 0 ) { bytesReturned += ALIGN_CLUSPROP( ((DWORD) wcslen( 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 { // // calculate the size of the "header" which consists of a property // name structure, the length of the property name, the size of // the property value structure minus the size of the storage area // (property specific) and the syntax endmark. // //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) + (((DWORD) wcslen( 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) + (((DWORD) wcslen( 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) + (((DWORD) wcslen( 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: build a property list entry for the property specified by the property table item. 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 - Pointer to the property item to process. pOutPropertyItem - Supplies the output buffer. pcbOutPropertyItemSize - Pointer that receives the number of bytes written to the output buffer 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; HRESULT hr; 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 = ((DWORD) wcslen((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR); } else { bytesReturned = ((DWORD) wcslen(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 = ((DWORD) wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR); props.pSyntax->dw = CLUSPROP_SYNTAX_NAME; props.pName->cbLength = nameLength; hr = StringCbCopyW( props.pName->sz, props.pName->cbLength, pPropertyTableItem->Name ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); goto Cleanup; } 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 that CLUSPROP_SZ, CLUSPROP_MULTI_SZ, and // CLUSPROP_BINARY are all 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 = ((DWORD) wcslen((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR); if ( bufferSize >= bytesReturned ) { hr = StringCbCopyW( (LPWSTR) dataBuffer, bytesReturned, (LPCWSTR) pPropertyTableItem->lpDefault ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } } else { bytesReturned = ((DWORD) wcslen(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: ERROR_FILE_NOT_FOUND 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 = ((DWORD) wcslen( pszExpanded ) + 1) * sizeof( WCHAR ); props.pStringValue->cbLength = bufferSize; bufferSize = ALIGN_CLUSPROP( bufferSize ); hr = StringCbCopyW( props.pStringValue->sz, props.pStringValue->cbLength, pszExpanded ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); } else { 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; } Cleanup: // // 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: write the properties identified in the property table from the property list to the cluster database. Update the values in the optional parameter block if the block's values are different from those in the property list. 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 property list (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 propList; PCLUSPROP_PROPERTY_NAME propName; CRegistryValueName rvn; UNREFERENCED_PARAMETER( Reserved ); 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); } propList.pb = (LPBYTE) pInPropertyList; inBufferSize = cbInPropertyListSize; // // Get the number of items in this list // if ( inBufferSize < sizeof(DWORD) ) { return(ERROR_INSUFFICIENT_BUFFER); } itemCount = propList.pList->nPropertyCount; propList.pdw++; inBufferSize -= sizeof(*propList.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. // propName = propList.pName; if ( inBufferSize < sizeof(*propName) ) { return(ERROR_INSUFFICIENT_BUFFER); } dataSize = sizeof(*propName) + ALIGN_CLUSPROP( propName->cbLength ); if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) { return(ERROR_INSUFFICIENT_BUFFER); } // // Verify that the syntax of the property name is correct. // if ( propName->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 ( propName->cbLength != (wcslen( propName->sz ) + 1) * sizeof(WCHAR) ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: property name size doesn't match stored length.\n" ); return(ERROR_INVALID_DATA); } // // Move the buffer pointer to the property value. // propList.pb += dataSize; inBufferSize -= dataSize; // // Find the property name in the list of known properties. // propertyItem = pPropertyTable; while ( propertyItem->Name != NULL ) { if ( lstrcmpiW( propName->sz, propertyItem->Name ) == 0 ) { // // Verify that the buffer is big enough to contain the value. // dataSize = sizeof(*propList.pValue) + ALIGN_CLUSPROP( propList.pValue->cbLength ) + sizeof(CLUSPROP_SYNTAX); // endmark if ( inBufferSize < dataSize ) { return(ERROR_INSUFFICIENT_BUFFER); } // // Verify that the syntax type is LIST_VALUE. // if ( propList.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", propName->sz, CLUSPROP_TYPE_LIST_VALUE, propList.pSyntax->wType ); return(ERROR_INVALID_PARAMETER); } // // Verify that this property should be of this format. // if ( propList.pSyntax->wFormat != propertyItem->Format ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' format %2!d! expected, was %3!d!.\n", propName->sz, propertyItem->Format, propList.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", propName->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 ( propList.pSyntax->wFormat ) { case CLUSPROP_FORMAT_DWORD: status = ClRtlpSetDwordProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pDwordValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_LONG: status = ClRtlpSetLongProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pLongValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_ULARGE_INTEGER: status = ClRtlpSetULargeIntegerProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pULargeIntegerValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_LARGE_INTEGER: status = ClRtlpSetLargeIntegerProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pLargeIntegerValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: status = ClRtlpSetStringProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pStringValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_MULTI_SZ: status = ClRtlpSetMultiStringProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pStringValue, bForceWrite, pOutParams ); break; case CLUSPROP_FORMAT_BINARY: status = ClRtlpSetBinaryProperty( hXsaction, key, pClusterRegApis, propertyItem, rvn, propList.pBinaryValue, bForceWrite, pOutParams ); break; default: ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", propName->sz, propList.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. // propList.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", propName->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", propName->sz ); return(ERROR_INVALID_PARAMETER); } // // Advance the buffer pointer past the value in the value list. // while ( (propList.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) && (inBufferSize > 0) ) { // ASSERT(inBufferSize > sizeof(*propList.pValue) + ALIGN_CLUSPROP(propList.pValue->cbLength)); propList.pb += sizeof(*propList.pValue) + ALIGN_CLUSPROP(propList.pValue->cbLength); inBufferSize -= sizeof(*propList.pValue) + ALIGN_CLUSPROP(propList.pValue->cbLength); } // while: more values in the list // // Advance the buffer pointer past the value list endmark. // // ASSERT(inBufferSize >= sizeof(*propList.pSyntax)); propList.pb += sizeof(*propList.pSyntax); // endmark inBufferSize -= sizeof(*propList.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; PDWORD pdwValue; UNREFERENCED_PARAMETER( bForceWrite ); 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; goto Cleanup; } // 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; goto Cleanup; } // 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; goto Cleanup; } // if: value to low } // if: non-zero length data pdwValue = (PDWORD) &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 Cleanup: 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; PLONG plValue; UNREFERENCED_PARAMETER( bForceWrite ); 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; goto Cleanup; } // 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; goto Cleanup; } // 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; goto Cleanup; } // if: value too small } // if: non-zero length data plValue = (PLONG) &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 Cleanup: 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 * pullOutParamValue; // pointer to optional Output paramter block ULARGE_INTEGER ullPropListValue; UNREFERENCED_PARAMETER( bForceWrite ); // // proplists are dword aligned and therefore might cause an alignment // fault when we make the range checks. Copy it (by DWORDs) into a // properly aligned automatic variable. // ullPropListValue.u = pInULargeIntegerValue->li.u; 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; goto Cleanup; } // if: data in value not size of DWORD // // Verify that the value is within the valid range. first check // the max value // if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && ((LONGLONG)ullPropListValue.QuadPart > (LONGLONG)pPropertyItem->ULargeIntData->Maximum.QuadPart)) || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && (ullPropListValue.QuadPart > pPropertyItem->ULargeIntData->Maximum.QuadPart)) ) { ClRtlDbgPrint(LOG_UNUSUAL, "ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value %2!I64u! " "too large.\n", rrvnModifiedNames.PszName(), ullPropListValue.QuadPart ); status = ERROR_INVALID_DATA; goto Cleanup; } // if: value too high if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && ((LONGLONG)ullPropListValue.QuadPart < (LONGLONG)pPropertyItem->ULargeIntData->Minimum.QuadPart)) || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && (ullPropListValue.QuadPart < pPropertyItem->ULargeIntData->Minimum.QuadPart)) ) { ClRtlDbgPrint(LOG_UNUSUAL, "ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value " "%2!I64u! too small.\n", rrvnModifiedNames.PszName(), ullPropListValue.QuadPart ); status = ERROR_INVALID_DATA; goto Cleanup; } // if: value to low } // if: non-zero length data // // 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 *) &ullPropListValue.QuadPart, sizeof(ULARGE_INTEGER) ); } else { status = (*pClusterRegApis->pfnSetValue)( hkey, rrvnModifiedNames.PszName(), REG_QWORD, (CONST BYTE *) &ullPropListValue.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) ) { pullOutParamValue = (ULARGE_INTEGER *) &pOutParams[pPropertyItem->Offset]; if ( bZeroLengthData ) { pullOutParamValue->QuadPart = pPropertyItem->ULargeIntData->Default.QuadPart; } else { pullOutParamValue->QuadPart = ullPropListValue.QuadPart; } // if/else: zero length data } // if: data written successfully and parameter block specified Cleanup: 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 * pllOutParamValue; LARGE_INTEGER llPropListValue; UNREFERENCED_PARAMETER( bForceWrite ); // // proplists are dword aligned and therefore might cause an alignment // fault when we make the range checks. Copy it (by DWORDs) into a // properly aligned automatic variable. // llPropListValue.u = pInLargeIntegerValue->li.u; 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; goto Cleanup; } // if: data in value not size of DWORD // // Verify that the value is within the valid range. // if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && ((LONGLONG)llPropListValue.QuadPart > (LONGLONG)pPropertyItem->LargeIntData->Maximum.QuadPart)) || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && (llPropListValue.QuadPart > pPropertyItem->LargeIntData->Maximum.QuadPart)) ) { ClRtlDbgPrint(LOG_UNUSUAL, "ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value %2!I64d! " "too large.\n", rrvnModifiedNames.PszName(), llPropListValue.QuadPart ); status = ERROR_INVALID_DATA; goto Cleanup; } // if: value too high if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && ((LONGLONG)llPropListValue.QuadPart < (LONGLONG)pPropertyItem->LargeIntData->Minimum.QuadPart)) || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED) && (llPropListValue.QuadPart < pPropertyItem->LargeIntData->Minimum.QuadPart)) ) { ClRtlDbgPrint(LOG_UNUSUAL, "ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value " "%2!I64d! too small.\n", rrvnModifiedNames.PszName(), llPropListValue.QuadPart ); status = ERROR_INVALID_DATA; goto Cleanup; } // if: value to low } // if: non-zero length data // // 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 *) &llPropListValue.QuadPart, sizeof(LARGE_INTEGER) ); } else { status = (*pClusterRegApis->pfnSetValue)( hkey, rrvnModifiedNames.PszName(), REG_QWORD, (CONST BYTE *) &llPropListValue.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) ) { pllOutParamValue = (LARGE_INTEGER *) &pOutParams[pPropertyItem->Offset]; if ( bZeroLengthData ) { pllOutParamValue->QuadPart = pPropertyItem->LargeIntData->Default.QuadPart; } else { pllOutParamValue->QuadPart = llPropListValue.QuadPart; } // if/else: zero length data } // if: data written successfully and parameter block specified Cleanup: 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 * ppszValue; DWORD dwType; size_t cbValLen; HRESULT hr; bZeroLengthData = ( pInStringValue->cbLength == 0 ); // // Validate the property data if not zero length. // if ( ! bZeroLengthData ) { // // Verify the length of the value. // if ( pInStringValue->cbLength != (wcslen( 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; goto Cleanup; } // if: string length doesn't match length in property } // if: non-zero length data ppszValue = (LPWSTR *) &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 || (wcsncmp( *ppszValue, pInStringValue->sz, pInStringValue->cbLength / sizeof( WCHAR ) ) != 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 ) { cbValLen = (wcslen( (LPCWSTR) pPropertyItem->lpDefault ) + 1) * sizeof(WCHAR); *ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, cbValLen ); 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() ); goto Cleanup; } // if: error allocating memory hr = StringCbCopyW( *ppszValue, cbValLen, (LPCWSTR) pPropertyItem->lpDefault ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); goto Cleanup; } } 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() ); goto Cleanup; } // if: error allocating memory hr = StringCbCopyW( *ppszValue, pInStringValue->cbLength, pInStringValue->sz ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); goto Cleanup; } } // if/else: zero length data } // if: data written successfully and parameter block specified } // if: value changed or zero-length value Cleanup: 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 * ppszValue; PDWORD pdwValue; DWORD dwType; bZeroLengthData = ( pInMultiStringValue->cbLength == 0 ); ppszValue = (LPWSTR *) &pOutParams[pPropertyItem->Offset]; pdwValue = (PDWORD) &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() ); goto Cleanup; } // 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() ); goto Cleanup; } // 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 Cleanup: 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 * ppbValue; PDWORD pdwValue; bZeroLengthData = ( pInBinaryValue->cbLength == 0 ); ppbValue = (PBYTE *) &pOutParams[pPropertyItem->Offset]; pdwValue = (PDWORD) &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() ); goto Cleanup; } // 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() ); goto Cleanup; } // 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 Cleanup: 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: Write the properties in the property list which are not specified in the property table to the cluster database. 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 propList; PCLUSPROP_PROPERTY_NAME pName; BOOL bZeroLengthData; CRegistryValueName rvn; UNREFERENCED_PARAMETER( Reserved ); // // 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); } propList.pb = (LPBYTE) pInPropertyList; inBufferSize = cbInPropertyListSize; // // Get the number of items in this list // if ( inBufferSize < sizeof(DWORD) ) { return(ERROR_INSUFFICIENT_BUFFER); } itemCount = propList.pList->nPropertyCount; propList.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 = propList.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 != (wcslen( 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. // propList.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(*propList.pValue) + ALIGN_CLUSPROP( propList.pValue->cbLength ); if ( inBufferSize < dataSize ) { return(ERROR_INSUFFICIENT_BUFFER); } // // Skip this value. // propList.pb += dataSize; inBufferSize -= dataSize; } while ( propList.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK ); // // Skip the endmark. // dataSize = sizeof( CLUSPROP_SYNTAX ); if ( inBufferSize < dataSize ) { return(ERROR_INSUFFICIENT_BUFFER); } propList.pb += dataSize; inBufferSize -= dataSize; break; } else { propertyItem++; } } // while: // // 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(*propList.pValue) + ALIGN_CLUSPROP( propList.pValue->cbLength ); if ( inBufferSize < dataSize + sizeof( CLUSPROP_SYNTAX ) ) { return(ERROR_INSUFFICIENT_BUFFER); } // // Verify that the syntax type is LIST_VALUE. // if ( propList.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, propList.pSyntax->wType ); return(ERROR_INVALID_PARAMETER); } // // If the value is not specified, delete the property. // bZeroLengthData = ( propList.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; } } switch ( propList.pSyntax->wFormat ) { case CLUSPROP_FORMAT_DWORD: // // Verify the length of the value. // if ( propList.pDwordValue->cbLength != sizeof(DWORD) ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not DWORD length.\n", pName->sz, propList.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*)&propList.pDwordValue->dw, sizeof(DWORD) ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_DWORD, (CONST BYTE*)&propList.pDwordValue->dw, sizeof(DWORD) ); } } break; case CLUSPROP_FORMAT_LONG: // // Verify the length of the value. // if ( propList.pLongValue->cbLength != sizeof(LONG) ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not LONG length.\n", pName->sz, propList.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*)&propList.pLongValue->l, sizeof(LONG) ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_DWORD, (CONST BYTE*)&propList.pLongValue->l, sizeof(LONG) ); } } break; case CLUSPROP_FORMAT_ULARGE_INTEGER: case CLUSPROP_FORMAT_LARGE_INTEGER: // // Verify the length of the value. // if ( propList.pULargeIntegerValue->cbLength != sizeof(ULARGE_INTEGER) ) { ClRtlDbgPrint(LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! " "not QWORD length.\n", pName->sz, propList.pULargeIntegerValue->cbLength ); status = ERROR_INVALID_DATA; break; } // // Write the value to the cluster database. Alignment // is not an issue since the SetValue API treats the // data as a stream of bytes instead of a large int. // if ( key != NULL ) { if ( hXsaction ) { status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction, key, rvn.PszName(), REG_QWORD, (CONST BYTE*)&propList.pULargeIntegerValue->li.QuadPart, sizeof(ULARGE_INTEGER)); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_QWORD, (CONST BYTE*)&propList.pULargeIntegerValue->li.QuadPart, sizeof(ULARGE_INTEGER)); } } break; case CLUSPROP_FORMAT_SZ: // // Verify the length of the value. // if ( propList.pStringValue->cbLength != (wcslen( propList.pStringValue->sz ) + 1) * sizeof(WCHAR) ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, propList.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*)propList.pStringValue->sz, propList.pStringValue->cbLength ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_SZ, (CONST BYTE*)propList.pStringValue->sz, propList.pStringValue->cbLength ); } } break; case CLUSPROP_FORMAT_EXPAND_SZ: // // Verify the length of the value. // if ( propList.pStringValue->cbLength != (wcslen( propList.pStringValue->sz ) + 1) * sizeof(WCHAR) ) { ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, propList.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*)propList.pStringValue->sz, propList.pStringValue->cbLength ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_EXPAND_SZ, (CONST BYTE*)propList.pStringValue->sz, propList.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*)propList.pStringValue->sz, propList.pStringValue->cbLength ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_MULTI_SZ, (CONST BYTE*)propList.pStringValue->sz, propList.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*)propList.pBinaryValue->rgb, propList.pStringValue->cbLength ); } else { status = (*pClusterRegApis->pfnSetValue)( key, rvn.PszName(), REG_BINARY, (CONST BYTE*)propList.pBinaryValue->rgb, propList.pStringValue->cbLength ); } } break; default: ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", pName->sz, propList.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(*propList.pValue) + ALIGN_CLUSPROP( propList.pValue->cbLength ); propList.pb += dataSize; inBufferSize -= dataSize; } while ( propList.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK ); dataSize = sizeof( CLUSPROP_SYNTAX ); propList.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: Write the properties as defined by the property table from the parameter block to the cluster database. Then parse the property list and write any properties that are not in the property table to the cluster database. 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; PVOID key; LPWSTR * ppszInValue; LPWSTR * ppszOutValue; PBYTE * ppbInValue; PBYTE * ppbOutValue; PDWORD pdwInValue; PDWORD pdwOutValue; size_t cbValLen; HRESULT hr; ULARGE_INTEGER * pullInValue; ULARGE_INTEGER * pullOutValue; CRegistryValueName rvn; UNREFERENCED_PARAMETER( Reserved ); // // 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 pfnLocalSetValue == 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 = (PDWORD) &pInParams[propertyItem->Offset]; pdwOutValue = (PDWORD) &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 *) &pInParams[propertyItem->Offset]; ppszOutValue = (LPWSTR *) &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) || (*ppszInValue == NULL) || (wcscmp( *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, ((DWORD) wcslen(*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, ((DWORD) wcslen(*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 { cbValLen = (wcslen( *ppszInValue )+1) * sizeof(WCHAR); *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, cbValLen ); 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; } hr = StringCbCopyW( *ppszOutValue, cbValLen, *ppszInValue ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } // else: } // if: } // if: break; case CLUSPROP_FORMAT_MULTI_SZ: ppszInValue = (LPWSTR *) &pInParams[propertyItem->Offset]; pdwInValue = (PDWORD) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)]; ppszOutValue = (LPWSTR *) &pOutParams[propertyItem->Offset]; pdwOutValue = (PDWORD) &pOutParams[propertyItem->Offset+sizeof(LPWSTR*)]; // // If the data changed, write it and save it. // if ( bForceWrite || (pOutParams == NULL) || (*ppszOutValue == NULL) || (*pdwInValue != *pdwOutValue) || (*ppszInValue == NULL) || (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 *) &pInParams[propertyItem->Offset]; pdwInValue = (PDWORD) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)]; ppbOutValue = (PBYTE *) &pOutParams[propertyItem->Offset]; pdwOutValue = (PDWORD) &pOutParams[propertyItem->Offset+sizeof(PBYTE*)]; // // If the data changed, write it and save it. // if ( bForceWrite || (pOutParams == NULL) || (*ppbOutValue == NULL) || (*pdwInValue != *pdwOutValue) || (*ppbInValue == NULL) || (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 != (wcslen( 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 != (wcslen( 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; 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, copy it into their output buffer // 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 LONG 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; 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, copy it into their output buffer // 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; 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, copy it into their output // buffer. Don't assume that props is aligned; use the double // DWORD copy variant. // if ( pullPropertyValue ) { pullPropertyValue->u = props.pULargeIntegerValue->li.u; } // // 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; 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, copy it into their output // buffer. Don't assume that props is aligned; use the double // DWORD copy variant. // if ( pllPropertyValue ) { pllPropertyValue->u = props.pLargeIntegerValue->li.u; } // // 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, copy it now // 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, copy it now // 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; } // // 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) ) { goto Cleanup; } //if the size is zero, just return if (valueSize == 0) { goto Cleanup; } // // Allocate a buffer to read the value into. // value = (LPBYTE) LocalAlloc( LMEM_FIXED, valueSize ); if ( value == NULL ) { status = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // // 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; } Cleanup: // // 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; } // // 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; goto Cleanup; } // // 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; goto Cleanup; } // // 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; } Cleanup: // // 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 * ppszInValue; LPDWORD pdwInValue; LPWSTR * ppszOutValue; LPDWORD pdwOutValue; size_t cbValLen; HRESULT hr; ULARGE_INTEGER * pullInValue; ULARGE_INTEGER * pullOutValue; // // loop through the entries in the property table // while ( propertyItem->Name != NULL ) { switch ( propertyItem->Format ) { case CLUSPROP_FORMAT_DWORD: case CLUSPROP_FORMAT_LONG: pdwInValue = (LPDWORD) &pInParams[propertyItem->Offset]; pdwOutValue = (LPDWORD) &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->QuadPart = pullInValue->QuadPart; break; case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: ppszInValue = (LPWSTR *) &pInParams[propertyItem->Offset]; ppszOutValue = (LPWSTR *) &pOutParams[propertyItem->Offset]; if ( *ppszInValue == NULL ) { if ( propertyItem->lpDefault != NULL ) { cbValLen = (wcslen( (LPCWSTR) propertyItem->lpDefault ) + 1) * sizeof(WCHAR); *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, cbValLen ); if ( *ppszOutValue == NULL ) { status = GetLastError(); } else { hr = StringCbCopyW( *ppszOutValue, cbValLen, (LPCWSTR) propertyItem->lpDefault ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } } else { *ppszOutValue = NULL; } } else { cbValLen = (wcslen( *ppszInValue ) + 1) * sizeof(WCHAR); *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, cbValLen ); if ( *ppszOutValue == NULL ) { status = GetLastError(); } else { hr = StringCbCopyW( *ppszOutValue, cbValLen, *ppszInValue ); if ( FAILED( hr ) ) { status = HRESULT_CODE( hr ); break; } } } break; case CLUSPROP_FORMAT_MULTI_SZ: case CLUSPROP_FORMAT_BINARY: ppszInValue = (LPWSTR *) &pInParams[propertyItem->Offset]; pdwInValue = (LPDWORD) &pInParams[propertyItem->Offset + sizeof(LPCWSTR)]; ppszOutValue = (LPWSTR *) &pOutParams[propertyItem->Offset]; pdwOutValue = (LPDWORD) &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 * ppszInValue; LPWSTR * 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 *) &pInParams[propertyItem->Offset]; ppszOutValue = (LPWSTR *) &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. The marshalled buffer has the following format: +-----------------------------------------------+ | Count of marshalled prop table items | +-----------------------------------------------+ | Number of bytes in prop name string | +-----------------------------------------------+ | Prop Name string (variable length) | +-----------------------------------------------+ | Number of bytes in key name (can be zero) | +-----------------------------------------------+ | Key name string (optional; variable length | +-----------------------------------------------+ | Prop Format | +-----------------------------------------------+ | Default Value | +-----------------------------------------------+ | Min | +-----------------------------------------------+ | Max | +-----------------------------------------------+ | Flags | +-----------------------------------------------+ | Offset | +-----------------------------------------------+ The processing for the strings don't force the next entry to be DWORD aligned. 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=((DWORD) wcslen(pPropertyItem->Name)+1)*sizeof(WCHAR); if(pPropertyItem->KeyName==NULL) { dwKeyLength=0; } else { dwKeyLength=((DWORD) wcslen(pPropertyItem->KeyName)+1)*sizeof(WCHAR); } // // total is the lengths of the strings plus 2 DWORDs for string counts // and 6 DWORDs for the remaining values // *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 Cleanup; } propertyItem=*ppPropertyTable; for(i=0; iName = NULL; propertyItem->Name=(LPWSTR)LocalAlloc(LMEM_FIXED,dwLength); if(propertyItem->Name == NULL) { status=GetLastError(); goto Cleanup; } 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 Cleanup; } 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++; } // for: // the last entry is marked NULL to indicate the end of table propertyItem->Name=NULL; Cleanup: 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 = ExpandEnvironmentStringsW( 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 = ExpandEnvironmentStringsW( 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. --*/ { DWORD valueLength; DWORD nameLength; // // We will return a name, value pair. // each of which must be aligned. // // Get the format type. //PCLUSPROP_SYNTAX propSyntax; //WORD formatType; //propSyntax = (PCLUSPROP_SYNTAX) &pPropertyTableItem->Format; //formatType = propSyntax->wFormat; nameLength = sizeof(CLUSPROP_PROPERTY_NAME) + (((DWORD) 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 nameLength; DWORD bytesReturned; PCLUSPROP_SYNTAX propSyntax; CLUSPROP_BUFFER_HELPER props; DWORD sc = ERROR_SUCCESS; HRESULT hr; 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 = ((DWORD) wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR); props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME; props.pName->cbLength = nameLength; hr = StringCbCopyW( props.pName->sz, props.pName->cbLength, pPropertyTableItem->Name ); if ( FAILED( hr ) ) { sc = HRESULT_CODE( hr ); goto Cleanup; } 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; Cleanup: return sc; } // 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 #pragma warning( pop )