Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7998 lines
281 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. rtlprop.c
  5. Abstract:
  6. Implements the management of properties.
  7. Author:
  8. Rod Gamache (rodga) 7-Jan-1996
  9. Revision History:
  10. David Potter (davidp) 12-Mar-1997
  11. Moved to CLUSRTL.
  12. --*/
  13. #define UNICODE 1
  14. #define _UNICODE 1
  15. #include "clusrtlp.h"
  16. #include "stdio.h"
  17. #include "stdlib.h"
  18. #include "RegistryValueName.h"
  19. #define CLRTL_NULL_STRING L"\0"
  20. //
  21. // Data alignment notes
  22. //
  23. // All data (including embedded pointers) are aligned on 32b boundaries (64b
  24. // platforms where not a consideration when this code was originally
  25. // written). This makes some of the typecasting a bit tricky since the
  26. // embedded pointers are really pointers to pointers. All double star pointers
  27. // (i.e., LPBYTE *) have to use UNALIGNED since it is possible that the
  28. // starting address of the pointer, i.e., the value contained in the variable,
  29. // could end in a 4 (which on 64b. platforms is unaligned). (LPBYTE *) becomes
  30. // (LPBYTE UNALIGNED *) or BYTE * UNALIGNED *.
  31. //
  32. // Consider these statements from below:
  33. //
  34. // LPWSTR UNALIGNED * ppszOutValue;
  35. // ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  36. //
  37. // ppszOutValue is an automatic variable so its address is guaranteed to be
  38. // aligned. pOutParams is essentially an array of DWORDS (though we make no
  39. // effort to enforce this. If that changed, property lists would be broken in
  40. // many different places). It is possible that when we take the address of
  41. // pOutParams + Offset, the offset may be on a DWORD boundary and not a QUAD
  42. // boundary. Therefore we have to treat ppszOutValue's value (a pointer to
  43. // WCHAR) as unaligned (the data itself is properly aligned). You can read the
  44. // typecast as "an aligned pointer (ppszOutValue) to an unaligned pointer
  45. // (address of pOutParams[Offset]) to an aligned WCHAR."
  46. //
  47. // LARGE_INTEGER allows us to "cheat" in that we can leverage the internal
  48. // struct definition of LARGER_INTEGER to do 2 DWORD copies instead of
  49. // treating the data for worst-case alignment.
  50. //
  51. // ISSUE-01/03/16 charlwi CLUSPROP_BUFFER_HELPER might not be correctly aligned
  52. //
  53. // still unsure about this but seeing how the whole property thing is
  54. // 32b. aligned and this structure is used copiously for casting (at DWORD
  55. // boundaries), the potential exists to have a pointer that is not QUADWORD
  56. // aligned. When we go to deref it, we get an alignment fault.
  57. //
  58. //
  59. // Static function prototypes.
  60. //
  61. static
  62. DWORD
  63. WINAPI
  64. ClRtlpSetDwordProperty(
  65. IN HANDLE hXsaction,
  66. IN PVOID hkey,
  67. IN const PCLUSTER_REG_APIS pClusterRegApis,
  68. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  69. IN const CRegistryValueName & rrvnModifiedNames,
  70. IN PCLUSPROP_DWORD pInDwordValue,
  71. IN BOOL bForceWrite,
  72. IN OUT OPTIONAL LPBYTE pOutParams
  73. );
  74. static
  75. DWORD
  76. WINAPI
  77. ClRtlpSetLongProperty(
  78. IN HANDLE hXsaction,
  79. IN PVOID hkey,
  80. IN const PCLUSTER_REG_APIS pClusterRegApis,
  81. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  82. IN const CRegistryValueName & rrvnModifiedNames,
  83. IN PCLUSPROP_LONG pInLongValue,
  84. IN BOOL bForceWrite,
  85. IN OUT OPTIONAL LPBYTE pOutParams
  86. );
  87. static
  88. DWORD
  89. WINAPI
  90. ClRtlpSetULargeIntegerProperty(
  91. IN HANDLE hXsaction,
  92. IN PVOID hkey,
  93. IN const PCLUSTER_REG_APIS pClusterRegApis,
  94. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  95. IN const CRegistryValueName & rrvnModifiedNames,
  96. IN PCLUSPROP_ULARGE_INTEGER pInULargeIntegerValue,
  97. IN BOOL bForceWrite,
  98. IN OUT OPTIONAL LPBYTE pOutParams
  99. );
  100. static
  101. DWORD
  102. WINAPI
  103. ClRtlpSetLargeIntegerProperty(
  104. IN HANDLE hXsaction,
  105. IN PVOID hkey,
  106. IN const PCLUSTER_REG_APIS pClusterRegApis,
  107. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  108. IN const CRegistryValueName & rrvnModifiedNames,
  109. IN PCLUSPROP_LARGE_INTEGER pInLargeIntegerValue,
  110. IN BOOL bForceWrite,
  111. IN OUT OPTIONAL LPBYTE pOutParams
  112. );
  113. static
  114. DWORD
  115. WINAPI
  116. ClRtlpSetStringProperty(
  117. IN HANDLE hXsaction,
  118. IN PVOID hkey,
  119. IN const PCLUSTER_REG_APIS pClusterRegApis,
  120. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  121. IN const CRegistryValueName & rrvnModifiedNames,
  122. IN PCLUSPROP_SZ pInStringValue,
  123. IN BOOL bForceWrite,
  124. IN OUT OPTIONAL LPBYTE pOutParams
  125. );
  126. static
  127. DWORD
  128. WINAPI
  129. ClRtlpSetMultiStringProperty(
  130. IN HANDLE hXsaction,
  131. IN PVOID hkey,
  132. IN const PCLUSTER_REG_APIS pClusterRegApis,
  133. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  134. IN const CRegistryValueName & rrvnModifiedNames,
  135. IN PCLUSPROP_MULTI_SZ pInMultiStringValue,
  136. IN BOOL bForceWrite,
  137. IN OUT OPTIONAL LPBYTE pOutParams
  138. );
  139. static
  140. DWORD
  141. WINAPI
  142. ClRtlpSetBinaryProperty(
  143. IN HANDLE hXsaction,
  144. IN PVOID hkey,
  145. IN const PCLUSTER_REG_APIS pClusterRegApis,
  146. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  147. IN const CRegistryValueName & rrvnModifiedNames,
  148. IN PCLUSPROP_BINARY pInBinaryValue,
  149. IN BOOL bForceWrite,
  150. IN OUT OPTIONAL LPBYTE pOutParams
  151. );
  152. DWORD
  153. WINAPI
  154. ClRtlEnumProperties(
  155. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  156. OUT LPWSTR pszOutProperties,
  157. IN DWORD cbOutPropertiesSize,
  158. OUT LPDWORD pcbBytesReturned,
  159. OUT LPDWORD pcbRequired
  160. )
  161. /*++
  162. Routine Description:
  163. Enumerates the properties for a given object.
  164. Arguments:
  165. pPropertyTable - Pointer to the property table to process.
  166. pszOutProperties - Supplies the output buffer.
  167. cbOutPropertiesSize - Supplies the size of the output buffer.
  168. pcbBytesReturned - The number of bytes returned in pszOutProperties.
  169. pcbRequired - The required number of bytes if pszOutProperties is too small.
  170. Return Value:
  171. ERROR_SUCCESS - Operation was successful.
  172. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  173. A Win32 error code on failure.
  174. --*/
  175. {
  176. DWORD status = ERROR_SUCCESS;
  177. DWORD totalBufferLength = 0;
  178. PRESUTIL_PROPERTY_ITEM property;
  179. LPWSTR psz = pszOutProperties;
  180. *pcbBytesReturned = 0;
  181. *pcbRequired = 0;
  182. if ( pPropertyTable == NULL ) {
  183. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlEnumProperties: pPropertyTable == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  184. return(ERROR_BAD_ARGUMENTS);
  185. }
  186. //
  187. // Clear the output buffer
  188. //
  189. if ( pszOutProperties != NULL ) {
  190. ZeroMemory( pszOutProperties, cbOutPropertiesSize );
  191. }
  192. //
  193. // Get the size of all property names for this object.
  194. //
  195. for ( property = pPropertyTable ; property->Name != NULL ; property++ ) {
  196. totalBufferLength += (lstrlenW( property->Name ) + 1) * sizeof(WCHAR);
  197. }
  198. totalBufferLength += sizeof(UNICODE_NULL);
  199. //
  200. // If the output buffer is big enough, copy the property names.
  201. //
  202. if ( totalBufferLength > cbOutPropertiesSize ) {
  203. *pcbRequired = totalBufferLength;
  204. totalBufferLength = 0;
  205. if ( pszOutProperties == NULL ) {
  206. status = ERROR_SUCCESS;
  207. } else {
  208. status = ERROR_MORE_DATA;
  209. }
  210. } else {
  211. DWORD cchCurrentNameSize;
  212. for ( property = pPropertyTable ; property->Name != NULL ; property++ ) {
  213. lstrcpyW( psz, property->Name );
  214. cchCurrentNameSize = lstrlenW( psz ) + 1;
  215. *pcbBytesReturned += cchCurrentNameSize * sizeof(WCHAR);
  216. psz += cchCurrentNameSize;
  217. }
  218. *psz = L'\0';
  219. *pcbBytesReturned += sizeof(WCHAR);
  220. }
  221. return(status);
  222. } // ClRtlEnumProperties
  223. DWORD
  224. WINAPI
  225. ClRtlEnumPrivateProperties(
  226. IN PVOID hkeyClusterKey,
  227. IN const PCLUSTER_REG_APIS pClusterRegApis,
  228. OUT LPWSTR pszOutProperties,
  229. IN DWORD cbOutPropertiesSize,
  230. OUT LPDWORD pcbBytesReturned,
  231. OUT LPDWORD pcbRequired
  232. )
  233. /*++
  234. Routine Description:
  235. Enumerates the properties for a given object.
  236. Arguments:
  237. hkeyClusterKey - Supplies the handle to the key in the cluster database
  238. to read from.
  239. pClusterRegApis - Supplies a structure of function pointers for accessing
  240. the cluster database.
  241. pszOutProperties - Supplies the output buffer.
  242. cbOutPropertiesSize - Supplies the size of the output buffer.
  243. pcbBytesReturned - The number of bytes returned in pszOutProperties.
  244. pcbRequired - The required number of bytes if pszOutProperties is too small.
  245. Return Value:
  246. ERROR_SUCCESS - Operation was successful.
  247. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  248. A Win32 error code on failure.
  249. --*/
  250. {
  251. DWORD status = ERROR_SUCCESS;
  252. DWORD totalBufferLength = 0;
  253. LPWSTR psz = pszOutProperties;
  254. DWORD ival;
  255. DWORD currentNameLength = 20;
  256. DWORD nameLength;
  257. DWORD dataLength;
  258. DWORD type;
  259. LPWSTR pszName;
  260. *pcbBytesReturned = 0;
  261. *pcbRequired = 0;
  262. //
  263. // Validate inputs
  264. //
  265. if ( (hkeyClusterKey == NULL) ||
  266. (pClusterRegApis == NULL) ) {
  267. ClRtlDbgPrint( LOG_CRITICAL,
  268. "ClRtlEnumPrivateProperties: hkeyClusterKey or pClusterRegApis == NULL. "
  269. "Returning ERROR_BAD_ARGUMENTS\n" );
  270. return(ERROR_BAD_ARGUMENTS);
  271. }
  272. //
  273. // Clear the output buffer
  274. //
  275. if ( pszOutProperties != NULL ) {
  276. ZeroMemory( pszOutProperties, cbOutPropertiesSize );
  277. }
  278. //
  279. // Allocate a property name buffer.
  280. //
  281. pszName = static_cast< LPWSTR >( LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) ) );
  282. if ( pszName == NULL ) {
  283. return(ERROR_NOT_ENOUGH_MEMORY);
  284. }
  285. //
  286. // Enumerate all properties to find the total size.
  287. //
  288. ival = 0;
  289. while ( TRUE ) {
  290. //
  291. // Read the next property.
  292. //
  293. nameLength = currentNameLength;
  294. dataLength = 0;
  295. status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
  296. ival,
  297. pszName,
  298. &nameLength,
  299. &type,
  300. NULL,
  301. &dataLength );
  302. if ( status == ERROR_NO_MORE_ITEMS ) {
  303. status = ERROR_SUCCESS;
  304. break;
  305. } else if ( status == ERROR_MORE_DATA ) {
  306. CL_ASSERT( (nameLength+1) > currentNameLength );
  307. LocalFree( pszName );
  308. currentNameLength = nameLength + 1; // returned value doesn't include terminating NULL
  309. pszName = static_cast< LPWSTR >( LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) ) );
  310. if ( pszName == NULL ) {
  311. status = ERROR_NOT_ENOUGH_MEMORY;
  312. break;
  313. }
  314. continue; // retry
  315. } else if ( status != ERROR_SUCCESS ) {
  316. break;
  317. }
  318. totalBufferLength += (nameLength + 1) * sizeof(WCHAR);
  319. ++ival;
  320. }
  321. //
  322. // Continue only if the operations so far have been successful.
  323. //
  324. if ( status == ERROR_SUCCESS ) {
  325. if ( totalBufferLength != 0 ) {
  326. totalBufferLength += sizeof(UNICODE_NULL);
  327. }
  328. //
  329. // If the output buffer is big enough, copy the property names.
  330. //
  331. if ( totalBufferLength > cbOutPropertiesSize ) {
  332. *pcbRequired = totalBufferLength;
  333. totalBufferLength = 0;
  334. if ( (pszOutProperties == NULL) ||
  335. (cbOutPropertiesSize == 0) ) {
  336. status = ERROR_SUCCESS;
  337. } else {
  338. status = ERROR_MORE_DATA;
  339. }
  340. } else if ( totalBufferLength != 0 ) {
  341. //
  342. // Enumerate all properties for copying
  343. //
  344. for ( ival = 0; ; ival++ ) {
  345. //
  346. // Read the next property.
  347. //
  348. nameLength = currentNameLength;
  349. dataLength = 0;
  350. status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
  351. ival,
  352. pszName,
  353. &nameLength,
  354. &type,
  355. NULL,
  356. &dataLength );
  357. if ( status == ERROR_NO_MORE_ITEMS ) {
  358. status = ERROR_SUCCESS;
  359. break;
  360. } else if ( status == ERROR_MORE_DATA ) {
  361. CL_ASSERT( 0 ); // THIS SHOULDN'T HAPPEN
  362. } else if ( status != ERROR_SUCCESS ) {
  363. break;
  364. }
  365. //CL_ASSERT( (DWORD)lstrlenW( name ) == nameLength );
  366. lstrcpyW( psz, pszName );
  367. psz += nameLength + 1;
  368. *pcbBytesReturned += (nameLength + 1) * sizeof(WCHAR);
  369. }
  370. *psz = L'\0';
  371. *pcbBytesReturned += sizeof(WCHAR);
  372. }
  373. }
  374. LocalFree( pszName );
  375. return(status);
  376. } // ClRtlEnumPrivateProperties
  377. DWORD
  378. WINAPI
  379. ClRtlGetProperties(
  380. IN PVOID hkeyClusterKey,
  381. IN const PCLUSTER_REG_APIS pClusterRegApis,
  382. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  383. OUT PVOID pOutPropertyList,
  384. IN DWORD cbOutPropertyListSize,
  385. OUT LPDWORD pcbBytesReturned,
  386. OUT LPDWORD pcbRequired
  387. )
  388. /*++
  389. Routine Description:
  390. Gets the properties for a given object.
  391. Arguments:
  392. hkeyClusterKey - Supplies the handle to the key in the cluster database
  393. to read from.
  394. pClusterRegApis - Supplies a structure of function pointers for accessing
  395. the cluster database.
  396. pPropertyTable - Pointer to the property list to process.
  397. pOutPropertyList - Supplies the output buffer.
  398. cbOutPropertyListSize - Supplies the size of the output buffer.
  399. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  400. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  401. Return Value:
  402. ERROR_SUCCESS - Operation was successful.
  403. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  404. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  405. A Win32 error code on failure.
  406. --*/
  407. {
  408. DWORD status = ERROR_SUCCESS;
  409. DWORD itemCount = 0;
  410. DWORD totalBufferLength = 0;
  411. PVOID outBuffer = pOutPropertyList;
  412. DWORD bufferLength = cbOutPropertyListSize;
  413. PRESUTIL_PROPERTY_ITEM property;
  414. *pcbBytesReturned = 0;
  415. *pcbRequired = 0;
  416. if ( (hkeyClusterKey == NULL) ||
  417. (pClusterRegApis == NULL) ||
  418. (pPropertyTable == NULL) ) {
  419. ClRtlDbgPrint( LOG_CRITICAL,
  420. "ClRtlGetProperties: hkeyClusterKey, pClusterRegApis, or "
  421. "pPropertyTable == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  422. return(ERROR_BAD_ARGUMENTS);
  423. }
  424. //
  425. // Clear the output buffer
  426. //
  427. if ( pOutPropertyList != NULL ) {
  428. ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
  429. }
  430. //
  431. // Get the size of all properties for this object.
  432. //
  433. property = pPropertyTable;
  434. while ( property->Name != NULL ) {
  435. status = ClRtlGetPropertySize( hkeyClusterKey,
  436. pClusterRegApis,
  437. property,
  438. &totalBufferLength,
  439. &itemCount );
  440. if ( status != ERROR_SUCCESS ) {
  441. break;
  442. }
  443. property++;
  444. }
  445. //
  446. // Continue only if the operations so far have been successful.
  447. //
  448. if ( status == ERROR_SUCCESS ) {
  449. //
  450. // Count for item count at front of return data and endmark.
  451. //
  452. totalBufferLength += sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
  453. //
  454. // Verify the size of all the properties
  455. //
  456. if ( totalBufferLength > cbOutPropertyListSize ) {
  457. *pcbRequired = totalBufferLength;
  458. totalBufferLength = 0;
  459. if ( pOutPropertyList == NULL ) {
  460. status = ERROR_SUCCESS;
  461. } else {
  462. status = ERROR_MORE_DATA;
  463. }
  464. }
  465. else {
  466. *(LPDWORD)outBuffer = itemCount;
  467. outBuffer = (PVOID)( (PUCHAR)outBuffer + sizeof(itemCount) );
  468. bufferLength -= sizeof(itemCount);
  469. //
  470. // Now fetch all of the properties.
  471. //
  472. property = pPropertyTable;
  473. while ( property->Name != NULL ) {
  474. status = ClRtlGetProperty( hkeyClusterKey,
  475. pClusterRegApis,
  476. property,
  477. &outBuffer,
  478. &bufferLength );
  479. if ( status != ERROR_SUCCESS ) {
  480. break;
  481. }
  482. property++;
  483. }
  484. // Don't forget the ENDMARK
  485. *(LPDWORD)outBuffer = CLUSPROP_SYNTAX_ENDMARK;
  486. if ( (status != ERROR_SUCCESS) &&
  487. (status != ERROR_MORE_DATA) ) {
  488. totalBufferLength = 0;
  489. }
  490. }
  491. *pcbBytesReturned = totalBufferLength;
  492. }
  493. return(status);
  494. } // ClRtlGetProperties
  495. DWORD
  496. WINAPI
  497. ClRtlGetAllProperties(
  498. IN PVOID hkeyClusterKey,
  499. IN const PCLUSTER_REG_APIS pClusterRegApis,
  500. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  501. OUT PVOID pOutPropertyList,
  502. IN DWORD cbOutPropertyListSize,
  503. OUT LPDWORD pcbReturned,
  504. OUT LPDWORD pcbRequired
  505. )
  506. /*++
  507. Routine Description:
  508. Gets the default and 'unknown' properties for a given object.
  509. Arguments:
  510. hkeyClusterKey - Supplies the handle to the key in the cluster database
  511. to read from.
  512. pClusterRegApis - Supplies a structure of function pointers for accessing
  513. the cluster database.
  514. pPropertyTable - Pointer to the property table to process.
  515. pOutPropertyList - Supplies the output buffer.
  516. cbOutPropertyListSize - Supplies the size of the output buffer.
  517. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  518. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  519. Return Value:
  520. ERROR_SUCCESS - Operation was successful.
  521. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  522. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  523. A Win32 error code on failure.
  524. --*/
  525. {
  526. CLUSPROP_BUFFER_HELPER cbhKnownPropBuffer;
  527. CLUSPROP_BUFFER_HELPER cbhUnknownPropBuffer;
  528. DWORD cbKnownPropBufferSize;
  529. DWORD cbUnknownPropBufferSize;
  530. DWORD sc = ERROR_SUCCESS;
  531. DWORD scUnknown;
  532. DWORD dwSavedData;
  533. DWORD cbUnknownRequired = 0;
  534. DWORD cbUnknownReturned = 0;
  535. cbhKnownPropBuffer.pb = static_cast< LPBYTE >( pOutPropertyList );
  536. cbKnownPropBufferSize = cbOutPropertyListSize;
  537. //
  538. // First get the 'known' properties.
  539. //
  540. sc = ClRtlGetProperties(
  541. hkeyClusterKey,
  542. pClusterRegApis,
  543. pPropertyTable,
  544. cbhKnownPropBuffer.pb,
  545. cbKnownPropBufferSize,
  546. pcbReturned,
  547. pcbRequired
  548. );
  549. if ( sc != ERROR_SUCCESS )
  550. {
  551. *pcbReturned = 0;
  552. if ( sc != ERROR_MORE_DATA )
  553. {
  554. *pcbRequired = 0;
  555. return sc;
  556. }
  557. // We already know that there is insufficient space.
  558. scUnknown = ClRtlGetUnknownProperties(
  559. hkeyClusterKey,
  560. pClusterRegApis,
  561. pPropertyTable,
  562. NULL,
  563. 0,
  564. &cbUnknownReturned,
  565. &cbUnknownRequired
  566. );
  567. if ( ( scUnknown != ERROR_SUCCESS ) &&
  568. ( scUnknown != ERROR_MORE_DATA ) )
  569. {
  570. *pcbRequired = 0;
  571. return scUnknown;
  572. }
  573. //
  574. // If both known and unknown properties exist, only one endmark
  575. // is required. So, subtract endmark size from total required size.
  576. //
  577. if ( ( *pcbRequired > sizeof(DWORD) ) &&
  578. ( cbUnknownRequired > sizeof(DWORD) ) )
  579. {
  580. *pcbRequired -= sizeof(CLUSPROP_SYNTAX);
  581. }
  582. //
  583. // Subtract off the size of the property count for the
  584. // unknown property list.
  585. //
  586. *pcbRequired += cbUnknownRequired - sizeof(DWORD);
  587. return sc;
  588. } // if: call to ClRtlGetProperties failed
  589. // If we are here then the call to ClRtlGetProperties succeeded.
  590. //
  591. // Calculate the position in the output buffer where unknown properties
  592. // should be stored. Subtract off the size of the property count for
  593. // the unknown property list. These calculations will cause the buffer
  594. // pointer to overlap the known property list buffer by one DWORD.
  595. //
  596. cbhUnknownPropBuffer.pb = cbhKnownPropBuffer.pb + *pcbReturned - sizeof(DWORD);
  597. cbUnknownPropBufferSize = cbKnownPropBufferSize - *pcbReturned + sizeof(DWORD);
  598. // If there are known properties, move the unknown property list
  599. // buffer pointer to overlap that as well.
  600. if ( *pcbReturned > sizeof(DWORD) )
  601. {
  602. cbhUnknownPropBuffer.pb -= sizeof(CLUSPROP_SYNTAX);
  603. cbUnknownPropBufferSize += sizeof(CLUSPROP_SYNTAX);
  604. } // if: a nonzero number of properties has been returned.
  605. //
  606. // Save the DWORD we are about to overlap.
  607. //
  608. dwSavedData = *(cbhUnknownPropBuffer.pdw);
  609. scUnknown = ClRtlGetUnknownProperties(
  610. hkeyClusterKey,
  611. pClusterRegApis,
  612. pPropertyTable,
  613. cbhUnknownPropBuffer.pb,
  614. cbUnknownPropBufferSize,
  615. &cbUnknownReturned,
  616. &cbUnknownRequired
  617. );
  618. if ( scUnknown == ERROR_SUCCESS )
  619. {
  620. //
  621. // The order of the next three statements is very important
  622. // since the known and the unknown property buffers can overlap.
  623. //
  624. DWORD nUnknownPropCount = cbhUnknownPropBuffer.pList->nPropertyCount;
  625. *(cbhUnknownPropBuffer.pdw) = dwSavedData;
  626. cbhKnownPropBuffer.pList->nPropertyCount += nUnknownPropCount;
  627. //
  628. // If both known and unknown properties exist, only one endmark
  629. // is required. So, subtract endmark size from total returned size.
  630. //
  631. if ( ( *pcbReturned > sizeof(DWORD) ) &&
  632. ( cbUnknownReturned > sizeof(DWORD) ) )
  633. {
  634. *pcbReturned -= sizeof(CLUSPROP_SYNTAX);
  635. }
  636. //
  637. // Add in the size of the unknown property list minus the
  638. // size of the unknown property list property count.
  639. //
  640. *pcbReturned += cbUnknownReturned - sizeof(DWORD);
  641. *pcbRequired = 0;
  642. } // if: call to ClRtlGetUnknownProperties succeeded
  643. else
  644. {
  645. if ( scUnknown == ERROR_MORE_DATA )
  646. {
  647. *pcbRequired = *pcbReturned;
  648. *pcbReturned = 0;
  649. //
  650. // Both known and unknown properties exist. Only one endmark
  651. // is required. So, subtract endmark size from total required size.
  652. //
  653. if ( ( *pcbRequired > sizeof(DWORD) ) &&
  654. ( cbUnknownRequired > sizeof(DWORD) ) )
  655. {
  656. *pcbRequired -= sizeof(CLUSPROP_SYNTAX);
  657. }
  658. //
  659. // Add in the size of the unknown property list minus the
  660. // size of the unknown property list property count.
  661. //
  662. *pcbRequired += cbUnknownRequired - sizeof(DWORD);
  663. } // if: ClRtlGetUnknownProperties returned ERROR_MORE_DATA
  664. else
  665. {
  666. *pcbRequired = 0;
  667. *pcbReturned = 0;
  668. } // else: ClRtlGetUnknownProperties failed for some unknown reason.
  669. } // else: Call to ClRtlGetUnknownProperties failed.
  670. return scUnknown;
  671. } //*** ClRtlGetAllProperties()
  672. DWORD
  673. WINAPI
  674. ClRtlGetPropertiesToParameterBlock(
  675. IN HKEY hkeyClusterKey,
  676. IN const PCLUSTER_REG_APIS pClusterRegApis,
  677. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  678. IN OUT LPBYTE pOutParams,
  679. IN BOOL bCheckForRequiredProperties,
  680. OUT OPTIONAL LPWSTR * pszNameOfPropInError
  681. )
  682. /*++
  683. Routine Description:
  684. Read properties based on a property table.
  685. Arguments:
  686. hkeyClusterKey - Supplies the cluster key where the properties are stored.
  687. pClusterRegApis - Supplies a structure of function pointers for accessing
  688. the cluster database.
  689. pPropertyTable - Pointer to the property table to process.
  690. pOutParams - Parameter block to read into.
  691. bCheckForRequiredProperties - Boolean value specifying whether missing
  692. required properties should cause an error.
  693. pszNameOfPropInError - String pointer in which to return the name of the
  694. property in error (optional).
  695. Return Value:
  696. ERROR_SUCCESS - Properties read successfully.
  697. ERROR_INVALID_DATA - Required property not present.
  698. ERROR_INVALID_PARAMETER -
  699. A Win32 error code on failure.
  700. --*/
  701. {
  702. PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
  703. HKEY key;
  704. DWORD status = ERROR_SUCCESS;
  705. DWORD valueType;
  706. DWORD valueSize;
  707. LPWSTR pszInValue;
  708. LPBYTE pbInValue;
  709. DWORD dwInValue;
  710. LPWSTR UNALIGNED * ppszOutValue;
  711. LPBYTE UNALIGNED * ppbOutValue;
  712. DWORD * pdwOutValue;
  713. LONG * plOutValue;
  714. ULARGE_INTEGER * pullOutValue;
  715. LARGE_INTEGER * pllOutValue;
  716. CRegistryValueName rvn;
  717. if ( pszNameOfPropInError != NULL ) {
  718. *pszNameOfPropInError = NULL;
  719. }
  720. if ( (hkeyClusterKey == NULL) ||
  721. (pPropertyTable == NULL) ||
  722. (pOutParams == NULL) ||
  723. (pClusterRegApis == NULL) ||
  724. (pClusterRegApis->pfnOpenKey == NULL) ||
  725. (pClusterRegApis->pfnCloseKey == NULL) ||
  726. (pClusterRegApis->pfnQueryValue == NULL) ) {
  727. ClRtlDbgPrint( LOG_CRITICAL,
  728. "ClRtlGetPropertiesToParameterBlock: hkeyClusterKey, pPropertyTable, "
  729. "pOutParams, pClusterRegApis, or required pfns == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  730. return(ERROR_BAD_ARGUMENTS);
  731. }
  732. while ( propertyItem->Name != NULL ) {
  733. //
  734. // Use the wrapper class CRegistryValueName to parse value name to see if it
  735. // contains a backslash.
  736. //
  737. status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
  738. if ( status != ERROR_SUCCESS ) {
  739. break;
  740. }
  741. //
  742. // If the value resides at a different location, open the key.
  743. //
  744. if ( rvn.PszKeyName() != NULL ) {
  745. DWORD disposition;
  746. status = (*pClusterRegApis->pfnOpenKey)(
  747. hkeyClusterKey,
  748. rvn.PszKeyName(),
  749. KEY_ALL_ACCESS,
  750. (void **) &key
  751. );
  752. // If key could not be opened, then we may need to put the default value
  753. // for the property item.
  754. if ( status != ERROR_SUCCESS ) {
  755. status = ERROR_FILE_NOT_FOUND;
  756. }
  757. } else {
  758. key = hkeyClusterKey;
  759. }
  760. switch ( propertyItem->Format ) {
  761. case CLUSPROP_FORMAT_DWORD:
  762. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
  763. valueSize = sizeof(DWORD);
  764. // If OpenKey has succeeded.
  765. if ( status == ERROR_SUCCESS ) {
  766. status = (*pClusterRegApis->pfnQueryValue)( key,
  767. rvn.PszName(),
  768. &valueType,
  769. (LPBYTE) pdwOutValue,
  770. &valueSize );
  771. }
  772. if ( status == ERROR_SUCCESS ) {
  773. if ( valueType != REG_DWORD ) {
  774. ClRtlDbgPrint( LOG_CRITICAL,
  775. "ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
  776. "expected to be REG_DWORD (%2!d!), was %3!d!.\n",
  777. propertyItem->Name, REG_DWORD, valueType );
  778. status = ERROR_INVALID_PARAMETER;
  779. }
  780. } else if ( (status == ERROR_FILE_NOT_FOUND) &&
  781. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  782. ! bCheckForRequiredProperties) ) {
  783. *pdwOutValue = propertyItem->Default;
  784. status = ERROR_SUCCESS;
  785. }
  786. break;
  787. case CLUSPROP_FORMAT_LONG:
  788. plOutValue = (LONG *) &pOutParams[propertyItem->Offset];
  789. valueSize = sizeof(LONG);
  790. // If OpenKey has succeeded.
  791. if ( status == ERROR_SUCCESS ) {
  792. status = (*pClusterRegApis->pfnQueryValue)( key,
  793. rvn.PszName(),
  794. &valueType,
  795. (LPBYTE) plOutValue,
  796. &valueSize );
  797. }
  798. if ( status == ERROR_SUCCESS ) {
  799. if ( valueType != REG_DWORD ) {
  800. ClRtlDbgPrint( LOG_CRITICAL,
  801. "ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
  802. "expected to be REG_DWORD (%2!d!), was %3!d!.\n",
  803. propertyItem->Name, REG_DWORD, valueType );
  804. status = ERROR_INVALID_PARAMETER;
  805. }
  806. } else if ( (status == ERROR_FILE_NOT_FOUND) &&
  807. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  808. !bCheckForRequiredProperties) ) {
  809. *plOutValue = propertyItem->Default;
  810. status = ERROR_SUCCESS;
  811. }
  812. break;
  813. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  814. pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
  815. valueSize = sizeof(ULARGE_INTEGER);
  816. // If OpenKey has succeeded.
  817. if ( status == ERROR_SUCCESS ) {
  818. status = (*pClusterRegApis->pfnQueryValue)( key,
  819. rvn.PszName(),
  820. &valueType,
  821. (LPBYTE) pullOutValue,
  822. &valueSize );
  823. }
  824. if ( status == ERROR_SUCCESS ) {
  825. if ( valueType != REG_QWORD ) {
  826. ClRtlDbgPrint( LOG_CRITICAL,
  827. "ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
  828. "expected to be REG_QWORD (%2!d!), was %3!d!.\n",
  829. propertyItem->Name, REG_QWORD, valueType );
  830. status = ERROR_INVALID_PARAMETER;
  831. }
  832. } else if ( (status == ERROR_FILE_NOT_FOUND) &&
  833. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  834. ! bCheckForRequiredProperties) ) {
  835. pullOutValue->u = propertyItem->ULargeIntData->Default.u;
  836. status = ERROR_SUCCESS;
  837. }
  838. break;
  839. case CLUSPROP_FORMAT_LARGE_INTEGER:
  840. pllOutValue = (LARGE_INTEGER *) &pOutParams[propertyItem->Offset];
  841. valueSize = sizeof(LARGE_INTEGER);
  842. // If OpenKey has succeeded.
  843. if ( status == ERROR_SUCCESS ) {
  844. status = (*pClusterRegApis->pfnQueryValue)( key,
  845. rvn.PszName(),
  846. &valueType,
  847. (LPBYTE) pllOutValue,
  848. &valueSize );
  849. }
  850. if ( status == ERROR_SUCCESS ) {
  851. if ( valueType != REG_QWORD ) {
  852. ClRtlDbgPrint( LOG_CRITICAL,
  853. "ClRtlGetPropertiesToParameterBlock: Property '%1!ls!' "
  854. "expected to be REG_QWORD (%2!d!), was %3!d!.\n",
  855. propertyItem->Name, REG_QWORD, valueType );
  856. status = ERROR_INVALID_PARAMETER;
  857. }
  858. } else if ( (status == ERROR_FILE_NOT_FOUND) &&
  859. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  860. ! bCheckForRequiredProperties) )
  861. {
  862. pllOutValue->u = propertyItem->LargeIntData->Default.u;
  863. status = ERROR_SUCCESS;
  864. }
  865. break;
  866. case CLUSPROP_FORMAT_SZ:
  867. case CLUSPROP_FORMAT_EXPAND_SZ:
  868. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  869. // If OpenKey has succeeded.
  870. if ( status == ERROR_SUCCESS ) {
  871. pszInValue = ClRtlGetSzValue( key,
  872. rvn.PszName(),
  873. pClusterRegApis );
  874. }
  875. else {
  876. pszInValue = NULL;
  877. SetLastError(status);
  878. }
  879. if ( pszInValue == NULL ) {
  880. status = GetLastError();
  881. if ( (status == ERROR_FILE_NOT_FOUND) &&
  882. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  883. ! bCheckForRequiredProperties) ) {
  884. status = ERROR_SUCCESS;
  885. // Deallocate old value.
  886. if ( *ppszOutValue != NULL ) {
  887. LocalFree( *ppszOutValue );
  888. *ppszOutValue = NULL;
  889. }
  890. // If a default is specified, copy it.
  891. if ( propertyItem->lpDefault != NULL ) {
  892. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( (LPCWSTR) propertyItem->lpDefault ) + 1) * sizeof(WCHAR) );
  893. if ( *ppszOutValue == NULL ) {
  894. status = GetLastError();
  895. } else {
  896. lstrcpyW( *ppszOutValue, (LPCWSTR) propertyItem->lpDefault );
  897. }
  898. }
  899. }
  900. } else {
  901. if ( *ppszOutValue != NULL ) {
  902. LocalFree( *ppszOutValue );
  903. }
  904. *ppszOutValue = pszInValue;
  905. }
  906. break;
  907. case CLUSPROP_FORMAT_MULTI_SZ:
  908. case CLUSPROP_FORMAT_BINARY:
  909. ppbOutValue = (LPBYTE UNALIGNED *) &pOutParams[propertyItem->Offset];
  910. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(LPBYTE*)];
  911. // If OpenKey has succeeded.
  912. if ( status == ERROR_SUCCESS ) {
  913. status = ClRtlGetBinaryValue( key,
  914. rvn.PszName(),
  915. &pbInValue,
  916. &dwInValue,
  917. pClusterRegApis );
  918. }
  919. if ( status == ERROR_SUCCESS ) {
  920. if ( *ppbOutValue != NULL ) {
  921. LocalFree( *ppbOutValue );
  922. }
  923. *ppbOutValue = pbInValue;
  924. *pdwOutValue = dwInValue;
  925. } else if ( (status == ERROR_FILE_NOT_FOUND) &&
  926. (!(propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED) ||
  927. ! bCheckForRequiredProperties) ) {
  928. status = ERROR_SUCCESS;
  929. // Deallocate old value.
  930. if ( *ppbOutValue != NULL ) {
  931. LocalFree( *ppbOutValue );
  932. *ppbOutValue = NULL;
  933. }
  934. *pdwOutValue = 0;
  935. // If a default is specified, copy it.
  936. if ( propertyItem->lpDefault != NULL ) {
  937. *ppbOutValue = (LPBYTE) LocalAlloc( LMEM_FIXED, propertyItem->Minimum );
  938. if ( *ppbOutValue == NULL ) {
  939. status = GetLastError();
  940. } else {
  941. CopyMemory( *ppbOutValue, (const PVOID) propertyItem->lpDefault, propertyItem->Minimum );
  942. *pdwOutValue = propertyItem->Minimum;
  943. }
  944. }
  945. }
  946. break;
  947. }
  948. //
  949. // Close the key if we opened it.
  950. //
  951. if ( (rvn.PszKeyName() != NULL) &&
  952. (key != NULL) ) {
  953. (*pClusterRegApis->pfnCloseKey)( key );
  954. }
  955. //
  956. // Handle any errors that occurred.
  957. //
  958. if ( status != ERROR_SUCCESS ) {
  959. if ( pszNameOfPropInError != NULL ) {
  960. *pszNameOfPropInError = propertyItem->Name;
  961. }
  962. if ( propertyItem->Flags & RESUTIL_PROPITEM_REQUIRED ) {
  963. if ( status == ERROR_FILE_NOT_FOUND ) {
  964. status = ERROR_INVALID_DATA;
  965. }
  966. break;
  967. } else {
  968. status = ERROR_SUCCESS;
  969. }
  970. }
  971. //
  972. // Advance to the next property.
  973. //
  974. propertyItem++;
  975. }
  976. return(status);
  977. } // ClRtlGetPropertiesToParameterBlock
  978. DWORD
  979. WINAPI
  980. ClRtlPropertyListFromParameterBlock(
  981. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  982. OUT PVOID pOutPropertyList,
  983. IN OUT LPDWORD pcbOutPropertyListSize,
  984. IN const LPBYTE pInParams,
  985. OUT LPDWORD pcbBytesReturned,
  986. OUT LPDWORD pcbRequired
  987. )
  988. /*++
  989. Routine Description:
  990. Constructs a property list from a parameter block.
  991. Arguments:
  992. pPropertyTable - Pointer to the property table to process.
  993. pOutPropertyList - Supplies the output buffer.
  994. pcbOutPropertyListSize - Supplies the size of the output buffer.
  995. pInParams - Supplies the input parameter block.
  996. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  997. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  998. Return Value:
  999. ERROR_SUCCESS - Operation was successful.
  1000. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  1001. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  1002. ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
  1003. A Win32 error code on failure.
  1004. --*/
  1005. {
  1006. DWORD status = ERROR_SUCCESS;
  1007. DWORD bytesReturned;
  1008. DWORD required;
  1009. DWORD nameSize;
  1010. DWORD dataSize;
  1011. DWORD bufferIncrement;
  1012. DWORD totalBufferSize = 0;
  1013. LPDWORD ptrItemCount;
  1014. WORD propertyFormat;
  1015. BOOL copying = TRUE;
  1016. PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
  1017. CLUSPROP_BUFFER_HELPER props;
  1018. LPWSTR UNALIGNED * ppszValue;
  1019. PBYTE UNALIGNED * ppbValue;
  1020. DWORD * pdwValue;
  1021. ULARGE_INTEGER * pullValue;
  1022. LPWSTR pszUnexpanded;
  1023. LPWSTR pszExpanded = NULL;
  1024. *pcbBytesReturned = 0;
  1025. *pcbRequired = 0;
  1026. if ( (pPropertyTable == NULL) ||
  1027. (pInParams == NULL) ||
  1028. (pcbOutPropertyListSize == NULL) ) {
  1029. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlPropertyListFromParameterBlock: pPropertyTable, pInParams, or pcbOutPropertyListSize == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  1030. return(ERROR_BAD_ARGUMENTS);
  1031. }
  1032. //
  1033. // Clear the output buffer.
  1034. //
  1035. if ( pOutPropertyList != NULL ) {
  1036. ZeroMemory( pOutPropertyList, *pcbOutPropertyListSize );
  1037. } else {
  1038. copying = FALSE;
  1039. }
  1040. //
  1041. // Need a DWORD of item count.
  1042. //
  1043. props.pb = (LPBYTE) pOutPropertyList;
  1044. ptrItemCount = props.pdw++;
  1045. totalBufferSize += sizeof(DWORD);
  1046. if ( totalBufferSize > *pcbOutPropertyListSize ) {
  1047. copying = FALSE;
  1048. }
  1049. while ( propertyItem->Name != NULL ) {
  1050. //
  1051. // Copy the property name.
  1052. //
  1053. nameSize = (lstrlenW( propertyItem->Name ) + 1) * sizeof(WCHAR);
  1054. bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME) + ALIGN_CLUSPROP( nameSize );
  1055. totalBufferSize += bufferIncrement;
  1056. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1057. props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  1058. props.pName->cbLength = nameSize;
  1059. lstrcpyW( props.pName->sz, propertyItem->Name );
  1060. props.pb += bufferIncrement;
  1061. } else {
  1062. copying = FALSE;
  1063. }
  1064. //
  1065. // Copy the property value.
  1066. //
  1067. propertyFormat = (WORD) propertyItem->Format;
  1068. switch ( propertyItem->Format ) {
  1069. case CLUSPROP_FORMAT_DWORD:
  1070. case CLUSPROP_FORMAT_LONG:
  1071. pdwValue = (DWORD *) &pInParams[propertyItem->Offset];
  1072. bufferIncrement = sizeof(CLUSPROP_DWORD);
  1073. totalBufferSize += bufferIncrement;
  1074. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1075. props.pSyntax->wFormat = propertyFormat;
  1076. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1077. props.pDwordValue->cbLength = sizeof(DWORD);
  1078. props.pDwordValue->dw = *pdwValue;
  1079. props.pb += bufferIncrement;
  1080. } else {
  1081. copying = FALSE;
  1082. }
  1083. break;
  1084. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  1085. case CLUSPROP_FORMAT_LARGE_INTEGER:
  1086. pullValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
  1087. bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
  1088. totalBufferSize += bufferIncrement;
  1089. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1090. props.pSyntax->wFormat = propertyFormat;
  1091. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1092. props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
  1093. props.pULargeIntegerValue->li.u = pullValue->u;
  1094. props.pb += bufferIncrement;
  1095. } else {
  1096. copying = FALSE;
  1097. }
  1098. break;
  1099. case CLUSPROP_FORMAT_SZ:
  1100. case CLUSPROP_FORMAT_EXPAND_SZ:
  1101. ppszValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  1102. pszUnexpanded = *ppszValue;
  1103. if ( *ppszValue != NULL ) {
  1104. dataSize = (lstrlenW( *ppszValue ) + 1) * sizeof(WCHAR);
  1105. } else {
  1106. dataSize = sizeof(WCHAR);
  1107. }
  1108. bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( dataSize );
  1109. totalBufferSize += bufferIncrement;
  1110. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1111. props.pSyntax->wFormat = propertyFormat;
  1112. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1113. props.pStringValue->cbLength = dataSize;
  1114. if ( *ppszValue != NULL ) {
  1115. lstrcpyW( props.pStringValue->sz, *ppszValue );
  1116. } else {
  1117. props.pStringValue->sz[0] = L'\0';
  1118. }
  1119. props.pb += bufferIncrement;
  1120. } else {
  1121. copying = FALSE;
  1122. }
  1123. //
  1124. // See if there is a different expanded string and, if so,
  1125. // return it as an additional value in the value list.
  1126. //
  1127. if ( pszUnexpanded != NULL ) {
  1128. pszExpanded = ClRtlExpandEnvironmentStrings( pszUnexpanded );
  1129. if ( pszExpanded == NULL ) {
  1130. status = GetLastError();
  1131. break;
  1132. }
  1133. if ( lstrcmpW( pszExpanded, pszUnexpanded ) != 0 ) {
  1134. dataSize = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
  1135. bufferIncrement = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataSize );
  1136. totalBufferSize += bufferIncrement;
  1137. if ( totalBufferSize <= *pcbOutPropertyListSize ) {
  1138. props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
  1139. props.pStringValue->cbLength = dataSize;
  1140. lstrcpyW( props.pStringValue->sz, pszExpanded );
  1141. props.pb += bufferIncrement;
  1142. } else {
  1143. copying = FALSE;
  1144. }
  1145. }
  1146. LocalFree( pszExpanded );
  1147. pszExpanded = NULL;
  1148. }
  1149. break;
  1150. case CLUSPROP_FORMAT_MULTI_SZ:
  1151. ppszValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  1152. pdwValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
  1153. if ( *ppszValue != NULL ) {
  1154. bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( *pdwValue );
  1155. } else {
  1156. bufferIncrement = sizeof(CLUSPROP_SZ) + ALIGN_CLUSPROP( sizeof(WCHAR) );
  1157. }
  1158. totalBufferSize += bufferIncrement;
  1159. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1160. props.pSyntax->wFormat = propertyFormat;
  1161. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1162. if ( *ppszValue != NULL ) {
  1163. props.pStringValue->cbLength = *pdwValue;
  1164. CopyMemory( props.pStringValue->sz, *ppszValue, *pdwValue );
  1165. } else {
  1166. props.pStringValue->cbLength = sizeof(WCHAR);
  1167. props.pStringValue->sz[0] = L'\0';
  1168. }
  1169. props.pb += bufferIncrement;
  1170. } else {
  1171. copying = FALSE;
  1172. }
  1173. break;
  1174. case CLUSPROP_FORMAT_BINARY:
  1175. ppbValue = (PBYTE UNALIGNED *) &pInParams[propertyItem->Offset];
  1176. pdwValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(PBYTE*)];
  1177. if ( *ppbValue != NULL ) {
  1178. bufferIncrement = sizeof(CLUSPROP_BINARY) + ALIGN_CLUSPROP( *pdwValue );
  1179. } else {
  1180. bufferIncrement = sizeof(CLUSPROP_BINARY);
  1181. }
  1182. totalBufferSize += bufferIncrement;
  1183. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1184. props.pSyntax->wFormat = propertyFormat;
  1185. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1186. if ( *ppbValue != NULL ) {
  1187. props.pBinaryValue->cbLength = *pdwValue;
  1188. CopyMemory( props.pBinaryValue->rgb, *ppbValue, *pdwValue );
  1189. } else {
  1190. props.pBinaryValue->cbLength = 0;
  1191. }
  1192. props.pb += bufferIncrement;
  1193. } else {
  1194. copying = FALSE;
  1195. }
  1196. break;
  1197. default:
  1198. break;
  1199. }
  1200. if ( status != ERROR_SUCCESS ) {
  1201. break;
  1202. }
  1203. //
  1204. // Add the value-closing endmark.
  1205. //
  1206. bufferIncrement = sizeof(CLUSPROP_SYNTAX);
  1207. totalBufferSize += bufferIncrement;
  1208. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1209. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1210. props.pb += bufferIncrement;
  1211. (*ptrItemCount)++;
  1212. } else {
  1213. copying = FALSE;
  1214. }
  1215. //
  1216. // Advance to the next property.
  1217. //
  1218. propertyItem++;
  1219. }
  1220. if ( status == ERROR_SUCCESS ) {
  1221. // Don't forget the ENDMARK.
  1222. totalBufferSize += sizeof(CLUSPROP_SYNTAX);
  1223. if ( copying && (totalBufferSize <= *pcbOutPropertyListSize) ) {
  1224. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1225. } else {
  1226. copying = FALSE;
  1227. }
  1228. //
  1229. // Return size of data.
  1230. //
  1231. if ( copying == FALSE ) {
  1232. *pcbRequired = totalBufferSize;
  1233. *pcbBytesReturned = 0;
  1234. status = ERROR_MORE_DATA;
  1235. } else {
  1236. *pcbRequired = 0;
  1237. *pcbBytesReturned = totalBufferSize;
  1238. status = ERROR_SUCCESS;
  1239. }
  1240. }
  1241. return(status);
  1242. } // ClRtlPropertyListFromParameterBlock
  1243. DWORD
  1244. WINAPI
  1245. ClRtlGetPrivateProperties(
  1246. IN PVOID hkeyClusterKey,
  1247. IN const PCLUSTER_REG_APIS pClusterRegApis,
  1248. OUT PVOID pOutPropertyList,
  1249. IN DWORD cbOutPropertyListSize,
  1250. OUT LPDWORD pcbBytesReturned,
  1251. OUT LPDWORD pcbRequired
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Gets the private properties for a given object.
  1256. Arguments:
  1257. hkeyClusterKey - Supplies the handle to the key in the cluster database
  1258. to read from.
  1259. pClusterRegApis - Supplies a structure of function pointers for accessing
  1260. the cluster database.
  1261. pOutPropertyList - Supplies the output buffer.
  1262. cbOutPropertyListSize - Supplies the size of the output buffer.
  1263. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  1264. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  1265. Return Value:
  1266. ERROR_SUCCESS - Operation was successful.
  1267. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  1268. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  1269. ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
  1270. A Win32 error code on failure.
  1271. --*/
  1272. {
  1273. DWORD status = ERROR_SUCCESS;
  1274. DWORD ival;
  1275. DWORD currentNameLength = 80;
  1276. DWORD currentDataLength = 80;
  1277. DWORD nameLength;
  1278. DWORD dataLength;
  1279. DWORD dataLengthExpanded;
  1280. DWORD type;
  1281. LPWSTR name;
  1282. PUCHAR data;
  1283. LPDWORD ptrItemCount;
  1284. DWORD itemCount = 0;
  1285. BOOL copying = TRUE;
  1286. DWORD totalBufferSize = 0;
  1287. DWORD bufferIncrement;
  1288. DWORD bufferIncrementExpanded;
  1289. CLUSPROP_BUFFER_HELPER props;
  1290. LPWSTR pszExpanded = NULL;
  1291. *pcbBytesReturned = 0;
  1292. *pcbRequired = 0;
  1293. if ( (hkeyClusterKey == NULL) ||
  1294. (pClusterRegApis->pfnEnumValue == NULL) ) {
  1295. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPrivateProperties: hkeyClusterKey or pClusterRegApis->pfnEnumValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  1296. return(ERROR_BAD_ARGUMENTS);
  1297. }
  1298. //
  1299. // Clear the output buffer
  1300. //
  1301. if ( pOutPropertyList != NULL ) {
  1302. ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
  1303. } else {
  1304. copying = FALSE;
  1305. }
  1306. //
  1307. // Need a DWORD of item count.
  1308. //
  1309. props.pb = (LPBYTE) pOutPropertyList;
  1310. ptrItemCount = props.pdw++;
  1311. totalBufferSize += sizeof(DWORD);
  1312. if ( totalBufferSize > cbOutPropertyListSize ) {
  1313. copying = FALSE;
  1314. }
  1315. //
  1316. // Allocate a property name buffer.
  1317. //
  1318. name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
  1319. if ( name == NULL ) {
  1320. return(ERROR_NOT_ENOUGH_MEMORY);
  1321. }
  1322. //
  1323. // Allocate a property value data buffer.
  1324. //
  1325. data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
  1326. if ( data == NULL ) {
  1327. LocalFree( name );
  1328. return(ERROR_NOT_ENOUGH_MEMORY);
  1329. }
  1330. //
  1331. // Enumerate all properties and return them!
  1332. //
  1333. for ( ival = 0; ; ival++ ) {
  1334. retry:
  1335. //
  1336. // Read the next property.
  1337. //
  1338. nameLength = currentNameLength;
  1339. dataLength = currentDataLength;
  1340. status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
  1341. ival,
  1342. name,
  1343. &nameLength,
  1344. &type,
  1345. data,
  1346. &dataLength );
  1347. if ( status == ERROR_MORE_DATA ) {
  1348. if ( (nameLength+1) > currentNameLength ) {
  1349. currentNameLength = nameLength+1;
  1350. LocalFree( name );
  1351. name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
  1352. if ( name == NULL ) {
  1353. status = ERROR_NOT_ENOUGH_MEMORY;
  1354. break;
  1355. }
  1356. }
  1357. if ( dataLength > currentDataLength ) {
  1358. currentDataLength = dataLength;
  1359. LocalFree( data );
  1360. data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
  1361. if ( data == NULL ) {
  1362. status = ERROR_NOT_ENOUGH_MEMORY;
  1363. break;
  1364. }
  1365. }
  1366. goto retry;
  1367. } else if ( status == ERROR_NO_MORE_ITEMS ) {
  1368. status = ERROR_SUCCESS;
  1369. break;
  1370. } else if ( status != ERROR_SUCCESS ) {
  1371. break;
  1372. }
  1373. //
  1374. // Skip this property if it isn't of a known type.
  1375. //
  1376. if ( (type != REG_SZ) &&
  1377. (type != REG_EXPAND_SZ) &&
  1378. (type != REG_MULTI_SZ) &&
  1379. (type != REG_BINARY) &&
  1380. (type != REG_DWORD) &&
  1381. (type != REG_QWORD) ) {
  1382. continue;
  1383. }
  1384. itemCount++;
  1385. //
  1386. // Copy the property name.
  1387. // Need a DWORD for the next name Syntax + DWORD for name byte count +
  1388. // the namelength (in bytes? + NULL?)... must be rounded!
  1389. //
  1390. bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME)
  1391. + ALIGN_CLUSPROP( (nameLength + 1) * sizeof(WCHAR) );
  1392. totalBufferSize += bufferIncrement;
  1393. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1394. props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  1395. props.pName->cbLength = (nameLength + 1) * sizeof(WCHAR);
  1396. lstrcpyW( props.pName->sz, name);
  1397. props.pb += bufferIncrement;
  1398. } else {
  1399. copying = FALSE;
  1400. }
  1401. switch ( type ) {
  1402. case REG_SZ:
  1403. case REG_EXPAND_SZ:
  1404. case REG_MULTI_SZ:
  1405. case REG_BINARY:
  1406. bufferIncrement = sizeof(CLUSPROP_BINARY)
  1407. + ALIGN_CLUSPROP( dataLength );
  1408. totalBufferSize += bufferIncrement;
  1409. if ( ( type == REG_SZ )
  1410. || ( type == REG_EXPAND_SZ ) ) {
  1411. pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) data );
  1412. if ( pszExpanded == NULL ) {
  1413. status = GetLastError();
  1414. break;
  1415. }
  1416. if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
  1417. dataLengthExpanded = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
  1418. bufferIncrementExpanded = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataLengthExpanded );
  1419. totalBufferSize += bufferIncrementExpanded;
  1420. }
  1421. }
  1422. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1423. if ( type == REG_SZ ) {
  1424. props.pSyntax->wFormat = CLUSPROP_FORMAT_SZ;
  1425. } else if ( type == REG_EXPAND_SZ ) {
  1426. props.pSyntax->wFormat = CLUSPROP_FORMAT_EXPAND_SZ;
  1427. } else if ( type == REG_MULTI_SZ ) {
  1428. props.pSyntax->wFormat = CLUSPROP_FORMAT_MULTI_SZ;
  1429. } else {
  1430. props.pSyntax->wFormat = CLUSPROP_FORMAT_BINARY;
  1431. }
  1432. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1433. props.pBinaryValue->cbLength = dataLength;
  1434. CopyMemory( props.pBinaryValue->rgb, data, dataLength );
  1435. props.pb += bufferIncrement;
  1436. //
  1437. // For SZ or EXPAND_SZ, see if there is a different
  1438. // expanded string and, if so, return it as an additional
  1439. // value in the value list.
  1440. //
  1441. if ( ( type == REG_SZ )
  1442. || ( type == REG_EXPAND_SZ ) ) {
  1443. if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
  1444. props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
  1445. props.pStringValue->cbLength = dataLengthExpanded;
  1446. lstrcpyW( props.pStringValue->sz, pszExpanded );
  1447. props.pb += bufferIncrementExpanded;
  1448. }
  1449. }
  1450. } else {
  1451. copying = FALSE;
  1452. }
  1453. if ( ( ( type == REG_SZ ) || ( type == REG_EXPAND_SZ ) )
  1454. && ( pszExpanded != NULL ) )
  1455. {
  1456. LocalFree( pszExpanded );
  1457. pszExpanded = NULL;
  1458. }
  1459. break;
  1460. case REG_DWORD:
  1461. bufferIncrement = sizeof(CLUSPROP_DWORD);
  1462. totalBufferSize += bufferIncrement;
  1463. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1464. props.pSyntax->wFormat = CLUSPROP_FORMAT_DWORD;
  1465. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1466. props.pDwordValue->cbLength = sizeof(DWORD);
  1467. props.pDwordValue->dw = *(LPDWORD)data;
  1468. props.pb += bufferIncrement;
  1469. } else {
  1470. copying = FALSE;
  1471. }
  1472. break;
  1473. case REG_QWORD:
  1474. bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
  1475. totalBufferSize += bufferIncrement;
  1476. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1477. props.pSyntax->wFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
  1478. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1479. props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
  1480. props.pULargeIntegerValue->li.u = ((ULARGE_INTEGER *)data)->u;
  1481. props.pb += bufferIncrement;
  1482. } else {
  1483. copying = FALSE;
  1484. }
  1485. break;
  1486. default:
  1487. break;
  1488. }
  1489. if ( status != ERROR_SUCCESS ) {
  1490. break;
  1491. }
  1492. //
  1493. // Add the closing endmark.
  1494. //
  1495. bufferIncrement = sizeof(CLUSPROP_SYNTAX);
  1496. totalBufferSize += bufferIncrement;
  1497. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1498. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1499. props.pb += bufferIncrement;
  1500. } else {
  1501. copying = FALSE;
  1502. }
  1503. }
  1504. if ( status == ERROR_SUCCESS ) {
  1505. //
  1506. // Add the closing endmark.
  1507. //
  1508. bufferIncrement = sizeof(CLUSPROP_SYNTAX);
  1509. totalBufferSize += bufferIncrement;
  1510. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1511. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1512. props.pb += bufferIncrement;
  1513. } else {
  1514. copying = FALSE;
  1515. }
  1516. }
  1517. LocalFree( name );
  1518. LocalFree( data );
  1519. if ( status == ERROR_SUCCESS ) {
  1520. if ( !copying ) {
  1521. *pcbRequired = totalBufferSize;
  1522. status = ERROR_MORE_DATA;
  1523. } else {
  1524. *ptrItemCount = itemCount;
  1525. *pcbBytesReturned = totalBufferSize;
  1526. status = ERROR_SUCCESS;
  1527. }
  1528. }
  1529. return(status);
  1530. } // ClRtlGetPrivateProperties
  1531. DWORD
  1532. WINAPI
  1533. ClRtlGetUnknownProperties(
  1534. IN PVOID hkeyClusterKey,
  1535. IN const PCLUSTER_REG_APIS pClusterRegApis,
  1536. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  1537. OUT PVOID pOutPropertyList,
  1538. IN DWORD cbOutPropertyListSize,
  1539. OUT LPDWORD pcbBytesReturned,
  1540. OUT LPDWORD pcbRequired
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Gets the unknown properties for a given object.
  1545. Arguments:
  1546. hkeyClusterKey - Supplies the handle to the key in the cluster database
  1547. to read from.
  1548. pClusterRegApis - Supplies a structure of function pointers for accessing
  1549. the cluster database.
  1550. pPropertyTable - Pointer to the property table to process.
  1551. pOutPropertyList - Supplies the output buffer.
  1552. cbOutPropertyListSize - Supplies the size of the output buffer.
  1553. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  1554. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  1555. Return Value:
  1556. ERROR_SUCCESS - Operation was successful.
  1557. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  1558. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  1559. ERROR_MORE_DATA - Output buffer isn't big enough to build the property list.
  1560. A Win32 error code on failure.
  1561. --*/
  1562. {
  1563. DWORD status = ERROR_SUCCESS;
  1564. DWORD ival;
  1565. DWORD currentNameLength = 80;
  1566. DWORD currentDataLength = 80;
  1567. DWORD nameLength;
  1568. DWORD dataLength;
  1569. DWORD dataLengthExpanded;
  1570. DWORD type;
  1571. LPWSTR name;
  1572. PUCHAR data;
  1573. LPDWORD ptrItemCount;
  1574. DWORD itemCount = 0;
  1575. BOOL copying = TRUE;
  1576. DWORD totalBufferSize = 0;
  1577. DWORD bufferIncrement;
  1578. DWORD bufferIncrementExpanded;
  1579. BOOL found;
  1580. LPWSTR pszExpanded = NULL;
  1581. CLUSPROP_BUFFER_HELPER props;
  1582. PRESUTIL_PROPERTY_ITEM property;
  1583. *pcbBytesReturned = 0;
  1584. *pcbRequired = 0;
  1585. if ( (hkeyClusterKey == NULL) ||
  1586. (pClusterRegApis->pfnEnumValue == NULL) ) {
  1587. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPrivateProperties: hkeyClusterKey or pClusterRegApis->pfnEnumValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  1588. return(ERROR_BAD_ARGUMENTS);
  1589. }
  1590. //
  1591. // Clear the output buffer
  1592. //
  1593. if ( pOutPropertyList != NULL ) {
  1594. ZeroMemory( pOutPropertyList, cbOutPropertyListSize );
  1595. } else {
  1596. copying = FALSE;
  1597. }
  1598. //
  1599. // Need a DWORD of item count.
  1600. //
  1601. props.pb = (LPBYTE) pOutPropertyList;
  1602. ptrItemCount = props.pdw++;
  1603. totalBufferSize += sizeof(DWORD);
  1604. if ( totalBufferSize > cbOutPropertyListSize ) {
  1605. copying = FALSE;
  1606. }
  1607. //
  1608. // Allocate a property name buffer.
  1609. //
  1610. name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
  1611. if ( name == NULL ) {
  1612. return(ERROR_NOT_ENOUGH_MEMORY);
  1613. }
  1614. //
  1615. // Allocate a property value data buffer.
  1616. //
  1617. data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
  1618. if ( data == NULL ) {
  1619. LocalFree( name );
  1620. return(ERROR_NOT_ENOUGH_MEMORY);
  1621. }
  1622. //
  1623. // Enumerate all properties and return them!
  1624. //
  1625. for ( ival = 0; ; ival++ ) {
  1626. retry:
  1627. //
  1628. // Read the next property.
  1629. //
  1630. nameLength = currentNameLength;
  1631. dataLength = currentDataLength;
  1632. status = (*pClusterRegApis->pfnEnumValue)( hkeyClusterKey,
  1633. ival,
  1634. name,
  1635. &nameLength,
  1636. &type,
  1637. data,
  1638. &dataLength );
  1639. if ( status == ERROR_MORE_DATA ) {
  1640. if ( (nameLength+1) > currentNameLength ) {
  1641. currentNameLength = nameLength+1;
  1642. LocalFree( name );
  1643. name = (LPWSTR) LocalAlloc( LMEM_FIXED, currentNameLength * sizeof(WCHAR) );
  1644. if ( name == NULL ) {
  1645. status = ERROR_NOT_ENOUGH_MEMORY;
  1646. break;
  1647. }
  1648. }
  1649. if ( dataLength > currentDataLength ) {
  1650. currentDataLength = dataLength;
  1651. LocalFree( data );
  1652. data = (PUCHAR) LocalAlloc( LMEM_FIXED, currentDataLength );
  1653. if ( data == NULL ) {
  1654. status = ERROR_NOT_ENOUGH_MEMORY;
  1655. break;
  1656. }
  1657. }
  1658. goto retry;
  1659. } else if ( status == ERROR_NO_MORE_ITEMS ) {
  1660. status = ERROR_SUCCESS;
  1661. break;
  1662. } else if ( status != ERROR_SUCCESS ) {
  1663. break;
  1664. }
  1665. //
  1666. // Skip this property if it isn't of a known type.
  1667. //
  1668. if ( (type != REG_SZ) &&
  1669. (type != REG_EXPAND_SZ) &&
  1670. (type != REG_MULTI_SZ) &&
  1671. (type != REG_BINARY) &&
  1672. (type != REG_DWORD) &&
  1673. (type != REG_QWORD) ) {
  1674. continue;
  1675. }
  1676. //
  1677. // Check if this property item is 'known'. If so, continue.
  1678. //
  1679. found = FALSE;
  1680. property = pPropertyTable;
  1681. while ( property->Name != NULL ) {
  1682. if ( lstrcmpiW( property->Name, name ) == 0 ) {
  1683. found = TRUE;
  1684. break;
  1685. }
  1686. property++;
  1687. }
  1688. if ( found ) {
  1689. continue;
  1690. }
  1691. itemCount++;
  1692. //
  1693. // Copy the property name.
  1694. // Need a DWORD for the next name Syntax + DWORD for name byte count +
  1695. // the namelength (in bytes? + NULL?)... must be rounded!
  1696. //
  1697. bufferIncrement = sizeof(CLUSPROP_PROPERTY_NAME)
  1698. + ALIGN_CLUSPROP( (nameLength + 1) * sizeof(WCHAR) );
  1699. totalBufferSize += bufferIncrement;
  1700. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1701. props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  1702. props.pName->cbLength = (nameLength + 1) * sizeof(WCHAR);
  1703. lstrcpyW( props.pName->sz, name);
  1704. props.pb += bufferIncrement;
  1705. } else {
  1706. copying = FALSE;
  1707. }
  1708. switch ( type ) {
  1709. case REG_SZ:
  1710. case REG_EXPAND_SZ:
  1711. case REG_MULTI_SZ:
  1712. case REG_BINARY:
  1713. bufferIncrement = sizeof(CLUSPROP_BINARY)
  1714. + ALIGN_CLUSPROP( dataLength );
  1715. totalBufferSize += bufferIncrement;
  1716. if ( type == REG_EXPAND_SZ ) {
  1717. pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) data );
  1718. if ( pszExpanded == NULL ) {
  1719. status = GetLastError();
  1720. break;
  1721. }
  1722. if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
  1723. dataLengthExpanded = (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR );
  1724. bufferIncrementExpanded = sizeof( CLUSPROP_SZ ) + ALIGN_CLUSPROP( dataLengthExpanded );
  1725. totalBufferSize += bufferIncrementExpanded;
  1726. }
  1727. }
  1728. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1729. if ( type == REG_SZ ) {
  1730. props.pSyntax->wFormat = CLUSPROP_FORMAT_SZ;
  1731. } else if ( type == REG_EXPAND_SZ ) {
  1732. props.pSyntax->wFormat = CLUSPROP_FORMAT_EXPAND_SZ;
  1733. } else if ( type == REG_MULTI_SZ ) {
  1734. props.pSyntax->wFormat = CLUSPROP_FORMAT_MULTI_SZ;
  1735. } else {
  1736. props.pSyntax->wFormat = CLUSPROP_FORMAT_BINARY;
  1737. }
  1738. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1739. props.pBinaryValue->cbLength = dataLength;
  1740. CopyMemory( props.pBinaryValue->rgb, data, dataLength );
  1741. props.pb += bufferIncrement;
  1742. //
  1743. // For SZ or EXPAND_SZ, see if there is a different
  1744. // expanded string and, if so, return it as an additional
  1745. // value in the value list.
  1746. //
  1747. if ( ( type == REG_SZ )
  1748. || ( type == REG_EXPAND_SZ ) )
  1749. {
  1750. if ( pszExpanded != NULL ) {
  1751. if ( lstrcmpW( pszExpanded, (LPCWSTR) data ) != 0 ) {
  1752. props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
  1753. props.pStringValue->cbLength = dataLengthExpanded;
  1754. lstrcpyW( props.pStringValue->sz, pszExpanded );
  1755. props.pb += bufferIncrementExpanded;
  1756. }
  1757. }
  1758. }
  1759. } else {
  1760. copying = FALSE;
  1761. }
  1762. if ( type == REG_EXPAND_SZ ) {
  1763. LocalFree( pszExpanded );
  1764. pszExpanded = NULL;
  1765. }
  1766. break;
  1767. case REG_DWORD:
  1768. bufferIncrement = sizeof(CLUSPROP_DWORD);
  1769. totalBufferSize += bufferIncrement;
  1770. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1771. props.pSyntax->wFormat = CLUSPROP_FORMAT_DWORD;
  1772. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1773. props.pDwordValue->cbLength = sizeof(DWORD);
  1774. props.pDwordValue->dw = *(LPDWORD)data;
  1775. props.pb += bufferIncrement;
  1776. } else {
  1777. copying = FALSE;
  1778. }
  1779. break;
  1780. case REG_QWORD:
  1781. bufferIncrement = sizeof(CLUSPROP_ULARGE_INTEGER);
  1782. totalBufferSize += bufferIncrement;
  1783. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1784. props.pSyntax->wFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
  1785. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  1786. props.pULargeIntegerValue->cbLength = sizeof(ULARGE_INTEGER);
  1787. props.pULargeIntegerValue->li.u = ((ULARGE_INTEGER *)data)->u;
  1788. props.pb += bufferIncrement;
  1789. } else {
  1790. copying = FALSE;
  1791. }
  1792. break;
  1793. default:
  1794. break;
  1795. }
  1796. //
  1797. // Add the closing endmark.
  1798. //
  1799. bufferIncrement = sizeof(CLUSPROP_SYNTAX);
  1800. totalBufferSize += bufferIncrement;
  1801. if ( copying && (totalBufferSize <= cbOutPropertyListSize) ) {
  1802. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1803. props.pb += bufferIncrement;
  1804. } else {
  1805. copying = FALSE;
  1806. }
  1807. }
  1808. LocalFree( name );
  1809. LocalFree( data );
  1810. if ( !copying ) {
  1811. *pcbRequired = totalBufferSize;
  1812. status = ERROR_MORE_DATA;
  1813. } else {
  1814. *ptrItemCount = itemCount;
  1815. *pcbBytesReturned = totalBufferSize;
  1816. status = ERROR_SUCCESS;
  1817. }
  1818. return(status);
  1819. } // ClRtlGetUnknownProperties
  1820. DWORD
  1821. WINAPI
  1822. ClRtlAddUnknownProperties(
  1823. IN PVOID hkeyClusterKey,
  1824. IN const PCLUSTER_REG_APIS pClusterRegApis,
  1825. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  1826. IN OUT PVOID pOutPropertyList,
  1827. IN DWORD cbOutPropertyListSize,
  1828. IN OUT LPDWORD pcbBytesReturned,
  1829. IN OUT LPDWORD pcbRequired
  1830. )
  1831. /*++
  1832. Routine Description:
  1833. Adds the unknown properties for a given object to the end of a property
  1834. list.
  1835. Arguments:
  1836. hkeyClusterKey - Supplies the handle to the key in the cluster database
  1837. to read from.
  1838. pClusterRegApis - Supplies a structure of function pointers for accessing
  1839. the cluster database.
  1840. pPropertyTable - Pointer to the property table to process.
  1841. pOutPropertyList - Supplies the output buffer.
  1842. cbOutPropertyListSize - Supplies the size of the output buffer.
  1843. pcbBytesReturned - On input, contains the number of bytes in use in the
  1844. output buffer. On output, contains the total number of bytes in
  1845. pOutPropertyList.
  1846. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  1847. Return Value:
  1848. ERROR_SUCCESS - Operation was successful.
  1849. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  1850. A Win32 error code on failure.
  1851. --*/
  1852. {
  1853. DWORD status;
  1854. CLUSPROP_BUFFER_HELPER copyBuffer;
  1855. CLUSPROP_BUFFER_HELPER outBuffer;
  1856. DWORD bufferLength;
  1857. DWORD bytesReturned;
  1858. DWORD required;
  1859. //
  1860. // Allocate a buffer for getting 'unknown' properties.
  1861. //
  1862. if ( (cbOutPropertyListSize > *pcbBytesReturned) &&
  1863. (*pcbRequired == 0) )
  1864. {
  1865. bufferLength = cbOutPropertyListSize + (2 * sizeof(DWORD)) - *pcbBytesReturned;
  1866. outBuffer.pb = (LPBYTE) LocalAlloc( LMEM_FIXED, bufferLength );
  1867. if ( outBuffer.pb == NULL ) {
  1868. *pcbBytesReturned = 0;
  1869. *pcbRequired = 0;
  1870. return(ERROR_NOT_ENOUGH_MEMORY);
  1871. }
  1872. } else {
  1873. bufferLength = 0;
  1874. outBuffer.pb = NULL;
  1875. }
  1876. //
  1877. // Get the 'unknown' properties.
  1878. //
  1879. status = ClRtlGetUnknownProperties( hkeyClusterKey,
  1880. pClusterRegApis,
  1881. pPropertyTable,
  1882. outBuffer.pb,
  1883. bufferLength,
  1884. &bytesReturned,
  1885. &required );
  1886. if ( status == ERROR_SUCCESS ) {
  1887. //
  1888. // Copy properties if any were found.
  1889. //
  1890. if ( bytesReturned > sizeof(DWORD) ) {
  1891. //
  1892. // Copy the unknown property data to the end of the property list.
  1893. //
  1894. CL_ASSERT( bytesReturned <= bufferLength );
  1895. copyBuffer.pb = (LPBYTE) pOutPropertyList;
  1896. copyBuffer.pList->nPropertyCount += outBuffer.pList->nPropertyCount;
  1897. copyBuffer.pb += *pcbBytesReturned - sizeof(CLUSPROP_SYNTAX);
  1898. CopyMemory( copyBuffer.pb, outBuffer.pb + sizeof(DWORD), bytesReturned - sizeof(DWORD) );
  1899. *pcbBytesReturned += bytesReturned - sizeof(DWORD) - sizeof(CLUSPROP_SYNTAX);
  1900. }
  1901. } else if ( ( status == ERROR_MORE_DATA )
  1902. && ( required == sizeof(DWORD) ) ) {
  1903. required = 0;
  1904. status = ERROR_SUCCESS;
  1905. } else {
  1906. if ( *pcbRequired == 0 ) {
  1907. *pcbRequired = *pcbBytesReturned;
  1908. }
  1909. *pcbBytesReturned = 0;
  1910. }
  1911. //
  1912. // If there are any properties, the number of bytes required will include
  1913. // both a property count (DWORD) and an endmark (CLUSPROP_SYNTAX).
  1914. // Subtract these off because these appear in both lists.
  1915. //
  1916. if ( required > sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX) ) {
  1917. required -= sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
  1918. }
  1919. //
  1920. // Free the out buffer (which may be NULL)
  1921. //
  1922. LocalFree( outBuffer.pb );
  1923. //
  1924. // Adjust lengths
  1925. //
  1926. *pcbRequired += required;
  1927. return(status);
  1928. } // ClRtlAddUnknownProperties
  1929. DWORD
  1930. WINAPI
  1931. ClRtlGetPropertySize(
  1932. IN PVOID hkeyClusterKey,
  1933. IN const PCLUSTER_REG_APIS pClusterRegApis,
  1934. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  1935. IN OUT LPDWORD pcbOutPropertyListSize,
  1936. IN OUT LPDWORD pnPropertyCount
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. Get the total number of bytes required for this property.
  1941. Arguments:
  1942. hkeyClusterKey - Supplies the handle to the key in the cluster database
  1943. to read from.
  1944. pClusterRegApis - Supplies a structure of function pointers for accessing
  1945. the cluster database.
  1946. pPropertyTableItem - Supplies the property table item for the property
  1947. whose size is to be returned.
  1948. pcbOutPropertyListSize - Supplies the size of the output buffer
  1949. required to add this property to a property list.
  1950. pnPropertyCount - The count of properties is incremented.
  1951. Return Value:
  1952. ERROR_SUCCESS - Operation was successful.
  1953. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  1954. ERROR_INVALID_PARAMETER -
  1955. A Win32 error code on failure.
  1956. --*/
  1957. {
  1958. DWORD status = ERROR_SUCCESS;
  1959. DWORD valueType;
  1960. DWORD bytesReturned;
  1961. DWORD headerLength;
  1962. PVOID key;
  1963. LPWSTR pszValue = NULL;
  1964. LPWSTR pszExpanded = NULL;
  1965. CRegistryValueName rvn;
  1966. if ( (hkeyClusterKey == NULL) ||
  1967. (pClusterRegApis->pfnQueryValue == NULL) ) {
  1968. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: hkeyClusterKey or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  1969. return(ERROR_BAD_ARGUMENTS);
  1970. }
  1971. //
  1972. // Use the wrapper class CRegistryValueName to parse value name to see if it
  1973. // contains a backslash.
  1974. //
  1975. status = rvn.ScInit( pPropertyTableItem->Name, pPropertyTableItem->KeyName );
  1976. if ( status != ERROR_SUCCESS )
  1977. {
  1978. return status;
  1979. }
  1980. //
  1981. // If the value resides at a different location, open the key.
  1982. //
  1983. if ( rvn.PszKeyName() != NULL ) {
  1984. if ( (pClusterRegApis->pfnOpenKey == NULL) ||
  1985. (pClusterRegApis->pfnCloseKey == NULL) ) {
  1986. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: pClusterRegApis->pfnOpenValue or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  1987. return(ERROR_BAD_ARGUMENTS);
  1988. }
  1989. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  1990. rvn.PszKeyName(),
  1991. KEY_READ,
  1992. &key);
  1993. } else {
  1994. key = hkeyClusterKey;
  1995. }
  1996. //
  1997. // Read the value size.
  1998. //
  1999. if ( status == ERROR_SUCCESS ) {
  2000. status = (*pClusterRegApis->pfnQueryValue)( key,
  2001. rvn.PszName(),
  2002. &valueType,
  2003. NULL,
  2004. &bytesReturned );
  2005. }
  2006. //
  2007. // If the value is not present, return the default value.
  2008. //
  2009. if ( status == ERROR_FILE_NOT_FOUND ) {
  2010. switch ( pPropertyTableItem->Format ) {
  2011. case CLUSPROP_FORMAT_DWORD:
  2012. case CLUSPROP_FORMAT_LONG:
  2013. status = ERROR_SUCCESS;
  2014. bytesReturned = sizeof(DWORD);
  2015. valueType = pPropertyTableItem->Format;
  2016. break;
  2017. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2018. case CLUSPROP_FORMAT_LARGE_INTEGER:
  2019. status = ERROR_SUCCESS;
  2020. bytesReturned = sizeof(ULARGE_INTEGER);
  2021. valueType = pPropertyTableItem->Format;
  2022. break;
  2023. case CLUSPROP_FORMAT_MULTI_SZ:
  2024. status = ERROR_SUCCESS;
  2025. if ( pPropertyTableItem->Default != 0 ) {
  2026. bytesReturned = pPropertyTableItem->Minimum;
  2027. } else {
  2028. bytesReturned = sizeof(WCHAR);
  2029. }
  2030. valueType = pPropertyTableItem->Format;
  2031. break;
  2032. case CLUSPROP_FORMAT_SZ:
  2033. case CLUSPROP_FORMAT_EXPAND_SZ:
  2034. status = ERROR_SUCCESS;
  2035. if ( pPropertyTableItem->Default != 0 ) {
  2036. bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
  2037. } else {
  2038. bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
  2039. }
  2040. valueType = pPropertyTableItem->Format;
  2041. break;
  2042. case CLUSPROP_FORMAT_BINARY:
  2043. status = ERROR_SUCCESS;
  2044. if ( pPropertyTableItem->Default != 0 ) {
  2045. bytesReturned = pPropertyTableItem->Minimum;
  2046. } else {
  2047. bytesReturned = 0;
  2048. }
  2049. valueType = pPropertyTableItem->Format;
  2050. break;
  2051. default:
  2052. valueType = CLUSPROP_FORMAT_UNKNOWN;
  2053. break;
  2054. }
  2055. } else if ( status == ERROR_SUCCESS ) {
  2056. switch ( valueType ) {
  2057. case REG_DWORD:
  2058. if ((pPropertyTableItem->Format == CLUSPROP_FORMAT_DWORD) ||
  2059. (pPropertyTableItem->Format == CLUSPROP_FORMAT_LONG))
  2060. {
  2061. valueType = pPropertyTableItem->Format;
  2062. } else {
  2063. valueType = CLUSPROP_FORMAT_UNKNOWN;
  2064. }
  2065. break;
  2066. case REG_QWORD:
  2067. if ((pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER) ||
  2068. (pPropertyTableItem->Format == CLUSPROP_FORMAT_LARGE_INTEGER))
  2069. {
  2070. valueType = pPropertyTableItem->Format;
  2071. } else {
  2072. valueType = CLUSPROP_FORMAT_UNKNOWN;
  2073. }
  2074. break;
  2075. case REG_MULTI_SZ:
  2076. valueType = CLUSPROP_FORMAT_MULTI_SZ;
  2077. break;
  2078. case REG_SZ:
  2079. case REG_EXPAND_SZ:
  2080. //
  2081. // Include the size of the expanded string in both REG_SZ and REG_EXPAND_SZ
  2082. //
  2083. pszValue = ClRtlGetSzValue( (HKEY) key,
  2084. rvn.PszName(),
  2085. pClusterRegApis );
  2086. if ( pszValue != NULL ) {
  2087. pszExpanded = ClRtlExpandEnvironmentStrings( pszValue );
  2088. if ( pszExpanded == NULL ) {
  2089. status = GetLastError();
  2090. } else if ( lstrcmpW( pszValue, pszExpanded ) != 0 ) {
  2091. bytesReturned += ALIGN_CLUSPROP( (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR ) );
  2092. bytesReturned += sizeof(CLUSPROP_SZ);
  2093. }
  2094. LocalFree( pszValue );
  2095. LocalFree( pszExpanded );
  2096. }
  2097. if ( valueType == REG_SZ ) {
  2098. valueType = CLUSPROP_FORMAT_SZ;
  2099. }
  2100. else {
  2101. valueType = CLUSPROP_FORMAT_EXPAND_SZ;
  2102. }
  2103. break;
  2104. case REG_BINARY:
  2105. valueType = CLUSPROP_FORMAT_BINARY;
  2106. break;
  2107. default:
  2108. valueType = CLUSPROP_FORMAT_UNKNOWN;
  2109. break;
  2110. }
  2111. }
  2112. if ( status == ERROR_FILE_NOT_FOUND ) {
  2113. status = ERROR_SUCCESS;
  2114. } else if ( status == ERROR_SUCCESS ) {
  2115. if ( pPropertyTableItem->Format != valueType ) {
  2116. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetPropertySize: Property '%1!ls!' format %2!d! expected, was %3!d!.\n", rvn.PszKeyName(), pPropertyTableItem->Format, valueType );
  2117. status = ERROR_INVALID_PARAMETER;
  2118. } else {
  2119. //assume that the size of dword and long
  2120. //is fixed to 32 bits
  2121. if (( valueType == CLUSPROP_FORMAT_DWORD ) ||
  2122. ( valueType == CLUSPROP_FORMAT_LONG ))
  2123. {
  2124. headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
  2125. + ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
  2126. + sizeof(CLUSPROP_DWORD)
  2127. - 4 // CLUSPROP_DWORD.dw (specified by bytesReturned)
  2128. + sizeof(CLUSPROP_SYNTAX); // for endmark
  2129. } else
  2130. if (( valueType == CLUSPROP_FORMAT_ULARGE_INTEGER ) ||
  2131. ( valueType == CLUSPROP_FORMAT_LARGE_INTEGER ))
  2132. {
  2133. headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
  2134. + ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
  2135. + sizeof(CLUSPROP_ULARGE_INTEGER)
  2136. - 8 // CLUSPROP_ULARGE_INTEGER.li (specified by bytesReturned)
  2137. + sizeof(CLUSPROP_SYNTAX); // for endmark
  2138. } else {
  2139. // NOTE: This assumes SZ, EXPAND_SZ, MULTI_SZ, and BINARY are the same size
  2140. headerLength = sizeof(CLUSPROP_PROPERTY_NAME)
  2141. + ((lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
  2142. + sizeof(CLUSPROP_BINARY)
  2143. + sizeof(CLUSPROP_SYNTAX); // for endmark
  2144. }
  2145. headerLength = ALIGN_CLUSPROP( headerLength );
  2146. bytesReturned = ALIGN_CLUSPROP( bytesReturned );
  2147. *pcbOutPropertyListSize += (bytesReturned + headerLength);
  2148. *pnPropertyCount += 1;
  2149. }
  2150. }
  2151. //
  2152. // Close the key if we opened it.
  2153. //
  2154. if ( ( rvn.PszKeyName() != NULL ) &&
  2155. ( key != NULL ) ) {
  2156. (*pClusterRegApis->pfnCloseKey)( key );
  2157. }
  2158. return(status);
  2159. } // ClRtlGetPropertySize
  2160. DWORD
  2161. WINAPI
  2162. ClRtlGetProperty(
  2163. IN PVOID hkeyClusterKey,
  2164. IN const PCLUSTER_REG_APIS pClusterRegApis,
  2165. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  2166. OUT PVOID * pOutPropertyItem,
  2167. IN OUT LPDWORD pcbOutPropertyItemSize
  2168. )
  2169. /*++
  2170. Routine Description:
  2171. Arguments:
  2172. Return Value:
  2173. ERROR_SUCCESS -
  2174. ERROR_BAD_ARGUMENTS -
  2175. ERROR_MORE_DATA -
  2176. Notes:
  2177. The buffer size has already been determined to be large enough to hold
  2178. the return data.
  2179. --*/
  2180. {
  2181. DWORD status = ERROR_SUCCESS;
  2182. DWORD valueType;
  2183. DWORD bytesReturned;
  2184. DWORD bufferSize;
  2185. PVOID dataBuffer;
  2186. DWORD nameLength;
  2187. PVOID key = NULL;
  2188. CLUSTER_PROPERTY_FORMAT format;
  2189. CLUSPROP_BUFFER_HELPER props;
  2190. LPWSTR pszExpanded = NULL;
  2191. CRegistryValueName rvn;
  2192. if ( (hkeyClusterKey == NULL) ||
  2193. (pClusterRegApis->pfnQueryValue == NULL) ) {
  2194. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetProperty: hkeyClusterKey or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  2195. return(ERROR_BAD_ARGUMENTS);
  2196. }
  2197. //
  2198. // Use the wrapper class CRegistryValueName to parse value name to see if it
  2199. // contains a backslash.
  2200. //
  2201. status = rvn.ScInit( pPropertyTableItem->Name, pPropertyTableItem->KeyName );
  2202. if ( status != ERROR_SUCCESS )
  2203. {
  2204. return status;
  2205. }
  2206. //
  2207. // If the value resides at a different location, open the key.
  2208. //
  2209. if ( rvn.PszKeyName() != NULL ) {
  2210. if ( (pClusterRegApis->pfnOpenKey == NULL) ||
  2211. (pClusterRegApis->pfnCloseKey == NULL) ) {
  2212. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetProperty: pClusterRegApis->pfnOpenValue or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  2213. return(ERROR_BAD_ARGUMENTS);
  2214. }
  2215. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  2216. rvn.PszKeyName(),
  2217. KEY_READ,
  2218. &key);
  2219. } else {
  2220. key = hkeyClusterKey;
  2221. }
  2222. //
  2223. // Find out if this property is available
  2224. //
  2225. if ( status == ERROR_SUCCESS ) {
  2226. status = (*pClusterRegApis->pfnQueryValue)( key,
  2227. rvn.PszName(),
  2228. &valueType,
  2229. NULL,
  2230. &bytesReturned );
  2231. }
  2232. //
  2233. // If the value is not present, return the default value.
  2234. //
  2235. if ( status == ERROR_FILE_NOT_FOUND ) {
  2236. switch ( pPropertyTableItem->Format ) {
  2237. case CLUSPROP_FORMAT_DWORD:
  2238. case CLUSPROP_FORMAT_LONG:
  2239. status = ERROR_SUCCESS;
  2240. bytesReturned = sizeof(DWORD);
  2241. valueType = pPropertyTableItem->Format;
  2242. break;
  2243. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2244. case CLUSPROP_FORMAT_LARGE_INTEGER:
  2245. status = ERROR_SUCCESS;
  2246. bytesReturned = sizeof(ULARGE_INTEGER);
  2247. valueType = pPropertyTableItem->Format;
  2248. break;
  2249. case CLUSPROP_FORMAT_MULTI_SZ:
  2250. status = ERROR_SUCCESS;
  2251. if ( pPropertyTableItem->Default != 0 ) {
  2252. bytesReturned = pPropertyTableItem->Minimum;
  2253. } else {
  2254. bytesReturned = sizeof(WCHAR);
  2255. }
  2256. valueType = pPropertyTableItem->Format;
  2257. break;
  2258. case CLUSPROP_FORMAT_SZ:
  2259. case CLUSPROP_FORMAT_EXPAND_SZ:
  2260. status = ERROR_SUCCESS;
  2261. if ( pPropertyTableItem->Default != 0 ) {
  2262. bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
  2263. } else {
  2264. bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
  2265. }
  2266. valueType = pPropertyTableItem->Format;
  2267. break;
  2268. case CLUSPROP_FORMAT_BINARY:
  2269. status = ERROR_SUCCESS;
  2270. if ( pPropertyTableItem->Default != 0 ) {
  2271. bytesReturned = pPropertyTableItem->Minimum;
  2272. } else {
  2273. bytesReturned = 0;
  2274. }
  2275. valueType = pPropertyTableItem->Format;
  2276. break;
  2277. default:
  2278. valueType = CLUSPROP_FORMAT_UNKNOWN;
  2279. break;
  2280. }
  2281. }
  2282. if ( status == ERROR_SUCCESS ) {
  2283. //
  2284. // Get the property format
  2285. //
  2286. switch ( pPropertyTableItem->Format ) {
  2287. case CLUSPROP_FORMAT_BINARY:
  2288. case CLUSPROP_FORMAT_DWORD:
  2289. case CLUSPROP_FORMAT_LONG:
  2290. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2291. case CLUSPROP_FORMAT_LARGE_INTEGER:
  2292. case CLUSPROP_FORMAT_MULTI_SZ:
  2293. case CLUSPROP_FORMAT_SZ:
  2294. case CLUSPROP_FORMAT_EXPAND_SZ:
  2295. format = (enum CLUSTER_PROPERTY_FORMAT) pPropertyTableItem->Format;
  2296. break;
  2297. default:
  2298. format = CLUSPROP_FORMAT_UNKNOWN;
  2299. break;
  2300. }
  2301. props.pb = (LPBYTE) *pOutPropertyItem;
  2302. //
  2303. // Copy the property name, which includes its syntax and length.
  2304. //
  2305. nameLength = (lstrlenW( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR);
  2306. props.pSyntax->dw = CLUSPROP_SYNTAX_NAME;
  2307. props.pName->cbLength = nameLength;
  2308. lstrcpyW( props.pName->sz, pPropertyTableItem->Name );
  2309. bytesReturned = sizeof(*props.pName) + ALIGN_CLUSPROP( nameLength );
  2310. *pcbOutPropertyItemSize -= bytesReturned;
  2311. props.pb += bytesReturned;
  2312. //
  2313. // Copy the property value header.
  2314. //
  2315. props.pSyntax->wFormat = (USHORT)format;
  2316. props.pSyntax->wType = CLUSPROP_TYPE_LIST_VALUE;
  2317. //
  2318. // Read the property value.
  2319. //
  2320. if ( pPropertyTableItem->Format == CLUSPROP_FORMAT_DWORD ||
  2321. pPropertyTableItem->Format == CLUSPROP_FORMAT_LONG )
  2322. {
  2323. bufferSize = *pcbOutPropertyItemSize
  2324. - (sizeof(*props.pDwordValue) - sizeof(props.pDwordValue->dw));
  2325. dataBuffer = &props.pDwordValue->dw;
  2326. } else
  2327. if ( pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER ||
  2328. pPropertyTableItem->Format == CLUSPROP_FORMAT_ULARGE_INTEGER )
  2329. {
  2330. bufferSize = *pcbOutPropertyItemSize
  2331. - (sizeof(*props.pULargeIntegerValue) - sizeof(props.pULargeIntegerValue->li));
  2332. dataBuffer = &props.pULargeIntegerValue->li;
  2333. } else {
  2334. // NOTE: This assumes SZ, MULTI_SZ, and BINARY are the same size
  2335. bufferSize = *pcbOutPropertyItemSize - sizeof(*props.pBinaryValue);
  2336. dataBuffer = props.pBinaryValue->rgb;
  2337. }
  2338. bytesReturned = bufferSize;
  2339. if ( key == NULL ) {
  2340. status = ERROR_FILE_NOT_FOUND;
  2341. } else {
  2342. status = (*pClusterRegApis->pfnQueryValue)( key,
  2343. rvn.PszName(),
  2344. &valueType,
  2345. (LPBYTE) dataBuffer,
  2346. &bytesReturned );
  2347. }
  2348. //
  2349. // If the value is not present, return the default value.
  2350. //
  2351. if ( status == ERROR_FILE_NOT_FOUND ) {
  2352. switch ( pPropertyTableItem->Format ) {
  2353. case CLUSPROP_FORMAT_DWORD:
  2354. case CLUSPROP_FORMAT_LONG:
  2355. //assume size of dword and long is the same
  2356. status = ERROR_SUCCESS;
  2357. bytesReturned = sizeof(DWORD);
  2358. props.pDwordValue->dw = pPropertyTableItem->Default;
  2359. break;
  2360. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2361. case CLUSPROP_FORMAT_LARGE_INTEGER:
  2362. status = ERROR_SUCCESS;
  2363. bytesReturned = sizeof(ULARGE_INTEGER);
  2364. props.pULargeIntegerValue->li.u = pPropertyTableItem->ULargeIntData->Default.u;
  2365. break;
  2366. case CLUSPROP_FORMAT_MULTI_SZ:
  2367. status = ERROR_SUCCESS;
  2368. if ( pPropertyTableItem->Default != 0 ) {
  2369. bytesReturned = pPropertyTableItem->Minimum;
  2370. if ( bufferSize < bytesReturned ) {
  2371. CopyMemory( dataBuffer, (LPCWSTR)pPropertyTableItem->lpDefault, bytesReturned );
  2372. }
  2373. } else {
  2374. bytesReturned = sizeof(WCHAR);
  2375. }
  2376. break;
  2377. case CLUSPROP_FORMAT_SZ:
  2378. case CLUSPROP_FORMAT_EXPAND_SZ:
  2379. status = ERROR_SUCCESS;
  2380. if ( pPropertyTableItem->Default != 0 ) {
  2381. bytesReturned = (lstrlenW((LPCWSTR)pPropertyTableItem->lpDefault) + 1) * sizeof(WCHAR);
  2382. if ( bufferSize < bytesReturned ) {
  2383. lstrcpyW( (LPWSTR) dataBuffer, (LPCWSTR)pPropertyTableItem->lpDefault );
  2384. }
  2385. } else {
  2386. bytesReturned = (lstrlenW(CLRTL_NULL_STRING) + 1) * sizeof(WCHAR);
  2387. }
  2388. break;
  2389. case CLUSPROP_FORMAT_BINARY:
  2390. status = ERROR_SUCCESS;
  2391. if ( pPropertyTableItem->Default != 0 ) {
  2392. bytesReturned = pPropertyTableItem->Minimum;
  2393. if ( bufferSize < bytesReturned ) {
  2394. CopyMemory( dataBuffer, (LPBYTE)pPropertyTableItem->lpDefault, bytesReturned );
  2395. }
  2396. } else {
  2397. bytesReturned = 0;
  2398. }
  2399. break;
  2400. default:
  2401. break;
  2402. }
  2403. }
  2404. if ( bufferSize < bytesReturned ) {
  2405. status = ERROR_MORE_DATA;
  2406. } else if ( status == ERROR_SUCCESS ) {
  2407. props.pValue->cbLength = bytesReturned;
  2408. // Round the bytes used up to the next DWORD boundary.
  2409. bytesReturned = ALIGN_CLUSPROP( bytesReturned );
  2410. bytesReturned += sizeof(*props.pValue);
  2411. props.pb += bytesReturned;
  2412. //
  2413. // If this is an SZ or EXPAND_SZ, see if the expanded value should
  2414. // be added to the value list.
  2415. //
  2416. if ( ( pPropertyTableItem->Format == CLUSPROP_FORMAT_SZ )
  2417. || ( pPropertyTableItem->Format == CLUSPROP_FORMAT_EXPAND_SZ ) ) {
  2418. pszExpanded = ClRtlExpandEnvironmentStrings( (LPCWSTR) dataBuffer );
  2419. if ( pszExpanded == NULL ) {
  2420. status = GetLastError();
  2421. } else {
  2422. if ( lstrcmpiW( pszExpanded, (LPCWSTR) dataBuffer ) != 0 ) {
  2423. props.pSyntax->dw = CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ;
  2424. bufferSize = ALIGN_CLUSPROP( (lstrlenW( pszExpanded ) + 1) * sizeof( WCHAR ) );
  2425. props.pStringValue->cbLength = bufferSize;
  2426. lstrcpyW( props.pStringValue->sz, pszExpanded );
  2427. bytesReturned += sizeof( *props.pStringValue ) + bufferSize;
  2428. props.pb += sizeof( *props.pStringValue ) + bufferSize;
  2429. }
  2430. LocalFree( pszExpanded );
  2431. }
  2432. }
  2433. if ( status == ERROR_SUCCESS ) {
  2434. // Add the value list endmark.
  2435. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  2436. props.pb += sizeof(*props.pSyntax);
  2437. bytesReturned += sizeof(*props.pSyntax);
  2438. *pcbOutPropertyItemSize -= bytesReturned;
  2439. *pOutPropertyItem = (PVOID)props.pb;
  2440. } // if: ERROR_SUCCESS
  2441. } // else if: ERROR_SUCCESS
  2442. } // if: ERROR_SUCCESS
  2443. if ( status == ERROR_FILE_NOT_FOUND ) {
  2444. status = ERROR_SUCCESS;
  2445. }
  2446. //
  2447. // Close the key if we opened it.
  2448. //
  2449. if ( (rvn.PszKeyName() != NULL) &&
  2450. (key != NULL) ) {
  2451. (*pClusterRegApis->pfnCloseKey)( key );
  2452. }
  2453. return(status);
  2454. } // ClRtlGetProperty
  2455. DWORD
  2456. WINAPI
  2457. ClRtlpSetPropertyTable(
  2458. IN HANDLE hXsaction,
  2459. IN PVOID hkeyClusterKey,
  2460. IN const PCLUSTER_REG_APIS pClusterRegApis,
  2461. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  2462. IN PVOID Reserved,
  2463. IN BOOL bAllowUnknownProperties,
  2464. IN const PVOID pInPropertyList,
  2465. IN DWORD cbInPropertyListSize,
  2466. IN BOOL bForceWrite,
  2467. IN OUT OPTIONAL LPBYTE pOutParams
  2468. )
  2469. /*++
  2470. Routine Description:
  2471. Arguments:
  2472. hkeyClusterKey - The opened cluster database key where properties are to
  2473. be written. If not specified, the property list will only be
  2474. validated.
  2475. pClusterRegApis - Supplies a structure of function pointers for accessing
  2476. the cluster database.
  2477. pPropertyTable - Pointer to the property table to process.
  2478. Reserved - Reserved for future use.
  2479. bAllowUnknownProperties - Don't fail if unknown properties are found.
  2480. pInPropertyList - The input buffer.
  2481. cbInPropertyListSize - The input buffer size.
  2482. bForceWrite - TRUE = always write the properties to the cluster database.
  2483. FALSE = only write the properties if they changed.
  2484. pOutParams - Parameter block in which to return the data. If specified,
  2485. parameters will only be written if they are different between
  2486. the input buffer and the parameter block.
  2487. Return Value:
  2488. ERROR_SUCCESS if successful.
  2489. ERROR_BAD_ARGUMENTS - hkeyClusterKey is specified but proper cluster
  2490. registry APIs are not specified, or no property table is specified.
  2491. ERROR_INVALID_DATA - No property list is specified or the format of the
  2492. property list is invalid.
  2493. ERROR_INSUFFICIENT_BUFFER - The property list buffer isn't large enough to
  2494. contain all the data it indicates it should contain.
  2495. ERROR_INVALID_PARAMETER - The property list isn't formatted properly.
  2496. A Win32 Error on failure.
  2497. --*/
  2498. {
  2499. DWORD status = ERROR_SUCCESS;
  2500. PRESUTIL_PROPERTY_ITEM propertyItem;
  2501. DWORD inBufferSize;
  2502. DWORD itemCount;
  2503. DWORD dataSize;
  2504. PVOID key;
  2505. CLUSPROP_BUFFER_HELPER buf;
  2506. PCLUSPROP_PROPERTY_NAME pName;
  2507. CRegistryValueName rvn;
  2508. if ( ( (hkeyClusterKey != NULL) &&
  2509. (pClusterRegApis->pfnSetValue == NULL) ) ||
  2510. ( pPropertyTable == NULL ) ) {
  2511. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: hkeyClusterKey or pClusterRegApis->pfnSetValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  2512. return(ERROR_BAD_ARGUMENTS);
  2513. }
  2514. if ( pInPropertyList == NULL ) {
  2515. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
  2516. return(ERROR_INVALID_DATA);
  2517. }
  2518. buf.pb = (LPBYTE) pInPropertyList;
  2519. inBufferSize = cbInPropertyListSize;
  2520. //
  2521. // Get the number of items in this list
  2522. //
  2523. if ( inBufferSize < sizeof(DWORD) ) {
  2524. return(ERROR_INSUFFICIENT_BUFFER);
  2525. }
  2526. itemCount = buf.pList->nPropertyCount;
  2527. buf.pdw++;
  2528. inBufferSize -= sizeof(*buf.pdw);
  2529. //
  2530. // Parse the rest of the items in the buffer.
  2531. //
  2532. while ( itemCount-- ) {
  2533. //
  2534. // Verify that the buffer is big enough to contain the
  2535. // property name and a value.
  2536. //
  2537. pName = buf.pName;
  2538. if ( inBufferSize < sizeof(*pName) ) {
  2539. return(ERROR_INSUFFICIENT_BUFFER);
  2540. }
  2541. dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
  2542. if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
  2543. return(ERROR_INSUFFICIENT_BUFFER);
  2544. }
  2545. //
  2546. // Verify that the syntax of the property name is correct.
  2547. //
  2548. if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
  2549. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: not a name syntax.\n" );
  2550. return(ERROR_INVALID_PARAMETER);
  2551. }
  2552. //
  2553. // Verify that the length is correct for the string.
  2554. //
  2555. if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
  2556. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: name is not a valid C string.\n" );
  2557. return(ERROR_INVALID_DATA);
  2558. }
  2559. //
  2560. // Move the buffer pointer to the property value.
  2561. //
  2562. buf.pb += dataSize;
  2563. inBufferSize -= dataSize;
  2564. //
  2565. // Find the property name in the list of known properties.
  2566. //
  2567. propertyItem = pPropertyTable;
  2568. while ( propertyItem->Name != NULL ) {
  2569. if ( lstrcmpiW( pName->sz, propertyItem->Name ) == 0 ) {
  2570. //
  2571. // Verify that the buffer is big enough to contain the value.
  2572. //
  2573. dataSize = sizeof(*buf.pValue)
  2574. + ALIGN_CLUSPROP( buf.pValue->cbLength )
  2575. + sizeof(CLUSPROP_SYNTAX); // endmark
  2576. if ( inBufferSize < dataSize ) {
  2577. return(ERROR_INSUFFICIENT_BUFFER);
  2578. }
  2579. //
  2580. // Verify that the syntax type is LIST_VALUE.
  2581. //
  2582. if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
  2583. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' type CLUSPROP_TYPE_LIST_VALUE (%2!d!) expected, was %3!d!.\n", pName->sz, CLUSPROP_TYPE_LIST_VALUE, buf.pSyntax->wType );
  2584. return(ERROR_INVALID_PARAMETER);
  2585. }
  2586. //
  2587. // Verify that this property should be of this format.
  2588. //
  2589. if ( buf.pSyntax->wFormat != propertyItem->Format ) {
  2590. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' format %2!d! expected, was %3!d!.\n", pName->sz, propertyItem->Format, buf.pSyntax->wType );
  2591. status = ERROR_INVALID_PARAMETER;
  2592. break;
  2593. }
  2594. //
  2595. // Make sure we are allowed to set this item.
  2596. //
  2597. if ( propertyItem->Flags & RESUTIL_PROPITEM_READ_ONLY ) {
  2598. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' is non-writable.\n", pName->sz );
  2599. return(ERROR_INVALID_PARAMETER);
  2600. }
  2601. //
  2602. // Use the wrapper class CRegistryValueName to parse value name to see if it
  2603. // contains a backslash.
  2604. //
  2605. status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
  2606. if ( status != ERROR_SUCCESS ) {
  2607. return status;
  2608. }
  2609. //
  2610. // If the value resides at a different location, create the key.
  2611. //
  2612. if ( (hkeyClusterKey != NULL) &&
  2613. (rvn.PszKeyName() != NULL) ) {
  2614. DWORD disposition;
  2615. if ( (pClusterRegApis->pfnCreateKey == NULL) ||
  2616. (pClusterRegApis->pfnCloseKey == NULL) ) {
  2617. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pClusterRegApis->pfnCreateKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  2618. return(ERROR_BAD_ARGUMENTS);
  2619. }
  2620. if ( hXsaction != NULL ) {
  2621. if ( pClusterRegApis->pfnLocalCreateKey == NULL ) {
  2622. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: pClusterRegApis->pfnLocalCreateKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  2623. return(ERROR_BAD_ARGUMENTS);
  2624. }
  2625. status = (*pClusterRegApis->pfnLocalCreateKey)(hXsaction,
  2626. hkeyClusterKey,
  2627. rvn.PszKeyName(),
  2628. 0,
  2629. KEY_ALL_ACCESS,
  2630. NULL,
  2631. &key,
  2632. &disposition );
  2633. }
  2634. else {
  2635. status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
  2636. rvn.PszKeyName(),
  2637. 0,
  2638. KEY_ALL_ACCESS,
  2639. NULL,
  2640. &key,
  2641. &disposition );
  2642. }
  2643. if ( status != ERROR_SUCCESS ) {
  2644. return(status);
  2645. }
  2646. } else {
  2647. key = hkeyClusterKey;
  2648. }
  2649. //
  2650. // Validate, write, and save the property data.
  2651. //
  2652. switch ( buf.pSyntax->wFormat ) {
  2653. case CLUSPROP_FORMAT_DWORD:
  2654. status = ClRtlpSetDwordProperty(
  2655. hXsaction,
  2656. key,
  2657. pClusterRegApis,
  2658. propertyItem,
  2659. rvn,
  2660. buf.pDwordValue,
  2661. bForceWrite,
  2662. pOutParams );
  2663. break;
  2664. case CLUSPROP_FORMAT_LONG:
  2665. status = ClRtlpSetLongProperty(
  2666. hXsaction,
  2667. key,
  2668. pClusterRegApis,
  2669. propertyItem,
  2670. rvn,
  2671. buf.pLongValue,
  2672. bForceWrite,
  2673. pOutParams );
  2674. break;
  2675. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2676. status = ClRtlpSetULargeIntegerProperty(
  2677. hXsaction,
  2678. key,
  2679. pClusterRegApis,
  2680. propertyItem,
  2681. rvn,
  2682. buf.pULargeIntegerValue,
  2683. bForceWrite,
  2684. pOutParams );
  2685. break;
  2686. case CLUSPROP_FORMAT_LARGE_INTEGER:
  2687. status = ClRtlpSetLargeIntegerProperty(
  2688. hXsaction,
  2689. key,
  2690. pClusterRegApis,
  2691. propertyItem,
  2692. rvn,
  2693. buf.pLargeIntegerValue,
  2694. bForceWrite,
  2695. pOutParams );
  2696. break;
  2697. case CLUSPROP_FORMAT_SZ:
  2698. case CLUSPROP_FORMAT_EXPAND_SZ:
  2699. status = ClRtlpSetStringProperty(
  2700. hXsaction,
  2701. key,
  2702. pClusterRegApis,
  2703. propertyItem,
  2704. rvn,
  2705. buf.pStringValue,
  2706. bForceWrite,
  2707. pOutParams );
  2708. break;
  2709. case CLUSPROP_FORMAT_MULTI_SZ:
  2710. status = ClRtlpSetMultiStringProperty(
  2711. hXsaction,
  2712. key,
  2713. pClusterRegApis,
  2714. propertyItem,
  2715. rvn,
  2716. buf.pStringValue,
  2717. bForceWrite,
  2718. pOutParams );
  2719. break;
  2720. case CLUSPROP_FORMAT_BINARY:
  2721. status = ClRtlpSetBinaryProperty(
  2722. hXsaction,
  2723. key,
  2724. pClusterRegApis,
  2725. propertyItem,
  2726. rvn,
  2727. buf.pBinaryValue,
  2728. bForceWrite,
  2729. pOutParams );
  2730. break;
  2731. default:
  2732. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", pName->sz, buf.pSyntax->wFormat );
  2733. status = ERROR_INVALID_PARAMETER;
  2734. break;
  2735. } // switch: value data format
  2736. //
  2737. // Close the key if we opened it.
  2738. //
  2739. if ( (hkeyClusterKey != NULL) &&
  2740. (rvn.PszKeyName() != NULL) ) {
  2741. (*pClusterRegApis->pfnCloseKey)( key );
  2742. }
  2743. //
  2744. // If an error occurred processing the property, cleanup and return.
  2745. //
  2746. if ( status != ERROR_SUCCESS ) {
  2747. return(status);
  2748. }
  2749. //
  2750. // Move the buffer past the value.
  2751. //
  2752. buf.pb += dataSize;
  2753. inBufferSize -= dataSize;
  2754. break;
  2755. } else {
  2756. propertyItem++;
  2757. //
  2758. // If we reached the end of the list, then return failure
  2759. // if we do not allow unknown properties.
  2760. //
  2761. if ( (propertyItem->Name == NULL) &&
  2762. ! bAllowUnknownProperties ) {
  2763. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' not found.\n", pName->sz );
  2764. return(ERROR_INVALID_PARAMETER);
  2765. }
  2766. }
  2767. }
  2768. //
  2769. // If no property name was found, this is an invalid parameter if
  2770. // we don't allow unknown properties. Otherwise advance past the
  2771. // property value.
  2772. //
  2773. if ( propertyItem->Name == NULL) {
  2774. if ( ! bAllowUnknownProperties ) {
  2775. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPropertyTable: Property '%1!ls!' not found.\n", pName->sz );
  2776. return(ERROR_INVALID_PARAMETER);
  2777. }
  2778. //
  2779. // Advance the buffer pointer past the value in the value list.
  2780. //
  2781. while ( (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  2782. (inBufferSize > 0) ) {
  2783. // ASSERT(inBufferSize > sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength));
  2784. buf.pb += sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength);
  2785. inBufferSize -= sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength);
  2786. } // while: more values in the list
  2787. //
  2788. // Advance the buffer pointer past the value list endmark.
  2789. //
  2790. // ASSERT(inBufferSize >= sizeof(*buf.pSyntax));
  2791. buf.pb += sizeof(*buf.pSyntax); // endmark
  2792. inBufferSize -= sizeof(*buf.pSyntax);
  2793. }
  2794. }
  2795. //
  2796. // Now find any parameters that are not represented in the property
  2797. // table. All of these extra properties will just be set without validation.
  2798. //
  2799. if ( (status == ERROR_SUCCESS) &&
  2800. (pInPropertyList != NULL) &&
  2801. bAllowUnknownProperties ) {
  2802. status = ClRtlpSetNonPropertyTable( hXsaction,
  2803. hkeyClusterKey,
  2804. pClusterRegApis,
  2805. pPropertyTable,
  2806. NULL,
  2807. pInPropertyList,
  2808. cbInPropertyListSize );
  2809. }
  2810. return(status);
  2811. } // ClRtlpSetPropertyTable
  2812. static
  2813. DWORD
  2814. WINAPI
  2815. ClRtlpSetDwordProperty(
  2816. IN HANDLE hXsaction,
  2817. IN PVOID hkey,
  2818. IN const PCLUSTER_REG_APIS pClusterRegApis,
  2819. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  2820. IN const CRegistryValueName & rrvnModifiedNames,
  2821. IN PCLUSPROP_DWORD pInDwordValue,
  2822. IN BOOL bForceWrite,
  2823. IN OUT OPTIONAL LPBYTE pOutParams
  2824. )
  2825. /*++
  2826. Routine Description:
  2827. Validate a DWORD property, write it to the cluster database (or delete it
  2828. if it is zero length), and save it in the specified parameter block.
  2829. Arguments:
  2830. hXsaction - Transaction handle.
  2831. hkey - The opened cluster database key where the property is to be written.
  2832. If not specified, the property will only be validated.
  2833. pClusterRegApis - Supplies a structure of function pointers for accessing
  2834. the cluster database.
  2835. pPropertyItem - The property from a property table to set/validate.
  2836. rrvnModifiedNames - If the name of the property contains a backslash
  2837. this object contains the modified name and keyname.
  2838. pInDwordValue - The value from the property list to set/validate.
  2839. bForceWrite - TRUE = always write the properties to the cluster database.
  2840. FALSE = only write the properties if they changed.
  2841. pOutParams - Parameter block in which to return the data. If specified,
  2842. parameters will only be written if they are different between
  2843. the input data and the parameter block, unless bForceWrite == TRUE.
  2844. Return Value:
  2845. ERROR_SUCCESS if successful.
  2846. ERROR_INVALID_DATA - The format of the data is invalid for a property
  2847. list value.
  2848. A Win32 Error on failure.
  2849. --*/
  2850. {
  2851. DWORD status = ERROR_SUCCESS;
  2852. BOOL bZeroLengthData;
  2853. DWORD * pdwValue;
  2854. // Loop to avoid goto's.
  2855. do
  2856. {
  2857. bZeroLengthData = ( pInDwordValue->cbLength == 0 );
  2858. //
  2859. // Validate the property data if not zero length.
  2860. //
  2861. if ( ! bZeroLengthData ) {
  2862. //
  2863. // Verify the length of the value.
  2864. //
  2865. if ( pInDwordValue->cbLength != sizeof(DWORD) ) {
  2866. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' length %2!d! not DWORD length.\n", rrvnModifiedNames.PszName(), pInDwordValue->cbLength );
  2867. status = ERROR_INVALID_DATA;
  2868. break;
  2869. } // if: data in value not size of DWORD
  2870. //
  2871. // Verify that the value is within the valid range.
  2872. //
  2873. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  2874. && ((LONG) pInDwordValue->dw > (LONG) pPropertyItem->Maximum))
  2875. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  2876. && (pInDwordValue->dw > pPropertyItem->Maximum)) ) {
  2877. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' value %2!u! too large.\n", rrvnModifiedNames.PszName(), pInDwordValue->dw );
  2878. status = ERROR_INVALID_DATA;
  2879. break;
  2880. } // if: value too high
  2881. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  2882. && ((LONG) pInDwordValue->dw < (LONG) pPropertyItem->Minimum))
  2883. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  2884. && (pInDwordValue->dw < pPropertyItem->Minimum)) ) {
  2885. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetDwordProperty: Property '%1!ls!' value %2!u! too small.\n", rrvnModifiedNames.PszName(), pInDwordValue->dw );
  2886. status = ERROR_INVALID_DATA;
  2887. break;
  2888. } // if: value to low
  2889. } // if: non-zero length data
  2890. pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset];
  2891. //
  2892. // Write the value to the cluster database.
  2893. // If the data length is zero, delete the value.
  2894. //
  2895. if ( hkey != NULL ) {
  2896. if ( bZeroLengthData ) {
  2897. if ( hXsaction ) {
  2898. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  2899. hXsaction,
  2900. hkey,
  2901. rrvnModifiedNames.PszName() );
  2902. } else {
  2903. status = (*pClusterRegApis->pfnDeleteValue)(
  2904. hkey,
  2905. rrvnModifiedNames.PszName() );
  2906. } // if/else: doing/not doing a transaction
  2907. //
  2908. // If the property doesn't exist in the
  2909. // cluster database, fix the status.
  2910. //
  2911. if ( status == ERROR_FILE_NOT_FOUND ) {
  2912. status = ERROR_SUCCESS;
  2913. } // if: property already doesn't exist
  2914. } else {
  2915. if ( hXsaction ) {
  2916. status = (*pClusterRegApis->pfnLocalSetValue)(
  2917. hXsaction,
  2918. hkey,
  2919. rrvnModifiedNames.PszName(),
  2920. REG_DWORD,
  2921. (CONST BYTE *) &pInDwordValue->dw,
  2922. sizeof(DWORD) );
  2923. } else {
  2924. status = (*pClusterRegApis->pfnSetValue)(
  2925. hkey,
  2926. rrvnModifiedNames.PszName(),
  2927. REG_DWORD,
  2928. (CONST BYTE *) &pInDwordValue->dw,
  2929. sizeof(DWORD) );
  2930. } // if/else: doing/not doing a transaction
  2931. } // if/else: zero length data
  2932. } // if: writing data
  2933. //
  2934. // Save the value to the output Parameter block.
  2935. // If the data length is zero, set to the default.
  2936. //
  2937. if ( (status == ERROR_SUCCESS)
  2938. && (pOutParams != NULL) ) {
  2939. if ( bZeroLengthData ) {
  2940. *pdwValue = pPropertyItem->Default;
  2941. } else {
  2942. *pdwValue = pInDwordValue->dw;
  2943. } // if/else: zero length data
  2944. } // if: data written successfully and parameter block specified
  2945. } while ( 0 );
  2946. return status;
  2947. } // ClRtlpSetDwordProperty
  2948. static
  2949. DWORD
  2950. WINAPI
  2951. ClRtlpSetLongProperty(
  2952. IN HANDLE hXsaction,
  2953. IN PVOID hkey,
  2954. IN const PCLUSTER_REG_APIS pClusterRegApis,
  2955. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  2956. IN const CRegistryValueName & rrvnModifiedNames,
  2957. IN PCLUSPROP_LONG pInLongValue,
  2958. IN BOOL bForceWrite,
  2959. IN OUT OPTIONAL LPBYTE pOutParams
  2960. )
  2961. /*++
  2962. Routine Description:
  2963. Validate a LONG property, write it to the cluster database (or delete it
  2964. if it is zero length), and save it in the specified parameter block.
  2965. Arguments:
  2966. hXsaction - Transaction handle.
  2967. hkey - The opened cluster database key where the property is to be written.
  2968. If not specified, the property will only be validated.
  2969. pClusterRegApis - Supplies a structure of function pointers for accessing
  2970. the cluster database.
  2971. pPropertyItem - The property from a property table to set/validate.
  2972. rrvnModifiedNames - If the name of the property contains a backslash
  2973. this object contains the modified name and keyname.
  2974. pInLongValue - The value from the property list to set/validate.
  2975. bForceWrite - TRUE = always write the properties to the cluster database.
  2976. FALSE = only write the properties if they changed.
  2977. pOutParams - Parameter block in which to return the data. If specified,
  2978. parameters will only be written if they are different between
  2979. the input data and the parameter block, unless bForceWrite == TRUE.
  2980. Return Value:
  2981. ERROR_SUCCESS if successful.
  2982. ERROR_INVALID_DATA - The format of the data is invalid for a property
  2983. list value.
  2984. A Win32 Error on failure.
  2985. --*/
  2986. {
  2987. DWORD status = ERROR_SUCCESS;
  2988. BOOL bZeroLengthData;
  2989. LONG * plValue;
  2990. // Loop to avoid goto's.
  2991. do
  2992. {
  2993. bZeroLengthData = ( pInLongValue->cbLength == 0 );
  2994. //
  2995. // Validate the property data if not zero length.
  2996. //
  2997. if ( ! bZeroLengthData ) {
  2998. //
  2999. // Verify the length of the value.
  3000. //
  3001. if ( pInLongValue->cbLength != sizeof(LONG) ) {
  3002. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' length %2!d! not LONG length.\n", rrvnModifiedNames.PszName(), pInLongValue->cbLength );
  3003. status = ERROR_INVALID_DATA;
  3004. break;
  3005. } // if: data in value not size of LONG
  3006. //
  3007. // Verify that the value is within the valid range.
  3008. //
  3009. if ( pInLongValue->l > (LONG) pPropertyItem->Maximum ) {
  3010. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' value %2!d! too large.\n", rrvnModifiedNames.PszName(), pInLongValue->l );
  3011. status = ERROR_INVALID_DATA;
  3012. break;
  3013. } // if: value too high
  3014. if ( pInLongValue->l < (LONG) pPropertyItem->Minimum ) {
  3015. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetLongProperty: Property '%1!ls!' value %2!d! too small.\n", rrvnModifiedNames.PszName(), pInLongValue->l );
  3016. status = ERROR_INVALID_DATA;
  3017. break;
  3018. } // if: value too small
  3019. } // if: non-zero length data
  3020. plValue = (LONG *) &pOutParams[pPropertyItem->Offset];
  3021. //
  3022. // Write the value to the cluster database.
  3023. // If the data length is zero, delete the value.
  3024. //
  3025. if ( hkey != NULL ) {
  3026. if ( bZeroLengthData ) {
  3027. if ( hXsaction ) {
  3028. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3029. hXsaction,
  3030. hkey,
  3031. rrvnModifiedNames.PszName() );
  3032. } else {
  3033. status = (*pClusterRegApis->pfnDeleteValue)(
  3034. hkey,
  3035. rrvnModifiedNames.PszName() );
  3036. } // if/else: doing/not doing a transaction
  3037. //
  3038. // If the property doesn't exist in the
  3039. // cluster database, fix the status.
  3040. //
  3041. if ( status == ERROR_FILE_NOT_FOUND ) {
  3042. status = ERROR_SUCCESS;
  3043. } // if: property already doesn't exist
  3044. } else {
  3045. if ( hXsaction ) {
  3046. status = (*pClusterRegApis->pfnLocalSetValue)(
  3047. hXsaction,
  3048. hkey,
  3049. rrvnModifiedNames.PszName(),
  3050. REG_DWORD,
  3051. (CONST BYTE *) &pInLongValue->l,
  3052. sizeof(LONG) );
  3053. } else {
  3054. status = (*pClusterRegApis->pfnSetValue)(
  3055. hkey,
  3056. rrvnModifiedNames.PszName(),
  3057. REG_DWORD,
  3058. (CONST BYTE *) &pInLongValue->l,
  3059. sizeof(LONG) );
  3060. } // if/else: doing/not doing a transaction
  3061. } // if/else: zero length data
  3062. } // if: writing data
  3063. //
  3064. // Save the value to the output Parameter block.
  3065. // If the data length is zero, set to the default.
  3066. //
  3067. if ( (status == ERROR_SUCCESS)
  3068. && (pOutParams != NULL) ) {
  3069. if ( bZeroLengthData ) {
  3070. *plValue = (LONG) pPropertyItem->Default;
  3071. } else {
  3072. *plValue = pInLongValue->l;
  3073. } // if/else: zero length data
  3074. } // if: data written successfully and parameter block specified
  3075. } while ( 0 );
  3076. return status;
  3077. } // ClRtlpSetLongProperty
  3078. static
  3079. DWORD
  3080. WINAPI
  3081. ClRtlpSetULargeIntegerProperty(
  3082. IN HANDLE hXsaction,
  3083. IN PVOID hkey,
  3084. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3085. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  3086. IN const CRegistryValueName & rrvnModifiedNames,
  3087. IN PCLUSPROP_ULARGE_INTEGER pInULargeIntegerValue,
  3088. IN BOOL bForceWrite,
  3089. IN OUT OPTIONAL LPBYTE pOutParams
  3090. )
  3091. /*++
  3092. Routine Description:
  3093. Validate a ULARGE_INTEGER property, write it to the cluster database (or
  3094. delete it if it is zero length), and save it in the specified parameter
  3095. block.
  3096. Arguments:
  3097. hXsaction - Transaction handle.
  3098. hkey - The opened cluster database key where the property is to be written.
  3099. If not specified, the property will only be validated.
  3100. pClusterRegApis - Supplies a structure of function pointers for accessing
  3101. the cluster database.
  3102. pPropertyItem - The property from a property table to set/validate.
  3103. rrvnModifiedNames - If the name of the property contains a backslash
  3104. this object contains the modified name and keyname.
  3105. pInULargeIntegerValue - The value from the property list to set/validate.
  3106. bForceWrite - TRUE = always write the properties to the cluster database.
  3107. FALSE = only write the properties if they changed.
  3108. pOutParams - Parameter block in which to return the data. If specified,
  3109. parameters will only be written if they are different between
  3110. the input data and the parameter block, unless bForceWrite == TRUE.
  3111. Return Value:
  3112. ERROR_SUCCESS if successful.
  3113. ERROR_INVALID_DATA - The format of the data is invalid for a property
  3114. list value.
  3115. A Win32 Error on failure.
  3116. --*/
  3117. {
  3118. DWORD status = ERROR_SUCCESS;
  3119. BOOL bZeroLengthData;
  3120. ULARGE_INTEGER * pullValue;
  3121. // Loop to avoid goto's.
  3122. do
  3123. {
  3124. bZeroLengthData = ( pInULargeIntegerValue->cbLength == 0 );
  3125. //
  3126. // Validate the property data if not zero length.
  3127. //
  3128. if ( ! bZeroLengthData ) {
  3129. //
  3130. // Verify the length of the value.
  3131. //
  3132. if ( pInULargeIntegerValue->cbLength != sizeof(ULARGE_INTEGER) ) {
  3133. ClRtlDbgPrint(LOG_UNUSUAL,
  3134. "ClRtlpSetULargeIntegerProperty: Property '%1!ls!' length %2!d! "
  3135. "not ULARGE_INTEGER length.\n",
  3136. rrvnModifiedNames.PszName(),
  3137. pInULargeIntegerValue->cbLength );
  3138. status = ERROR_INVALID_DATA;
  3139. break;
  3140. } // if: data in value not size of DWORD
  3141. //
  3142. // Verify that the value is within the valid range.
  3143. //
  3144. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3145. && ((LONGLONG)pInULargeIntegerValue->li.QuadPart > (LONGLONG)pPropertyItem->ULargeIntData->Maximum.QuadPart))
  3146. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3147. && (pInULargeIntegerValue->li.QuadPart > pPropertyItem->ULargeIntData->Maximum.QuadPart)) )
  3148. {
  3149. ClRtlDbgPrint(
  3150. LOG_UNUSUAL,
  3151. "ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value %2!I64u! "
  3152. "too large.\n",
  3153. rrvnModifiedNames.PszName(),
  3154. pInULargeIntegerValue->li.QuadPart );
  3155. status = ERROR_INVALID_DATA;
  3156. break;
  3157. } // if: value too high
  3158. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3159. && ((LONGLONG)pInULargeIntegerValue->li.QuadPart < (LONGLONG)pPropertyItem->ULargeIntData->Minimum.QuadPart))
  3160. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3161. && (pInULargeIntegerValue->li.QuadPart < pPropertyItem->ULargeIntData->Minimum.QuadPart)) )
  3162. {
  3163. ClRtlDbgPrint(LOG_UNUSUAL,
  3164. "ClRtlpSetULargeIntegerProperty: Property '%1!ls!' value "
  3165. "%2!I64u! too small.\n",
  3166. rrvnModifiedNames.PszName(),
  3167. pInULargeIntegerValue->li.QuadPart );
  3168. status = ERROR_INVALID_DATA;
  3169. break;
  3170. } // if: value to low
  3171. } // if: non-zero length data
  3172. pullValue = (ULARGE_INTEGER *) &pOutParams[pPropertyItem->Offset];
  3173. //
  3174. // Write the value to the cluster database.
  3175. // If the data length is zero, delete the value.
  3176. //
  3177. if ( hkey != NULL ) {
  3178. if ( bZeroLengthData ) {
  3179. if ( hXsaction ) {
  3180. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3181. hXsaction,
  3182. hkey,
  3183. rrvnModifiedNames.PszName() );
  3184. } else {
  3185. status = (*pClusterRegApis->pfnDeleteValue)(
  3186. hkey,
  3187. rrvnModifiedNames.PszName() );
  3188. } // if/else: doing/not doing a transaction
  3189. //
  3190. // If the property doesn't exist in the
  3191. // cluster database, fix the status.
  3192. //
  3193. if ( status == ERROR_FILE_NOT_FOUND ) {
  3194. status = ERROR_SUCCESS;
  3195. } // if: property already doesn't exist
  3196. } else {
  3197. if ( hXsaction ) {
  3198. status = (*pClusterRegApis->pfnLocalSetValue)(
  3199. hXsaction,
  3200. hkey,
  3201. rrvnModifiedNames.PszName(),
  3202. REG_QWORD,
  3203. (CONST BYTE *) &pInULargeIntegerValue->li.QuadPart,
  3204. sizeof(ULARGE_INTEGER) );
  3205. } else {
  3206. status = (*pClusterRegApis->pfnSetValue)(
  3207. hkey,
  3208. rrvnModifiedNames.PszName(),
  3209. REG_QWORD,
  3210. (CONST BYTE *) &pInULargeIntegerValue->li.QuadPart,
  3211. sizeof(ULARGE_INTEGER) );
  3212. } // if/else: doing/not doing a transaction
  3213. } // if/else: zero length data
  3214. } // if: writing data
  3215. //
  3216. // Save the value to the output Parameter block.
  3217. // If the data length is zero, set to the default.
  3218. //
  3219. if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
  3220. if ( bZeroLengthData ) {
  3221. pullValue->u = pPropertyItem->ULargeIntData->Default.u;
  3222. } else {
  3223. pullValue->u = pInULargeIntegerValue->li.u;
  3224. } // if/else: zero length data
  3225. } // if: data written successfully and parameter block specified
  3226. } while ( 0 );
  3227. return status;
  3228. } // ClRtlpSetULargeIntegerProperty
  3229. static
  3230. DWORD
  3231. WINAPI
  3232. ClRtlpSetLargeIntegerProperty(
  3233. IN HANDLE hXsaction,
  3234. IN PVOID hkey,
  3235. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3236. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  3237. IN const CRegistryValueName & rrvnModifiedNames,
  3238. IN PCLUSPROP_LARGE_INTEGER pInLargeIntegerValue,
  3239. IN BOOL bForceWrite,
  3240. IN OUT OPTIONAL LPBYTE pOutParams
  3241. )
  3242. /*++
  3243. Routine Description:
  3244. Validate a LARGE_INTEGER property, write it to the cluster database (or
  3245. delete it if it is zero length), and save it in the specified parameter
  3246. block.
  3247. Arguments:
  3248. hXsaction - Transaction handle.
  3249. hkey - The opened cluster database key where the property is to be written.
  3250. If not specified, the property will only be validated.
  3251. pClusterRegApis - Supplies a structure of function pointers for accessing
  3252. the cluster database.
  3253. pPropertyItem - The property from a property table to set/validate.
  3254. rrvnModifiedNames - If the name of the property contains a backslash
  3255. this object contains the modified name and keyname.
  3256. pInLargeIntegerValue - The value from the property list to set/validate.
  3257. bForceWrite - TRUE = always write the properties to the cluster database.
  3258. FALSE = only write the properties if they changed.
  3259. pOutParams - Parameter block in which to return the data. If specified,
  3260. parameters will only be written if they are different between
  3261. the input data and the parameter block, unless bForceWrite == TRUE.
  3262. Return Value:
  3263. ERROR_SUCCESS if successful.
  3264. ERROR_INVALID_DATA - The format of the data is invalid for a property
  3265. list value.
  3266. A Win32 Error on failure.
  3267. --*/
  3268. {
  3269. DWORD status = ERROR_SUCCESS;
  3270. BOOL bZeroLengthData;
  3271. LARGE_INTEGER * pllValue;
  3272. // Loop to avoid goto's.
  3273. do
  3274. {
  3275. bZeroLengthData = ( pInLargeIntegerValue->cbLength == 0 );
  3276. //
  3277. // Validate the property data if not zero length.
  3278. //
  3279. if ( ! bZeroLengthData ) {
  3280. //
  3281. // Verify the length of the value.
  3282. //
  3283. if ( pInLargeIntegerValue->cbLength != sizeof(LARGE_INTEGER) ) {
  3284. ClRtlDbgPrint(LOG_UNUSUAL,
  3285. "ClRtlpSetLargeIntegerProperty: Property '%1!ls!' length %2!d! "
  3286. "not LARGE_INTEGER length.\n",
  3287. rrvnModifiedNames.PszName(),
  3288. pInLargeIntegerValue->cbLength );
  3289. status = ERROR_INVALID_DATA;
  3290. break;
  3291. } // if: data in value not size of DWORD
  3292. //
  3293. // Verify that the value is within the valid range.
  3294. //
  3295. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3296. && ((LONGLONG)pInLargeIntegerValue->li.QuadPart > (LONGLONG)pPropertyItem->LargeIntData->Maximum.QuadPart))
  3297. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3298. && (pInLargeIntegerValue->li.QuadPart > pPropertyItem->LargeIntData->Maximum.QuadPart)) )
  3299. {
  3300. ClRtlDbgPrint(LOG_UNUSUAL,
  3301. "ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value %2!I64d! "
  3302. "too large.\n",
  3303. rrvnModifiedNames.PszName(),
  3304. pInLargeIntegerValue->li.QuadPart );
  3305. status = ERROR_INVALID_DATA;
  3306. break;
  3307. } // if: value too high
  3308. if ( ( (pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3309. && ((LONGLONG)pInLargeIntegerValue->li.QuadPart < (LONGLONG)pPropertyItem->LargeIntData->Minimum.QuadPart))
  3310. || ( !(pPropertyItem->Flags & RESUTIL_PROPITEM_SIGNED)
  3311. && (pInLargeIntegerValue->li.QuadPart < pPropertyItem->LargeIntData->Minimum.QuadPart)) )
  3312. {
  3313. ClRtlDbgPrint(LOG_UNUSUAL,
  3314. "ClRtlpSetLargeIntegerProperty: Property '%1!ls!' value "
  3315. "%2!I64d! too small.\n",
  3316. rrvnModifiedNames.PszName(),
  3317. pInLargeIntegerValue->li.QuadPart );
  3318. status = ERROR_INVALID_DATA;
  3319. break;
  3320. } // if: value to low
  3321. } // if: non-zero length data
  3322. pllValue = (LARGE_INTEGER *) &pOutParams[pPropertyItem->Offset];
  3323. //
  3324. // Write the value to the cluster database.
  3325. // If the data length is zero, delete the value.
  3326. //
  3327. if ( hkey != NULL ) {
  3328. if ( bZeroLengthData ) {
  3329. if ( hXsaction ) {
  3330. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3331. hXsaction,
  3332. hkey,
  3333. rrvnModifiedNames.PszName() );
  3334. } else {
  3335. status = (*pClusterRegApis->pfnDeleteValue)(
  3336. hkey,
  3337. rrvnModifiedNames.PszName() );
  3338. } // if/else: doing/not doing a transaction
  3339. //
  3340. // If the property doesn't exist in the
  3341. // cluster database, fix the status.
  3342. //
  3343. if ( status == ERROR_FILE_NOT_FOUND ) {
  3344. status = ERROR_SUCCESS;
  3345. } // if: property already doesn't exist
  3346. } else {
  3347. if ( hXsaction ) {
  3348. status = (*pClusterRegApis->pfnLocalSetValue)(
  3349. hXsaction,
  3350. hkey,
  3351. rrvnModifiedNames.PszName(),
  3352. REG_QWORD,
  3353. (CONST BYTE *) &pInLargeIntegerValue->li.QuadPart,
  3354. sizeof(LARGE_INTEGER) );
  3355. } else {
  3356. status = (*pClusterRegApis->pfnSetValue)(
  3357. hkey,
  3358. rrvnModifiedNames.PszName(),
  3359. REG_QWORD,
  3360. (CONST BYTE *) &pInLargeIntegerValue->li.QuadPart,
  3361. sizeof(LARGE_INTEGER) );
  3362. } // if/else: doing/not doing a transaction
  3363. } // if/else: zero length data
  3364. } // if: writing data
  3365. //
  3366. // Save the value to the output Parameter block.
  3367. // If the data length is zero, set to the default.
  3368. //
  3369. if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
  3370. if ( bZeroLengthData ) {
  3371. pllValue->u = pPropertyItem->LargeIntData->Default.u;
  3372. } else {
  3373. pllValue->u = pInLargeIntegerValue->li.u;
  3374. } // if/else: zero length data
  3375. } // if: data written successfully and parameter block specified
  3376. } while ( 0 );
  3377. return status;
  3378. } // ClRtlpSetLargeIntegerProperty
  3379. static
  3380. DWORD
  3381. WINAPI
  3382. ClRtlpSetStringProperty(
  3383. IN HANDLE hXsaction,
  3384. IN PVOID hkey,
  3385. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3386. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  3387. IN const CRegistryValueName & rrvnModifiedNames,
  3388. IN PCLUSPROP_SZ pInStringValue,
  3389. IN BOOL bForceWrite,
  3390. IN OUT OPTIONAL LPBYTE pOutParams
  3391. )
  3392. /*++
  3393. Routine Description:
  3394. Validate a string property (SZ or EXPAND_SZ), write it to the cluster
  3395. database (or delete it if it is zero length), and save it in the
  3396. specified parameter block.
  3397. Arguments:
  3398. hXsaction - Transaction handle.
  3399. hkey - The opened cluster database key where the property is to be written.
  3400. If not specified, the property will only be validated.
  3401. pClusterRegApis - Supplies a structure of function pointers for accessing
  3402. the cluster database.
  3403. pPropertyItem - The property from a property table to set/validate.
  3404. rrvnModifiedNames - If the name of the property contains a backslash
  3405. this object contains the modified name and keyname.
  3406. pInStringValue - The value from the property list to set/validate.
  3407. bForceWrite - TRUE = always write the properties to the cluster database.
  3408. FALSE = only write the properties if they changed.
  3409. pOutParams - Parameter block in which to return the data. If specified,
  3410. parameters will only be written if they are different between
  3411. the input data and the parameter block, unless bForceWrite == TRUE.
  3412. Return Value:
  3413. ERROR_SUCCESS if successful.
  3414. ERROR_INVALID_DATA - The format of the data is invalid for a property
  3415. list value.
  3416. A Win32 Error on failure.
  3417. --*/
  3418. {
  3419. DWORD status = ERROR_SUCCESS;
  3420. BOOL bZeroLengthData;
  3421. LPWSTR UNALIGNED * ppszValue;
  3422. DWORD dwType;
  3423. // Loop to avoid goto's.
  3424. do
  3425. {
  3426. bZeroLengthData = ( pInStringValue->cbLength == 0 );
  3427. //
  3428. // Validate the property data if not zero length.
  3429. //
  3430. if ( ! bZeroLengthData ) {
  3431. //
  3432. // Verify the length of the value.
  3433. //
  3434. if ( pInStringValue->cbLength != (lstrlenW( pInStringValue->sz ) + 1) * sizeof(WCHAR) ) {
  3435. ClRtlDbgPrint( LOG_UNUSUAL, "ClRtlpSetStringProperty: Property '%1!ls!' length %2!d! doesn't match zero-term. length.\n", rrvnModifiedNames.PszName(), pInStringValue->cbLength );
  3436. status = ERROR_INVALID_DATA;
  3437. break;
  3438. } // if: string length doesn't match length in property
  3439. } // if: non-zero length data
  3440. ppszValue = (LPWSTR UNALIGNED *) &pOutParams[pPropertyItem->Offset];
  3441. //
  3442. // If the data changed, write it and save it.
  3443. // Do this even if only the case of the data changed.
  3444. //
  3445. if ( (pOutParams == NULL)
  3446. || (*ppszValue == NULL)
  3447. || bZeroLengthData
  3448. || bForceWrite
  3449. || (lstrcmpW( *ppszValue, pInStringValue->sz ) != 0) ) {
  3450. //
  3451. // Write the value to the cluster database.
  3452. // If the data length is zero, delete the value.
  3453. //
  3454. if ( hkey != NULL ) {
  3455. if ( bZeroLengthData ) {
  3456. if ( hXsaction ) {
  3457. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3458. hXsaction,
  3459. hkey,
  3460. rrvnModifiedNames.PszName() );
  3461. } else {
  3462. status = (*pClusterRegApis->pfnDeleteValue)(
  3463. hkey,
  3464. rrvnModifiedNames.PszName() );
  3465. } // if/else: doing/not doing a transaction
  3466. //
  3467. // If the property doesn't exist in the
  3468. // cluster database, fix the status.
  3469. //
  3470. if ( status == ERROR_FILE_NOT_FOUND ) {
  3471. status = ERROR_SUCCESS;
  3472. } // if: property already doesn't exist
  3473. } else {
  3474. if ( pPropertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ ) {
  3475. dwType = REG_EXPAND_SZ;
  3476. } else {
  3477. dwType = REG_SZ;
  3478. } // if/else: property format is EXPAND_SZ
  3479. if ( hXsaction ) {
  3480. status = (*pClusterRegApis->pfnLocalSetValue)(
  3481. hXsaction,
  3482. hkey,
  3483. rrvnModifiedNames.PszName(),
  3484. dwType,
  3485. (CONST BYTE *) &pInStringValue->sz,
  3486. pInStringValue->cbLength );
  3487. } else {
  3488. status = (*pClusterRegApis->pfnSetValue)(
  3489. hkey,
  3490. rrvnModifiedNames.PszName(),
  3491. dwType,
  3492. (CONST BYTE *) &pInStringValue->sz,
  3493. pInStringValue->cbLength );
  3494. } // if/else: doing/not doing a transaction
  3495. } // if/else: zero length data
  3496. } // if: writing data
  3497. //
  3498. // Save the value to the output Parameter block.
  3499. // If the data length is zero, set to the default.
  3500. //
  3501. if ( (status == ERROR_SUCCESS)
  3502. && (pOutParams != NULL) ) {
  3503. if ( *ppszValue != NULL ) {
  3504. LocalFree( *ppszValue );
  3505. } // if: previous value in parameter block
  3506. if ( bZeroLengthData ) {
  3507. // If a default is specified, copy it.
  3508. if ( pPropertyItem->lpDefault != NULL ) {
  3509. *ppszValue = (LPWSTR) LocalAlloc(
  3510. LMEM_FIXED,
  3511. (lstrlenW( (LPCWSTR) pPropertyItem->lpDefault ) + 1) * sizeof(WCHAR)
  3512. );
  3513. if ( *ppszValue == NULL ) {
  3514. status = GetLastError();
  3515. ClRtlDbgPrint(
  3516. LOG_CRITICAL,
  3517. "ClRtlpSetStringProperty: error allocating memory for default "
  3518. "SZ value '%1!ls!' in parameter block for property '%2!ls!'.\n",
  3519. pPropertyItem->lpDefault,
  3520. rrvnModifiedNames.PszName() );
  3521. break;
  3522. } // if: error allocating memory
  3523. lstrcpyW( *ppszValue, (LPCWSTR) pPropertyItem->lpDefault );
  3524. } else {
  3525. *ppszValue = NULL;
  3526. } // if/else: default value specified
  3527. } else {
  3528. *ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pInStringValue->cbLength );
  3529. if ( *ppszValue == NULL ) {
  3530. status = GetLastError();
  3531. ClRtlDbgPrint(
  3532. LOG_CRITICAL,
  3533. "ClRtlpSetStringProperty: error allocating memory for SZ "
  3534. "value '%1!ls!' in parameter block for property '%2!ls!'.\n",
  3535. pInStringValue->cbLength,
  3536. rrvnModifiedNames.PszName() );
  3537. break;
  3538. } // if: error allocating memory
  3539. lstrcpyW( *ppszValue, pInStringValue->sz );
  3540. } // if/else: zero length data
  3541. } // if: data written successfully and parameter block specified
  3542. } // if: value changed or zero-length value
  3543. } while ( 0 );
  3544. return status;
  3545. } // ClRtlpSetStringProperty
  3546. static
  3547. DWORD
  3548. WINAPI
  3549. ClRtlpSetMultiStringProperty(
  3550. IN HANDLE hXsaction,
  3551. IN PVOID hkey,
  3552. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3553. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  3554. IN const CRegistryValueName & rrvnModifiedNames,
  3555. IN PCLUSPROP_MULTI_SZ pInMultiStringValue,
  3556. IN BOOL bForceWrite,
  3557. IN OUT OPTIONAL LPBYTE pOutParams
  3558. )
  3559. /*++
  3560. Routine Description:
  3561. Validate a MULTI_SZ property, write it to the cluster database (or delete
  3562. it if it is zero length), and save it in the specified parameter block.
  3563. Arguments:
  3564. hXsaction - Transaction handle.
  3565. hkey - The opened cluster database key where the property is to be written.
  3566. If not specified, the property will only be validated.
  3567. pClusterRegApis - Supplies a structure of function pointers for accessing
  3568. the cluster database.
  3569. pPropertyItem - The property from a property table to set/validate.
  3570. rrvnModifiedNames - If the name of the property contains a backslash
  3571. this object contains the modified name and keyname.
  3572. pInMultiStringValue - The value from the property list to set/validate.
  3573. bForceWrite - TRUE = always write the properties to the cluster database.
  3574. FALSE = only write the properties if they changed.
  3575. pOutParams - Parameter block in which to return the data. If specified,
  3576. parameters will only be written if they are different between
  3577. the input data and the parameter block, unless bForceWrite == TRUE.
  3578. Return Value:
  3579. ERROR_SUCCESS if successful.
  3580. ERROR_INVALID_DATA - The format of the data is invalid for a property
  3581. list value.
  3582. A Win32 Error on failure.
  3583. --*/
  3584. {
  3585. DWORD status = ERROR_SUCCESS;
  3586. BOOL bZeroLengthData;
  3587. LPWSTR UNALIGNED * ppszValue;
  3588. DWORD * pdwValue;
  3589. DWORD dwType;
  3590. // Loop to avoid goto's.
  3591. do
  3592. {
  3593. bZeroLengthData = ( pInMultiStringValue->cbLength == 0 );
  3594. ppszValue = (LPWSTR UNALIGNED *) &pOutParams[pPropertyItem->Offset];
  3595. pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset + sizeof(LPWSTR *)];
  3596. //
  3597. // If the data changed, write it and save it.
  3598. // Do this even if only the case of the data changed.
  3599. //
  3600. if ( (pOutParams == NULL)
  3601. || (*ppszValue == NULL)
  3602. || (*pdwValue != pInMultiStringValue->cbLength)
  3603. || bZeroLengthData
  3604. || bForceWrite
  3605. || (memcmp( *ppszValue, pInMultiStringValue->sz, *pdwValue ) != 0) ) {
  3606. //
  3607. // Write the value to the cluster database.
  3608. // If the data length is zero, delete the value.
  3609. //
  3610. if ( hkey != NULL ) {
  3611. if ( bZeroLengthData ) {
  3612. if ( hXsaction ) {
  3613. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3614. hXsaction,
  3615. hkey,
  3616. rrvnModifiedNames.PszName() );
  3617. } else {
  3618. status = (*pClusterRegApis->pfnDeleteValue)(
  3619. hkey,
  3620. rrvnModifiedNames.PszName() );
  3621. } // if/else: doing/not doing a transaction
  3622. //
  3623. // If the property doesn't exist in the
  3624. // cluster database, fix the status.
  3625. //
  3626. if ( status == ERROR_FILE_NOT_FOUND ) {
  3627. status = ERROR_SUCCESS;
  3628. } // if: property already doesn't exist
  3629. } else {
  3630. if ( pPropertyItem->Format == CLUSPROP_FORMAT_MULTI_SZ ) {
  3631. dwType = REG_MULTI_SZ;
  3632. } else {
  3633. dwType = REG_SZ;
  3634. } // if/else: property format is EXPAND_SZ
  3635. if ( hXsaction ) {
  3636. status = (*pClusterRegApis->pfnLocalSetValue)(
  3637. hXsaction,
  3638. hkey,
  3639. rrvnModifiedNames.PszName(),
  3640. dwType,
  3641. (CONST BYTE *) &pInMultiStringValue->sz,
  3642. pInMultiStringValue->cbLength );
  3643. } else {
  3644. status = (*pClusterRegApis->pfnSetValue)(
  3645. hkey,
  3646. rrvnModifiedNames.PszName(),
  3647. dwType,
  3648. (CONST BYTE *) &pInMultiStringValue->sz,
  3649. pInMultiStringValue->cbLength );
  3650. } // if/else: doing/not doing a transaction
  3651. } // if/else: zero length data
  3652. } // if: writing data
  3653. //
  3654. // Save the value to the output Parameter block.
  3655. // If the data length is zero, set to the default.
  3656. //
  3657. if ( (status == ERROR_SUCCESS)
  3658. && (pOutParams != NULL) ) {
  3659. if ( *ppszValue != NULL ) {
  3660. LocalFree( *ppszValue );
  3661. } // if: previous value in parameter block
  3662. if ( bZeroLengthData ) {
  3663. // If a default is specified, copy it.
  3664. if ( pPropertyItem->lpDefault != NULL ) {
  3665. *ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pPropertyItem->Minimum );
  3666. if ( *ppszValue == NULL ) {
  3667. status = GetLastError();
  3668. *pdwValue = 0;
  3669. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetMultiStringProperty: error allocating memory for default MULTI_SZ value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
  3670. break;
  3671. } // if: error allocating memory
  3672. CopyMemory( *ppszValue, pPropertyItem->lpDefault, pPropertyItem->Minimum );
  3673. *pdwValue = pPropertyItem->Minimum;
  3674. } else {
  3675. *ppszValue = NULL;
  3676. *pdwValue = 0;
  3677. } // if/else: default value specified
  3678. } else {
  3679. *ppszValue = (LPWSTR) LocalAlloc( LMEM_FIXED, pInMultiStringValue->cbLength );
  3680. if ( *ppszValue == NULL ) {
  3681. status = GetLastError();
  3682. *pdwValue = 0;
  3683. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetMultiStringProperty: error allocating memory for MULTI_SZ value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
  3684. break;
  3685. } // if: error allocating memory
  3686. CopyMemory( *ppszValue, pInMultiStringValue->sz, pInMultiStringValue->cbLength );
  3687. *pdwValue = pInMultiStringValue->cbLength;
  3688. } // if/else: zero length data
  3689. } // if: data written successfully and parameter block specified
  3690. } // if: value changed or zero-length value
  3691. } while ( 0 );
  3692. return status;
  3693. } // ClRtlpSetMultiStringProperty
  3694. static
  3695. DWORD
  3696. WINAPI
  3697. ClRtlpSetBinaryProperty(
  3698. IN HANDLE hXsaction,
  3699. IN PVOID hkey,
  3700. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3701. IN const PRESUTIL_PROPERTY_ITEM pPropertyItem,
  3702. IN const CRegistryValueName & rrvnModifiedNames,
  3703. IN PCLUSPROP_BINARY pInBinaryValue,
  3704. IN BOOL bForceWrite,
  3705. IN OUT OPTIONAL LPBYTE pOutParams
  3706. )
  3707. /*++
  3708. Routine Description:
  3709. Validate a BINARY property, write it to the cluster database (or delete
  3710. it if it is zero length), and save it in the specified parameter block.
  3711. Arguments:
  3712. hXsaction - Transaction handle.
  3713. hkey - The opened cluster database key where the property is to be written.
  3714. If not specified, the property will only be validated.
  3715. pClusterRegApis - Supplies a structure of function pointers for accessing
  3716. the cluster database.
  3717. pPropertyItem - The property from a property table to set/validate.
  3718. rrvnModifiedNames - If the name of the property contains a backslash
  3719. this object contains the modified name and keyname.
  3720. pInBinaryValue - The value from the property list to set/validate.
  3721. bForceWrite - TRUE = always write the properties to the cluster database.
  3722. FALSE = only write the properties if they changed.
  3723. pOutParams - Parameter block in which to return the data. If specified,
  3724. parameters will only be written if they are different between
  3725. the input data and the parameter block, unless bForceWrite == TRUE.
  3726. Return Value:
  3727. ERROR_SUCCESS if successful.
  3728. ERROR_INVALID_DATA - The format of the data is invalid for a property
  3729. list value.
  3730. A Win32 Error on failure.
  3731. --*/
  3732. {
  3733. DWORD status = ERROR_SUCCESS;
  3734. BOOL bZeroLengthData;
  3735. PBYTE UNALIGNED * ppbValue;
  3736. DWORD * pdwValue;
  3737. // Loop to avoid goto's.
  3738. do
  3739. {
  3740. bZeroLengthData = ( pInBinaryValue->cbLength == 0 );
  3741. ppbValue = (PBYTE UNALIGNED *) &pOutParams[pPropertyItem->Offset];
  3742. pdwValue = (DWORD *) &pOutParams[pPropertyItem->Offset + sizeof(PBYTE *)];
  3743. //
  3744. // If the data changed, write it and save it.
  3745. // Do this even if only the case of the data changed.
  3746. //
  3747. if ( (pOutParams == NULL)
  3748. || (*ppbValue == NULL)
  3749. || (*pdwValue != pInBinaryValue->cbLength)
  3750. || bZeroLengthData
  3751. || bForceWrite
  3752. || (memcmp( *ppbValue, pInBinaryValue->rgb, *pdwValue ) != 0) ) {
  3753. //
  3754. // Write the value to the cluster database.
  3755. // If the data length is zero, delete the value.
  3756. //
  3757. if ( hkey != NULL ) {
  3758. if ( bZeroLengthData ) {
  3759. if ( hXsaction ) {
  3760. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  3761. hXsaction,
  3762. hkey,
  3763. rrvnModifiedNames.PszName() );
  3764. } else {
  3765. status = (*pClusterRegApis->pfnDeleteValue)(
  3766. hkey,
  3767. rrvnModifiedNames.PszName() );
  3768. } // if/else: doing/not doing a transaction
  3769. //
  3770. // If the property doesn't exist in the
  3771. // cluster database, fix the status.
  3772. //
  3773. if ( status == ERROR_FILE_NOT_FOUND ) {
  3774. status = ERROR_SUCCESS;
  3775. } // if: property already doesn't exist
  3776. } else {
  3777. if ( hXsaction ) {
  3778. status = (*pClusterRegApis->pfnLocalSetValue)(
  3779. hXsaction,
  3780. hkey,
  3781. rrvnModifiedNames.PszName(),
  3782. REG_BINARY,
  3783. (CONST BYTE *) &pInBinaryValue->rgb,
  3784. pInBinaryValue->cbLength );
  3785. } else {
  3786. status = (*pClusterRegApis->pfnSetValue)(
  3787. hkey,
  3788. rrvnModifiedNames.PszName(),
  3789. REG_BINARY,
  3790. (CONST BYTE *) &pInBinaryValue->rgb,
  3791. pInBinaryValue->cbLength );
  3792. } // if/else: doing/not doing a transaction
  3793. } // if/else: zero length data
  3794. } // if: writing data
  3795. //
  3796. // Save the value to the output Parameter block.
  3797. // If the data length is zero, set to the default.
  3798. //
  3799. if ( (status == ERROR_SUCCESS)
  3800. && (pOutParams != NULL) ) {
  3801. if ( *ppbValue != NULL ) {
  3802. LocalFree( *ppbValue );
  3803. } // if: previous value in parameter block
  3804. if ( bZeroLengthData ) {
  3805. // If a default is specified, copy it.
  3806. if ( pPropertyItem->lpDefault != NULL ) {
  3807. *ppbValue = (LPBYTE) LocalAlloc( LMEM_FIXED, pPropertyItem->Minimum );
  3808. if ( *ppbValue == NULL ) {
  3809. status = GetLastError();
  3810. *pdwValue = 0;
  3811. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetBinaryProperty: error allocating memory for default BINARY value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
  3812. break;
  3813. } // if: error allocating memory
  3814. CopyMemory( *ppbValue, pPropertyItem->lpDefault, pPropertyItem->Minimum );
  3815. *pdwValue = pPropertyItem->Minimum;
  3816. } else {
  3817. *ppbValue = NULL;
  3818. *pdwValue = 0;
  3819. } // if/else: default value specified
  3820. } else {
  3821. *ppbValue = (LPBYTE) LocalAlloc( LMEM_FIXED, pInBinaryValue->cbLength );
  3822. if ( *ppbValue == NULL ) {
  3823. status = GetLastError();
  3824. *pdwValue = 0;
  3825. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetBinaryProperty: error allocating memory for BINARY value in parameter block for property '%1!ls!'.\n", rrvnModifiedNames.PszName() );
  3826. break;
  3827. } // if: error allocating memory
  3828. CopyMemory( *ppbValue, pInBinaryValue->rgb, pInBinaryValue->cbLength );
  3829. *pdwValue = pInBinaryValue->cbLength;
  3830. } // if/else: zero length data
  3831. } // if: data written successfully and parameter block specified
  3832. } // if: value changed or zero-length value
  3833. } while ( 0 );
  3834. return status;
  3835. } // ClRtlpSetBinaryProperty
  3836. DWORD
  3837. WINAPI
  3838. ClRtlpSetNonPropertyTable(
  3839. IN HANDLE hXsaction,
  3840. IN PVOID hkeyClusterKey,
  3841. IN const PCLUSTER_REG_APIS pClusterRegApis,
  3842. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  3843. IN PVOID Reserved,
  3844. IN const PVOID pInPropertyList,
  3845. IN DWORD cbInPropertyListSize
  3846. )
  3847. /*++
  3848. Routine Description:
  3849. Set items that are not in the property table list.
  3850. Arguments:
  3851. hXsaction - Local Transaction handle.
  3852. hkeyClusterKey - The opened registry key for this object's parameters.
  3853. If not specified, the property list will only be validated.
  3854. pClusterRegApis - Supplies a structure of function pointers for accessing
  3855. the cluster database.
  3856. pPropertyTable - Pointer to the property table to process.
  3857. pInPropertyList - The input buffer.
  3858. cbInPropertyListSize - The input buffer size.
  3859. Return Value:
  3860. ERROR_SUCCESS if successful.
  3861. A Win32 Error on failure.
  3862. --*/
  3863. {
  3864. DWORD status = ERROR_SUCCESS;
  3865. PRESUTIL_PROPERTY_ITEM propertyItem;
  3866. DWORD inBufferSize;
  3867. DWORD itemCount;
  3868. DWORD dataSize;
  3869. CLUSPROP_BUFFER_HELPER buf;
  3870. PCLUSPROP_PROPERTY_NAME pName;
  3871. BOOL bZeroLengthData;
  3872. CRegistryValueName rvn;
  3873. //
  3874. // If hKeyClusterKey is present then 'normal' functions must be present.
  3875. //
  3876. if ( ( (hkeyClusterKey != NULL) &&
  3877. ((pClusterRegApis->pfnSetValue == NULL) ||
  3878. (pClusterRegApis->pfnCreateKey == NULL) ||
  3879. (pClusterRegApis->pfnOpenKey == NULL) ||
  3880. (pClusterRegApis->pfnCloseKey == NULL)
  3881. )) ||
  3882. ( pPropertyTable == NULL ) ) {
  3883. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pClusterRegApis->pfnSetValue, pfnCreateKey, pfnOpenKey, or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  3884. return(ERROR_BAD_ARGUMENTS);
  3885. }
  3886. //
  3887. // If hKeyClusterKey and hXsaction are present
  3888. // then 'local' functions must be present.
  3889. //
  3890. if ( ((hkeyClusterKey != NULL) &&
  3891. (hXsaction != NULL )) &&
  3892. ((pClusterRegApis->pfnLocalCreateKey == NULL) ||
  3893. (pClusterRegApis->pfnLocalDeleteValue == NULL)
  3894. ) ) {
  3895. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pClusterRegApis->pfnpfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  3896. return(ERROR_BAD_ARGUMENTS);
  3897. }
  3898. if ( pInPropertyList == NULL ) {
  3899. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
  3900. return(ERROR_INVALID_DATA);
  3901. }
  3902. buf.pb = (LPBYTE) pInPropertyList;
  3903. inBufferSize = cbInPropertyListSize;
  3904. //
  3905. // Get the number of items in this list
  3906. //
  3907. if ( inBufferSize < sizeof(DWORD) ) {
  3908. return(ERROR_INSUFFICIENT_BUFFER);
  3909. }
  3910. itemCount = buf.pList->nPropertyCount;
  3911. buf.pdw++;
  3912. //
  3913. // Parse the rest of the items in the buffer.
  3914. //
  3915. while ( itemCount-- ) {
  3916. //
  3917. // Verify that the buffer is big enough to contain the
  3918. // property name and a value.
  3919. //
  3920. pName = buf.pName;
  3921. if ( inBufferSize < sizeof(*pName) ) {
  3922. return(ERROR_INSUFFICIENT_BUFFER);
  3923. }
  3924. dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
  3925. if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
  3926. return(ERROR_INSUFFICIENT_BUFFER);
  3927. }
  3928. //
  3929. // Verify that the syntax of the property name is correct.
  3930. //
  3931. if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
  3932. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: syntax %1!d! not a name syntax.\n", pName->Syntax.dw );
  3933. return(ERROR_INVALID_PARAMETER);
  3934. }
  3935. //
  3936. // Verify that the length is correct for the string.
  3937. //
  3938. if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
  3939. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: name is not a valid C string.\n" );
  3940. return(ERROR_INVALID_DATA);
  3941. }
  3942. //
  3943. // Move the buffer pointer to the property value.
  3944. //
  3945. buf.pb += dataSize;
  3946. inBufferSize -= dataSize;
  3947. //
  3948. // Find the property name in the list of known properties.
  3949. //
  3950. propertyItem = pPropertyTable;
  3951. while ( propertyItem->Name != NULL ) {
  3952. if ( lstrcmpiW( pName->sz, propertyItem->Name ) == 0 ) {
  3953. //
  3954. // Verify that the buffer is big enough to contain the value.
  3955. //
  3956. do {
  3957. dataSize = sizeof(*buf.pValue)
  3958. + ALIGN_CLUSPROP( buf.pValue->cbLength );
  3959. if ( inBufferSize < dataSize ) {
  3960. return(ERROR_INSUFFICIENT_BUFFER);
  3961. }
  3962. //
  3963. // Skip this value.
  3964. //
  3965. buf.pb += dataSize;
  3966. inBufferSize -= dataSize;
  3967. } while ( buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
  3968. //
  3969. // Skip the endmark.
  3970. //
  3971. dataSize = sizeof( CLUSPROP_SYNTAX );
  3972. if ( inBufferSize < dataSize ) {
  3973. return(ERROR_INSUFFICIENT_BUFFER);
  3974. }
  3975. buf.pb += dataSize;
  3976. inBufferSize -= dataSize;
  3977. break;
  3978. } else {
  3979. propertyItem++;
  3980. }
  3981. }
  3982. //
  3983. // If no property name was found, just save this item.
  3984. //
  3985. if ( propertyItem->Name == NULL) {
  3986. //
  3987. // Verify that the buffer is big enough to contain the value.
  3988. //
  3989. dataSize = sizeof(*buf.pValue)
  3990. + ALIGN_CLUSPROP( buf.pValue->cbLength );
  3991. if ( inBufferSize < dataSize + sizeof( CLUSPROP_SYNTAX ) ) {
  3992. return(ERROR_INSUFFICIENT_BUFFER);
  3993. }
  3994. //
  3995. // Verify that the syntax type is LIST_VALUE.
  3996. //
  3997. if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
  3998. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' type CLUSPROP_TYPE_LIST_VALUE (%2!d!) expected, was %3!d!.\n", pName->sz, CLUSPROP_TYPE_LIST_VALUE, buf.pSyntax->wType );
  3999. return(ERROR_INVALID_PARAMETER);
  4000. }
  4001. //
  4002. // If the value is not specified, delete the property.
  4003. //
  4004. bZeroLengthData = ( buf.pValue->cbLength == 0 );
  4005. if ( bZeroLengthData ) {
  4006. if ( hkeyClusterKey != NULL ) {
  4007. PVOID key = NULL;
  4008. DWORD disposition;
  4009. //
  4010. // Use the wrapper class CRegistryValueName to parse value name to see if it
  4011. // contains a backslash.
  4012. //
  4013. status = rvn.ScInit( pName->sz, NULL );
  4014. if ( status != ERROR_SUCCESS ) {
  4015. break;
  4016. }
  4017. //
  4018. // If the value resides at a different location, open the key.
  4019. //
  4020. if ( rvn.PszKeyName() != NULL ) {
  4021. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  4022. rvn.PszKeyName(),
  4023. KEY_ALL_ACCESS,
  4024. &key);
  4025. if ( status != ERROR_SUCCESS ) {
  4026. break;
  4027. }
  4028. } else {
  4029. key = hkeyClusterKey;
  4030. }
  4031. if ( hXsaction != NULL ) {
  4032. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  4033. hXsaction,
  4034. key,
  4035. rvn.PszName() );
  4036. }
  4037. else {
  4038. status = (*pClusterRegApis->pfnDeleteValue)(
  4039. key,
  4040. rvn.PszName() );
  4041. }
  4042. //
  4043. // If the property doesn't exist in the
  4044. // cluster database, fix the status.
  4045. //
  4046. if ( status == ERROR_FILE_NOT_FOUND ) {
  4047. status = ERROR_SUCCESS;
  4048. } // if: property already doesn't exist
  4049. //
  4050. // Close the key if we opened it.
  4051. //
  4052. if ( (rvn.PszKeyName() != NULL) &&
  4053. (key != NULL) ) {
  4054. (*pClusterRegApis->pfnCloseKey)( key );
  4055. }
  4056. } // if: key specified
  4057. } else {
  4058. PVOID key = NULL;
  4059. DWORD disposition;
  4060. if ( hkeyClusterKey != NULL ) {
  4061. //
  4062. // Use the wrapper class CRegistryValueName to parse value name to see if it
  4063. // contains a backslash.
  4064. //
  4065. status = rvn.ScInit( pName->sz, NULL );
  4066. if ( status != ERROR_SUCCESS ) {
  4067. break;
  4068. }
  4069. //
  4070. // If the value resides at a different location, open the key.
  4071. //
  4072. if ( rvn.PszKeyName() != NULL ) {
  4073. if ( hXsaction != NULL ) {
  4074. status = (*pClusterRegApis->pfnLocalCreateKey)( hXsaction,
  4075. hkeyClusterKey,
  4076. rvn.PszKeyName(),
  4077. 0,
  4078. KEY_ALL_ACCESS,
  4079. NULL,
  4080. &key,
  4081. &disposition);
  4082. }
  4083. else {
  4084. status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
  4085. rvn.PszKeyName(),
  4086. 0,
  4087. KEY_ALL_ACCESS,
  4088. NULL,
  4089. &key,
  4090. &disposition);
  4091. }
  4092. if ( status != ERROR_SUCCESS ) {
  4093. break;
  4094. }
  4095. } else {
  4096. key = hkeyClusterKey;
  4097. }
  4098. }
  4099. switch ( buf.pSyntax->wFormat ) {
  4100. case CLUSPROP_FORMAT_DWORD:
  4101. //
  4102. // Verify the length of the value.
  4103. //
  4104. if ( buf.pDwordValue->cbLength != sizeof(DWORD) ) {
  4105. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not DWORD length.\n", pName->sz, buf.pDwordValue->cbLength );
  4106. status = ERROR_INVALID_DATA;
  4107. break;
  4108. }
  4109. //
  4110. // Write the value to the cluster database.
  4111. //
  4112. if ( key != NULL ) {
  4113. if ( hXsaction != NULL ) {
  4114. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4115. key,
  4116. rvn.PszName(),
  4117. REG_DWORD,
  4118. (CONST BYTE*)&buf.pDwordValue->dw,
  4119. sizeof(DWORD) );
  4120. }
  4121. else {
  4122. status = (*pClusterRegApis->pfnSetValue)( key,
  4123. rvn.PszName(),
  4124. REG_DWORD,
  4125. (CONST BYTE*)&buf.pDwordValue->dw,
  4126. sizeof(DWORD) );
  4127. }
  4128. }
  4129. break;
  4130. case CLUSPROP_FORMAT_LONG:
  4131. //
  4132. // Verify the length of the value.
  4133. //
  4134. if ( buf.pLongValue->cbLength != sizeof(LONG) ) {
  4135. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! not LONG length.\n", pName->sz, buf.pLongValue->cbLength );
  4136. status = ERROR_INVALID_DATA;
  4137. break;
  4138. }
  4139. //
  4140. // Write the value to the cluster database.
  4141. //
  4142. if ( key != NULL ) {
  4143. if ( hXsaction != NULL ) {
  4144. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4145. key,
  4146. rvn.PszName(),
  4147. REG_DWORD,
  4148. (CONST BYTE*)&buf.pLongValue->l,
  4149. sizeof(LONG) );
  4150. }
  4151. else {
  4152. status = (*pClusterRegApis->pfnSetValue)( key,
  4153. rvn.PszName(),
  4154. REG_DWORD,
  4155. (CONST BYTE*)&buf.pLongValue->l,
  4156. sizeof(LONG) );
  4157. }
  4158. }
  4159. break;
  4160. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  4161. case CLUSPROP_FORMAT_LARGE_INTEGER:
  4162. //
  4163. // Write the value to the cluster database.
  4164. //
  4165. if ( key != NULL ) {
  4166. if ( hXsaction ) {
  4167. status = (*pClusterRegApis->pfnLocalSetValue)(
  4168. hXsaction,
  4169. key,
  4170. rvn.PszName(),
  4171. REG_QWORD,
  4172. (CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
  4173. sizeof(ULARGE_INTEGER));
  4174. } else {
  4175. status = (*pClusterRegApis->pfnSetValue)(
  4176. key,
  4177. rvn.PszName(),
  4178. REG_QWORD,
  4179. (CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
  4180. sizeof(ULARGE_INTEGER));
  4181. }
  4182. }
  4183. break;
  4184. case CLUSPROP_FORMAT_SZ:
  4185. //
  4186. // Verify the length of the value.
  4187. //
  4188. if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
  4189. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
  4190. status = ERROR_INVALID_DATA;
  4191. break;
  4192. }
  4193. //
  4194. // Write the value to the cluster database.
  4195. //
  4196. if ( key != NULL ) {
  4197. if ( hXsaction != NULL ) {
  4198. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4199. key,
  4200. rvn.PszName(),
  4201. REG_SZ,
  4202. (CONST BYTE*)buf.pStringValue->sz,
  4203. buf.pStringValue->cbLength );
  4204. }
  4205. else {
  4206. status = (*pClusterRegApis->pfnSetValue)( key,
  4207. rvn.PszName(),
  4208. REG_SZ,
  4209. (CONST BYTE*)buf.pStringValue->sz,
  4210. buf.pStringValue->cbLength );
  4211. }
  4212. }
  4213. break;
  4214. case CLUSPROP_FORMAT_EXPAND_SZ:
  4215. //
  4216. // Verify the length of the value.
  4217. //
  4218. if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
  4219. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
  4220. status = ERROR_INVALID_DATA;
  4221. break;
  4222. }
  4223. //
  4224. // Write the value to the cluster database.
  4225. //
  4226. if ( key != NULL ) {
  4227. if ( hXsaction != NULL ) {
  4228. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4229. key,
  4230. rvn.PszName(),
  4231. REG_EXPAND_SZ,
  4232. (CONST BYTE*)buf.pStringValue->sz,
  4233. buf.pStringValue->cbLength );
  4234. }
  4235. else {
  4236. status = (*pClusterRegApis->pfnSetValue)( key,
  4237. rvn.PszName(),
  4238. REG_EXPAND_SZ,
  4239. (CONST BYTE*)buf.pStringValue->sz,
  4240. buf.pStringValue->cbLength );
  4241. }
  4242. }
  4243. break;
  4244. case CLUSPROP_FORMAT_MULTI_SZ:
  4245. //
  4246. // Write the value to the cluster database.
  4247. //
  4248. if ( key != NULL ) {
  4249. if ( hXsaction != NULL ) {
  4250. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4251. key,
  4252. rvn.PszName(),
  4253. REG_MULTI_SZ,
  4254. (CONST BYTE*)buf.pStringValue->sz,
  4255. buf.pStringValue->cbLength );
  4256. }
  4257. else {
  4258. status = (*pClusterRegApis->pfnSetValue)( key,
  4259. rvn.PszName(),
  4260. REG_MULTI_SZ,
  4261. (CONST BYTE*)buf.pStringValue->sz,
  4262. buf.pStringValue->cbLength );
  4263. }
  4264. }
  4265. break;
  4266. case CLUSPROP_FORMAT_BINARY:
  4267. //
  4268. // Write the value to the cluster database.
  4269. //
  4270. if ( key != NULL ) {
  4271. if ( hXsaction ) {
  4272. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4273. key,
  4274. rvn.PszName(),
  4275. REG_BINARY,
  4276. (CONST BYTE*)buf.pBinaryValue->rgb,
  4277. buf.pStringValue->cbLength );
  4278. } else {
  4279. status = (*pClusterRegApis->pfnSetValue)( key,
  4280. rvn.PszName(),
  4281. REG_BINARY,
  4282. (CONST BYTE*)buf.pBinaryValue->rgb,
  4283. buf.pStringValue->cbLength );
  4284. }
  4285. }
  4286. break;
  4287. default:
  4288. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetNonPropertyTable: Property '%1!ls!' unknown format %2!d! specified.\n", pName->sz, buf.pSyntax->wFormat );
  4289. status = ERROR_INVALID_PARAMETER;
  4290. break;
  4291. } // switch
  4292. //
  4293. // Close the key if we opened it.
  4294. //
  4295. if ( (rvn.PszKeyName() != NULL) &&
  4296. (key != NULL) ) {
  4297. (*pClusterRegApis->pfnCloseKey)( key );
  4298. }
  4299. } // if/else: zero length data
  4300. //
  4301. // Move the buffer past the value.
  4302. //
  4303. do {
  4304. dataSize = sizeof(*buf.pValue)
  4305. + ALIGN_CLUSPROP( buf.pValue->cbLength );
  4306. buf.pb += dataSize;
  4307. inBufferSize -= dataSize;
  4308. } while ( buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
  4309. dataSize = sizeof( CLUSPROP_SYNTAX );
  4310. buf.pb += dataSize;
  4311. inBufferSize -= dataSize;
  4312. }
  4313. if ( status != ERROR_SUCCESS ) {
  4314. break;
  4315. }
  4316. }
  4317. return(status);
  4318. } // ClRtlpSetNonPropertyTable
  4319. DWORD
  4320. WINAPI
  4321. ClRtlSetPropertyParameterBlock(
  4322. IN HANDLE hXsaction,
  4323. IN PVOID hkeyClusterKey,
  4324. IN const PCLUSTER_REG_APIS pClusterRegApis,
  4325. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  4326. IN PVOID Reserved,
  4327. IN const LPBYTE pInParams,
  4328. IN const PVOID pInPropertyList,
  4329. IN DWORD cbInPropertyListSize,
  4330. IN BOOL bForceWrite,
  4331. IN OUT OPTIONAL LPBYTE pOutParams
  4332. )
  4333. /*++
  4334. Routine Description:
  4335. Arguments:
  4336. hXsaction - Transaction key used when called from the cluster service.
  4337. hkeyClusterKey - The opened registry key for this object's parameters.
  4338. pClusterRegApis - Supplies a structure of function pointers for accessing
  4339. the cluster database.
  4340. pPropertyTable - Pointer to the property table to process.
  4341. pInParams - Parameter block to set.
  4342. pInPropertyList - Full property list.
  4343. cbInPropertyListSize - Size of the input full property list.
  4344. bForceWrite - TRUE = always write the properties to the cluster database.
  4345. FALSE = only write the properties if they changed.
  4346. pOutParams - Parameters block to copy pInParams to. If specified,
  4347. parameters will only be written if they are different between
  4348. the two parameter blocks.
  4349. Return Value:
  4350. ERROR_SUCCESS if successful.
  4351. A Win32 Error on failure.
  4352. --*/
  4353. {
  4354. DWORD status = ERROR_SUCCESS;
  4355. PRESUTIL_PROPERTY_ITEM propertyItem;
  4356. DWORD itemCount;
  4357. DWORD dataSize;
  4358. PVOID key;
  4359. LPWSTR UNALIGNED * ppszInValue;
  4360. LPWSTR UNALIGNED * ppszOutValue;
  4361. PBYTE UNALIGNED * ppbInValue;
  4362. PBYTE UNALIGNED * ppbOutValue;
  4363. DWORD * pdwInValue;
  4364. DWORD * pdwOutValue;
  4365. ULARGE_INTEGER * pullInValue;
  4366. ULARGE_INTEGER * pullOutValue;
  4367. CRegistryValueName rvn;
  4368. //
  4369. // If hKeyClusterKey is present then 'normal' functions must be present.
  4370. //
  4371. if ( (hkeyClusterKey == NULL) ||
  4372. (pClusterRegApis->pfnCreateKey == NULL) ||
  4373. (pClusterRegApis->pfnSetValue == NULL) ||
  4374. (pClusterRegApis->pfnCloseKey == NULL) ||
  4375. (pPropertyTable == NULL) ||
  4376. (pInParams == NULL) ) {
  4377. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: hkeyClusterKey, pClusterRegApis->pfnCreateKey, pfnSetValue, or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  4378. return(ERROR_BAD_ARGUMENTS);
  4379. }
  4380. //
  4381. // If hXsaction is present then 'local' functions must be present.
  4382. //
  4383. if ( (hXsaction != NULL ) &&
  4384. ((pClusterRegApis->pfnLocalCreateKey == NULL) ||
  4385. (pClusterRegApis->pfnLocalSetValue == NULL) ) ) {
  4386. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: pClusterRegApis->pfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  4387. return(ERROR_BAD_ARGUMENTS);
  4388. }
  4389. //
  4390. // Parse the property table.
  4391. //
  4392. propertyItem = pPropertyTable;
  4393. while ( propertyItem->Name != NULL ) {
  4394. //
  4395. // Make sure we are allowed to set this item.
  4396. //
  4397. if ( propertyItem->Flags & RESUTIL_PROPITEM_READ_ONLY ) {
  4398. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: Property '%1!ls!' is non-writable.\n", propertyItem->Name );
  4399. return(ERROR_INVALID_PARAMETER);
  4400. }
  4401. //
  4402. // Use the wrapper class CRegistryValueName to parse value name to see if it
  4403. // contains a backslash.
  4404. //
  4405. status = rvn.ScInit( propertyItem->Name, propertyItem->KeyName );
  4406. if ( status != ERROR_SUCCESS ) {
  4407. break;
  4408. }
  4409. //
  4410. // If the value resides at a different location, create the key.
  4411. //
  4412. if ( rvn.PszKeyName() != NULL ) {
  4413. DWORD disposition;
  4414. if ( hXsaction != NULL ) {
  4415. status = (*pClusterRegApis->pfnLocalCreateKey)( hXsaction,
  4416. hkeyClusterKey,
  4417. rvn.PszKeyName(),
  4418. 0,
  4419. KEY_ALL_ACCESS,
  4420. NULL,
  4421. &key,
  4422. &disposition );
  4423. } else {
  4424. status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
  4425. rvn.PszKeyName(),
  4426. 0,
  4427. KEY_ALL_ACCESS,
  4428. NULL,
  4429. &key,
  4430. &disposition );
  4431. }
  4432. if ( status != ERROR_SUCCESS ) {
  4433. return(status);
  4434. }
  4435. } else {
  4436. key = hkeyClusterKey;
  4437. }
  4438. switch ( propertyItem->Format ) {
  4439. case CLUSPROP_FORMAT_DWORD:
  4440. case CLUSPROP_FORMAT_LONG:
  4441. pdwInValue = (DWORD *) &pInParams[propertyItem->Offset];
  4442. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
  4443. //
  4444. // Write the value to the cluster database.
  4445. //
  4446. if ( hXsaction != NULL ) {
  4447. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4448. key,
  4449. rvn.PszName(),
  4450. REG_DWORD,
  4451. (CONST BYTE*)pdwInValue,
  4452. sizeof(DWORD) );
  4453. } else {
  4454. status = (*pClusterRegApis->pfnSetValue)( key,
  4455. rvn.PszName(),
  4456. REG_DWORD,
  4457. (CONST BYTE*)pdwInValue,
  4458. sizeof(DWORD) );
  4459. }
  4460. //
  4461. // Save the value to the output Parameter block.
  4462. //
  4463. if ( (status == ERROR_SUCCESS) &&
  4464. (pOutParams != NULL) ) {
  4465. *pdwOutValue = *pdwInValue;
  4466. }
  4467. break;
  4468. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  4469. case CLUSPROP_FORMAT_LARGE_INTEGER:
  4470. pullInValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
  4471. pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
  4472. //
  4473. // Write the value to the cluster database.
  4474. //
  4475. if ( hXsaction != NULL ) {
  4476. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4477. key,
  4478. rvn.PszName(),
  4479. REG_QWORD,
  4480. (CONST BYTE*)pullInValue,
  4481. sizeof(ULARGE_INTEGER) );
  4482. } else {
  4483. status = (*pClusterRegApis->pfnSetValue)( key,
  4484. rvn.PszName(),
  4485. REG_QWORD,
  4486. (CONST BYTE*)pullInValue,
  4487. sizeof(ULARGE_INTEGER) );
  4488. }
  4489. //
  4490. // Save the value to the output Parameter block.
  4491. //
  4492. if ( (status == ERROR_SUCCESS) && (pOutParams != NULL) ) {
  4493. pullOutValue->u = pullInValue->u;
  4494. }
  4495. break;
  4496. case CLUSPROP_FORMAT_SZ:
  4497. case CLUSPROP_FORMAT_EXPAND_SZ:
  4498. ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  4499. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  4500. //
  4501. // If the data changed, write it and save it.
  4502. // Do this even if only the case of the data changed.
  4503. //
  4504. if ( bForceWrite ||
  4505. (pOutParams == NULL) ||
  4506. (*ppszOutValue == NULL) ||
  4507. (lstrcmpW( *ppszInValue, *ppszOutValue ) != 0) ) {
  4508. //
  4509. // Write the value to the cluster database.
  4510. //
  4511. if ( *ppszInValue != NULL ) {
  4512. if ( hXsaction != NULL ) {
  4513. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4514. key,
  4515. rvn.PszName(),
  4516. (propertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ
  4517. ? REG_EXPAND_SZ
  4518. : REG_SZ),
  4519. (CONST BYTE*)*ppszInValue,
  4520. (lstrlenW(*ppszInValue) + 1) * sizeof(WCHAR) );
  4521. } else {
  4522. status = (*pClusterRegApis->pfnSetValue)( key,
  4523. rvn.PszName(),
  4524. (propertyItem->Format == CLUSPROP_FORMAT_EXPAND_SZ
  4525. ? REG_EXPAND_SZ
  4526. : REG_SZ),
  4527. (CONST BYTE*)*ppszInValue,
  4528. (lstrlenW(*ppszInValue) + 1) * sizeof(WCHAR) );
  4529. }
  4530. }
  4531. //
  4532. // Save the value to the output Parameter block.
  4533. //
  4534. if ( (status == ERROR_SUCCESS) &&
  4535. (pOutParams != NULL) ) {
  4536. if ( *ppszOutValue != NULL ) {
  4537. LocalFree( *ppszOutValue );
  4538. }
  4539. if ( *ppszInValue == NULL ) {
  4540. *ppszOutValue = NULL;
  4541. } else {
  4542. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( *ppszInValue )+1) * sizeof(WCHAR) );
  4543. if ( *ppszOutValue == NULL ) {
  4544. status = GetLastError();
  4545. ClRtlDbgPrint(
  4546. LOG_CRITICAL,
  4547. "ClRtlSetPropertyParameterBlock: error allocating memory for "
  4548. "SZ value '%1!ls!' in parameter block for property '%2!ls!'.\n",
  4549. *ppszInValue,
  4550. propertyItem->Name );
  4551. break;
  4552. }
  4553. lstrcpyW( *ppszOutValue, *ppszInValue );
  4554. }
  4555. }
  4556. }
  4557. break;
  4558. case CLUSPROP_FORMAT_MULTI_SZ:
  4559. ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  4560. pdwInValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
  4561. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  4562. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(LPWSTR*)];
  4563. //
  4564. // If the data changed, write it and save it.
  4565. //
  4566. if ( bForceWrite ||
  4567. (pOutParams == NULL) ||
  4568. (*ppszOutValue == NULL) ||
  4569. (*pdwInValue != *pdwOutValue) ||
  4570. (memcmp( *ppszInValue, *ppszOutValue, *pdwInValue ) != 0) ) {
  4571. //
  4572. // Write the value to the cluster database.
  4573. //
  4574. if ( *ppszInValue != NULL ) {
  4575. if ( hXsaction != NULL ) {
  4576. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4577. key,
  4578. rvn.PszName(),
  4579. REG_MULTI_SZ,
  4580. (CONST BYTE*)*ppszInValue,
  4581. *pdwInValue );
  4582. } else {
  4583. status = (*pClusterRegApis->pfnSetValue)( key,
  4584. rvn.PszName(),
  4585. REG_MULTI_SZ,
  4586. (CONST BYTE*)*ppszInValue,
  4587. *pdwInValue );
  4588. }
  4589. }
  4590. //
  4591. // Save the value to the output Parameter block.
  4592. //
  4593. if ( (status == ERROR_SUCCESS) &&
  4594. (pOutParams != NULL) ) {
  4595. if ( *ppszOutValue != NULL ) {
  4596. LocalFree( *ppszOutValue );
  4597. }
  4598. if ( *ppszInValue == NULL ) {
  4599. *ppszOutValue = NULL;
  4600. } else {
  4601. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, *pdwInValue );
  4602. if ( *ppszOutValue == NULL ) {
  4603. status = GetLastError();
  4604. *pdwOutValue = 0;
  4605. ClRtlDbgPrint(
  4606. LOG_CRITICAL,
  4607. "ClRtlSetPropertyParameterBlock: error allocating memory for "
  4608. "MULTI_SZ value in parameter block for property '%1!ls!'.\n",
  4609. propertyItem->Name );
  4610. break;
  4611. }
  4612. CopyMemory( *ppszOutValue, *ppszInValue, *pdwInValue );
  4613. *pdwOutValue = *pdwInValue;
  4614. }
  4615. }
  4616. }
  4617. break;
  4618. case CLUSPROP_FORMAT_BINARY:
  4619. ppbInValue = (PBYTE UNALIGNED *) &pInParams[propertyItem->Offset];
  4620. pdwInValue = (DWORD *) &pInParams[propertyItem->Offset+sizeof(LPWSTR*)];
  4621. ppbOutValue = (PBYTE UNALIGNED *) &pOutParams[propertyItem->Offset];
  4622. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset+sizeof(PBYTE*)];
  4623. //
  4624. // If the data changed, write it and save it.
  4625. //
  4626. if ( bForceWrite ||
  4627. (pOutParams == NULL) ||
  4628. (*ppbOutValue == NULL) ||
  4629. (*pdwInValue != *pdwOutValue) ||
  4630. (memcmp( *ppbInValue, *ppbOutValue, *pdwInValue ) != 0) ) {
  4631. //
  4632. // Write the value to the cluster database.
  4633. //
  4634. if ( *ppbInValue != NULL ) {
  4635. if ( hXsaction != NULL ) {
  4636. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4637. key,
  4638. rvn.PszName(),
  4639. REG_BINARY,
  4640. (CONST BYTE*)*ppbInValue,
  4641. *pdwInValue );
  4642. }
  4643. else {
  4644. status = (*pClusterRegApis->pfnSetValue)( key,
  4645. rvn.PszName(),
  4646. REG_BINARY,
  4647. (CONST BYTE*)*ppbInValue,
  4648. *pdwInValue );
  4649. }
  4650. }
  4651. //
  4652. // Save the value to the output Parameter block.
  4653. //
  4654. if ( (status == ERROR_SUCCESS) &&
  4655. (pOutParams != NULL) ) {
  4656. if ( *ppbOutValue != NULL ) {
  4657. LocalFree( *ppbOutValue );
  4658. }
  4659. if ( *ppbInValue == NULL ) {
  4660. *ppbOutValue = NULL;
  4661. } else {
  4662. *ppbOutValue = (LPBYTE) LocalAlloc( LMEM_FIXED, *pdwInValue );
  4663. if ( *ppbOutValue == NULL ) {
  4664. status = GetLastError();
  4665. *pdwOutValue = 0;
  4666. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: error allocating memory for BINARY value in parameter block for property '%1!ls!'.\n", propertyItem->Name );
  4667. break;
  4668. }
  4669. CopyMemory( *ppbOutValue, *ppbInValue, *pdwInValue );
  4670. *pdwOutValue = *pdwInValue;
  4671. }
  4672. }
  4673. }
  4674. break;
  4675. default:
  4676. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlSetPropertyParameterBlock: Property '%1!ls!' unknown format %2!d! specified.\n", propertyItem->Name, propertyItem->Format );
  4677. status = ERROR_INVALID_PARAMETER;
  4678. break;
  4679. }
  4680. //
  4681. // Close the key if we opened it.
  4682. //
  4683. if ( rvn.PszKeyName() != NULL ) {
  4684. (*pClusterRegApis->pfnCloseKey)( key );
  4685. }
  4686. //
  4687. // If an error occurred processing the property, cleanup and return.
  4688. //
  4689. if ( status != ERROR_SUCCESS ) {
  4690. return(status);
  4691. }
  4692. propertyItem++;
  4693. }
  4694. //
  4695. // Now find any parameters that are not represented in the property
  4696. // table. All of these extra properties will just be set without validation.
  4697. //
  4698. if ( (status == ERROR_SUCCESS) &&
  4699. (pInPropertyList != NULL) ) {
  4700. status = ClRtlpSetNonPropertyTable( hXsaction,
  4701. hkeyClusterKey,
  4702. pClusterRegApis,
  4703. pPropertyTable,
  4704. NULL,
  4705. pInPropertyList,
  4706. cbInPropertyListSize );
  4707. }
  4708. return(status);
  4709. } // ClRtlSetPropertyParameterBlock
  4710. DWORD
  4711. WINAPI
  4712. ClRtlpSetPrivatePropertyList(
  4713. IN HANDLE hXsaction,
  4714. IN PVOID hkeyClusterKey,
  4715. IN const PCLUSTER_REG_APIS pClusterRegApis,
  4716. IN const PVOID pInPropertyList,
  4717. IN DWORD cbInPropertyListSize
  4718. )
  4719. /*++
  4720. Routine Description:
  4721. Arguments:
  4722. hkeyClusterKey - The opened registry key for this resource's parameters.
  4723. If not specified, the property list will only be validated.
  4724. pClusterRegApis - Supplies a structure of function pointers for accessing
  4725. the cluster database.
  4726. pInPropertyList - The input buffer.
  4727. cbInPropertyListSize - The input buffer size.
  4728. Return Value:
  4729. ERROR_SUCCESS if successful.
  4730. A Win32 Error on failure.
  4731. --*/
  4732. {
  4733. DWORD status = ERROR_SUCCESS;
  4734. DWORD inBufferSize;
  4735. DWORD itemCount;
  4736. DWORD dataSize;
  4737. DWORD valueSize;
  4738. CLUSPROP_BUFFER_HELPER bufSizeTest;
  4739. CLUSPROP_BUFFER_HELPER buf;
  4740. PCLUSPROP_PROPERTY_NAME pName;
  4741. BOOL bZeroLengthData;
  4742. CRegistryValueName rvn;
  4743. if ( (hkeyClusterKey != NULL) &&
  4744. ( (pClusterRegApis->pfnSetValue == NULL) ||
  4745. (pClusterRegApis->pfnCreateKey == NULL) ||
  4746. (pClusterRegApis->pfnOpenKey == NULL) ||
  4747. (pClusterRegApis->pfnCloseKey == NULL) ||
  4748. (pClusterRegApis->pfnDeleteValue == NULL)
  4749. ) ) {
  4750. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pClusterRegApis->pfnCreateKey, pfnOpenKey, pfnSetValue, pfnCloseKey, or pfnDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  4751. return(ERROR_BAD_ARGUMENTS);
  4752. }
  4753. if ( pInPropertyList == NULL ) {
  4754. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pInPropertyList == NULL. Returning ERROR_INVALID_DATA\n" );
  4755. return(ERROR_INVALID_DATA);
  4756. }
  4757. //
  4758. // If hXsaction is present then 'local' functions must be present.
  4759. //
  4760. if ( (hXsaction != NULL ) &&
  4761. ( (pClusterRegApis->pfnLocalCreateKey == NULL) ||
  4762. (pClusterRegApis->pfnLocalDeleteValue == NULL)
  4763. ) ) {
  4764. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: pClusterRegApis->pfnLocalCreateKey or pfnLocalDeleteValue == NULL. Returning ERROR_BAD_ARGUMENTS\n" );
  4765. return(ERROR_BAD_ARGUMENTS);
  4766. }
  4767. buf.pb = (LPBYTE) pInPropertyList;
  4768. inBufferSize = cbInPropertyListSize;
  4769. //
  4770. // Get the number of items in this list
  4771. //
  4772. if ( inBufferSize < sizeof(DWORD) ) {
  4773. return(ERROR_INSUFFICIENT_BUFFER);
  4774. }
  4775. itemCount = buf.pList->nPropertyCount;
  4776. buf.pdw++;
  4777. //
  4778. // Parse the rest of the items in the buffer.
  4779. //
  4780. while ( itemCount-- ) {
  4781. pName = buf.pName;
  4782. if ( inBufferSize < sizeof(*pName) ) {
  4783. return(ERROR_INSUFFICIENT_BUFFER);
  4784. }
  4785. dataSize = sizeof(*pName) + ALIGN_CLUSPROP( pName->cbLength );
  4786. if ( inBufferSize < dataSize + sizeof(CLUSPROP_VALUE) ) {
  4787. return(ERROR_INSUFFICIENT_BUFFER);
  4788. }
  4789. //
  4790. // Verify that the syntax of the property name is correct.
  4791. //
  4792. if ( pName->Syntax.dw != CLUSPROP_SYNTAX_NAME ) {
  4793. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: syntax %1!d! not a name syntax.\n", pName->Syntax.dw );
  4794. return(ERROR_INVALID_PARAMETER);
  4795. }
  4796. //
  4797. // Verify that the length is correct for the string.
  4798. //
  4799. if ( pName->cbLength != (lstrlenW( pName->sz ) + 1) * sizeof(WCHAR) ) {
  4800. ClRtlDbgPrint( LOG_CRITICAL, "SetPrivatePropertyList: name is not a valid C string.\n" );
  4801. return(ERROR_INVALID_DATA);
  4802. }
  4803. //
  4804. // Move the buffer pointer to the property value.
  4805. //
  4806. buf.pb += dataSize;
  4807. inBufferSize -= dataSize;
  4808. //
  4809. // Verify that the buffer is big enough to contain the value.
  4810. //
  4811. bufSizeTest.pb = buf.pb;
  4812. dataSize = 0;
  4813. do {
  4814. valueSize = sizeof( *bufSizeTest.pValue )
  4815. + ALIGN_CLUSPROP( bufSizeTest.pValue->cbLength );
  4816. bufSizeTest.pb += valueSize;
  4817. dataSize += valueSize;
  4818. } while ( bufSizeTest.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK );
  4819. dataSize += sizeof( CLUSPROP_SYNTAX );
  4820. if ( inBufferSize < dataSize ) {
  4821. return(ERROR_INSUFFICIENT_BUFFER);
  4822. }
  4823. //
  4824. // Verify that the syntax type is SPECIAL.
  4825. //
  4826. if ( buf.pSyntax->wType != CLUSPROP_TYPE_LIST_VALUE ) {
  4827. 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 );
  4828. return(ERROR_INVALID_PARAMETER);
  4829. }
  4830. //
  4831. // If the value is not specified, delete the property.
  4832. //
  4833. bZeroLengthData = ( buf.pValue->cbLength == 0 );
  4834. if ( bZeroLengthData ) {
  4835. if ( hkeyClusterKey != NULL ) {
  4836. PVOID key = NULL;
  4837. //
  4838. // Use the wrapper class CRegistryValueName to parse value name to see if it
  4839. // contains a backslash.
  4840. //
  4841. status = rvn.ScInit( pName->sz, NULL );
  4842. if ( status != ERROR_SUCCESS ) {
  4843. break;
  4844. }
  4845. //
  4846. // If the value resides at a different location, open the key.
  4847. //
  4848. if ( rvn.PszKeyName() != NULL ) {
  4849. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  4850. rvn.PszKeyName(),
  4851. KEY_ALL_ACCESS,
  4852. &key);
  4853. if ( status != ERROR_SUCCESS ) {
  4854. break;
  4855. }
  4856. } else {
  4857. key = hkeyClusterKey;
  4858. }
  4859. if ( hXsaction != NULL ) {
  4860. status = (*pClusterRegApis->pfnLocalDeleteValue)(
  4861. hXsaction,
  4862. key,
  4863. rvn.PszName() );
  4864. }
  4865. else {
  4866. status = (*pClusterRegApis->pfnDeleteValue)(
  4867. key,
  4868. rvn.PszName() );
  4869. }
  4870. //
  4871. // If the property doesn't exist in the
  4872. // cluster database, fix the status.
  4873. //
  4874. if ( status == ERROR_FILE_NOT_FOUND ) {
  4875. status = ERROR_SUCCESS;
  4876. } // if: property already doesn't exist
  4877. //
  4878. // Close the key if we opened it.
  4879. //
  4880. if ( (rvn.PszKeyName() != NULL) &&
  4881. (key != NULL) ) {
  4882. (*pClusterRegApis->pfnCloseKey)( key );
  4883. }
  4884. } // if: key specified
  4885. } else {
  4886. PVOID key = NULL;
  4887. DWORD disposition;
  4888. if ( hkeyClusterKey != NULL ) {
  4889. //
  4890. // Use the wrapper class CRegistryValueName to parse value name to see if it
  4891. // contains a backslash.
  4892. //
  4893. status = rvn.ScInit( pName->sz, NULL );
  4894. if ( status != ERROR_SUCCESS ) {
  4895. break;
  4896. }
  4897. //
  4898. // If the value resides at a different location, open the key.
  4899. //
  4900. if ( rvn.PszKeyName() != NULL ) {
  4901. if ( hXsaction != NULL ) {
  4902. status = (*pClusterRegApis->pfnLocalCreateKey)(
  4903. hXsaction,
  4904. hkeyClusterKey,
  4905. rvn.PszKeyName(),
  4906. 0,
  4907. KEY_ALL_ACCESS,
  4908. NULL,
  4909. &key,
  4910. &disposition);
  4911. }
  4912. else {
  4913. status = (*pClusterRegApis->pfnCreateKey)( hkeyClusterKey,
  4914. rvn.PszKeyName(),
  4915. 0,
  4916. KEY_ALL_ACCESS,
  4917. NULL,
  4918. &key,
  4919. &disposition);
  4920. }
  4921. if ( status != ERROR_SUCCESS ) {
  4922. break;
  4923. }
  4924. } else {
  4925. key = hkeyClusterKey;
  4926. }
  4927. }
  4928. //
  4929. // Parse the property and set it in the cluster database
  4930. //
  4931. switch ( buf.pSyntax->wFormat ) {
  4932. case CLUSPROP_FORMAT_DWORD:
  4933. case CLUSPROP_FORMAT_LONG:
  4934. //
  4935. // Verify the length of the value.
  4936. //
  4937. if ( buf.pDwordValue->cbLength != sizeof(DWORD) ) {
  4938. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: Property '%1!ls!' length %2!d! not DWORD or LONG length.\n", pName->sz, buf.pDwordValue->cbLength );
  4939. status = ERROR_INVALID_DATA;
  4940. break;
  4941. }
  4942. //
  4943. // Write the value to the cluster database.
  4944. //
  4945. if ( key != NULL ) {
  4946. if ( hXsaction != NULL ) {
  4947. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  4948. key,
  4949. rvn.PszName(),
  4950. REG_DWORD,
  4951. (CONST BYTE*)&buf.pDwordValue->dw,
  4952. sizeof(DWORD) );
  4953. }
  4954. else {
  4955. status = (*pClusterRegApis->pfnSetValue)( key,
  4956. rvn.PszName(),
  4957. REG_DWORD,
  4958. (CONST BYTE*)&buf.pDwordValue->dw,
  4959. sizeof(DWORD));
  4960. }
  4961. }
  4962. break;
  4963. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  4964. case CLUSPROP_FORMAT_LARGE_INTEGER:
  4965. //
  4966. // Verify the length of the value.
  4967. //
  4968. if ( buf.pULargeIntegerValue->cbLength != sizeof(ULARGE_INTEGER) ) {
  4969. ClRtlDbgPrint(LOG_CRITICAL,
  4970. "ClRtlpSetPrivatePropertyList: Property '%1!ls!' length "
  4971. "%2!d! not ULARGE_INTEGER or LARGE_INTEGER length.\n",
  4972. pName->sz,
  4973. buf.pULargeIntegerValue->cbLength );
  4974. status = ERROR_INVALID_DATA;
  4975. break;
  4976. }
  4977. //
  4978. // Write the value to the cluster database.
  4979. //
  4980. if ( key != NULL ) {
  4981. if ( hXsaction != NULL ) {
  4982. status = (*pClusterRegApis->pfnLocalSetValue)(
  4983. hXsaction,
  4984. key,
  4985. rvn.PszName(),
  4986. REG_QWORD,
  4987. (CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
  4988. sizeof(ULARGE_INTEGER) );
  4989. }
  4990. else {
  4991. status = (*pClusterRegApis->pfnSetValue)(
  4992. key,
  4993. rvn.PszName(),
  4994. REG_QWORD,
  4995. (CONST BYTE*)&buf.pULargeIntegerValue->li.QuadPart,
  4996. sizeof(ULARGE_INTEGER));
  4997. }
  4998. }
  4999. break;
  5000. case CLUSPROP_FORMAT_SZ:
  5001. case CLUSPROP_FORMAT_EXPAND_SZ:
  5002. //
  5003. // Verify the length of the value.
  5004. //
  5005. if ( buf.pStringValue->cbLength != (lstrlenW( buf.pStringValue->sz ) + 1) * sizeof(WCHAR) ) {
  5006. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlpSetPrivatePropertyList: Property '%1!ls!' length %2!d! doesn't match null-term. length.\n", pName->sz, buf.pStringValue->cbLength );
  5007. status = ERROR_INVALID_DATA;
  5008. break;
  5009. }
  5010. //
  5011. // Write the value to the cluster database.
  5012. //
  5013. if ( key != NULL ) {
  5014. if ( hXsaction != NULL ) {
  5015. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  5016. key,
  5017. rvn.PszName(),
  5018. (buf.pSyntax->wFormat == CLUSPROP_FORMAT_EXPAND_SZ
  5019. ? REG_EXPAND_SZ
  5020. : REG_SZ),
  5021. (CONST BYTE*)buf.pStringValue->sz,
  5022. buf.pStringValue->cbLength);
  5023. }
  5024. else {
  5025. status = (*pClusterRegApis->pfnSetValue)( key,
  5026. rvn.PszName(),
  5027. (buf.pSyntax->wFormat == CLUSPROP_FORMAT_EXPAND_SZ
  5028. ? REG_EXPAND_SZ
  5029. : REG_SZ),
  5030. (CONST BYTE*)buf.pStringValue->sz,
  5031. buf.pStringValue->cbLength);
  5032. }
  5033. }
  5034. break;
  5035. case CLUSPROP_FORMAT_MULTI_SZ:
  5036. //
  5037. // Write the value to the cluster database.
  5038. //
  5039. if ( key != NULL ) {
  5040. if ( hXsaction != NULL ) {
  5041. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  5042. key,
  5043. rvn.PszName(),
  5044. REG_MULTI_SZ,
  5045. (CONST BYTE*)buf.pStringValue->sz,
  5046. buf.pStringValue->cbLength );
  5047. }
  5048. else {
  5049. status = (*pClusterRegApis->pfnSetValue)( key,
  5050. rvn.PszName(),
  5051. REG_MULTI_SZ,
  5052. (CONST BYTE*)buf.pStringValue->sz,
  5053. buf.pStringValue->cbLength );
  5054. }
  5055. }
  5056. break;
  5057. case CLUSPROP_FORMAT_BINARY:
  5058. //
  5059. // Write the value to the cluster database.
  5060. //
  5061. if ( key != NULL ) {
  5062. if ( hXsaction != NULL ) {
  5063. status = (*pClusterRegApis->pfnLocalSetValue)( hXsaction,
  5064. key,
  5065. rvn.PszName(),
  5066. REG_BINARY,
  5067. (CONST BYTE*)buf.pBinaryValue->rgb,
  5068. buf.pBinaryValue->cbLength );
  5069. }
  5070. else {
  5071. status = (*pClusterRegApis->pfnSetValue)( key,
  5072. rvn.PszName(),
  5073. REG_BINARY,
  5074. (CONST BYTE*)buf.pBinaryValue->rgb,
  5075. buf.pBinaryValue->cbLength );
  5076. }
  5077. }
  5078. break;
  5079. default:
  5080. status = ERROR_INVALID_PARAMETER; // not tested
  5081. } // switch
  5082. //
  5083. // Close the key if we opened it.
  5084. //
  5085. if ( (rvn.PszKeyName() != NULL) &&
  5086. (key != NULL) ) {
  5087. (*pClusterRegApis->pfnCloseKey)( key );
  5088. }
  5089. } // if/else: zero length data
  5090. if ( status != ERROR_SUCCESS ) {
  5091. break;
  5092. }
  5093. //
  5094. // Move the buffer past the value.
  5095. //
  5096. buf.pb += dataSize;
  5097. inBufferSize -= dataSize;
  5098. }
  5099. return(status);
  5100. } // ClRtlpSetPrivatePropertyList
  5101. DWORD
  5102. WINAPI
  5103. ClRtlpFindSzProperty(
  5104. IN const PVOID pPropertyList,
  5105. IN DWORD cbPropertyListSize,
  5106. IN LPCWSTR pszPropertyName,
  5107. OUT LPWSTR * pszPropertyValue,
  5108. IN BOOL bReturnExpandedValue
  5109. )
  5110. /*++
  5111. Routine Description:
  5112. Finds the specified string property in the Property List buffer pointed at
  5113. by pPropertyList.
  5114. Arguments:
  5115. pPropertyList - a property list.
  5116. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5117. pszPropertyName - the property name to look for in the buffer.
  5118. pszPropertyValue - the matching string value found.
  5119. bReturnExpandedValue - TRUE = return expanded value if one is present,
  5120. FALSE = return the first value.
  5121. Return Value:
  5122. ERROR_SUCCESS if successful.
  5123. ERROR_INVALID_DATA -
  5124. ERROR_FILE_NOT_FOUND -
  5125. ERROR_NOT_ENOUGH_MEMORY -
  5126. A Win32 error code on failure.
  5127. --*/
  5128. {
  5129. CLUSPROP_BUFFER_HELPER props;
  5130. LPWSTR valueData;
  5131. LPWSTR listValueData;
  5132. DWORD listByteLength;
  5133. DWORD itemCount;
  5134. DWORD byteCount;
  5135. props.pb = (LPBYTE) pPropertyList;
  5136. itemCount = *(props.pdw++);
  5137. cbPropertyListSize -= sizeof(DWORD);
  5138. while ( itemCount-- &&
  5139. ((LONG)cbPropertyListSize > 0) ) {
  5140. //
  5141. // If we found the specified property, validate the entry and return
  5142. // the value to the caller.
  5143. //
  5144. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5145. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5146. //
  5147. // Calculate the size of the name and move to the value.
  5148. //
  5149. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5150. props.pb += sizeof(*props.pValue) + byteCount;
  5151. //
  5152. // Make sure this is a string property.
  5153. //
  5154. if ( (props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_SZ) &&
  5155. (props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_EXPAND_SZ) ) {
  5156. 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 );
  5157. return(ERROR_INVALID_DATA);
  5158. }
  5159. //
  5160. // If caller wants the value, allocate a buffer for it
  5161. // and copy the value in.
  5162. //
  5163. if ( pszPropertyValue != NULL ) {
  5164. //
  5165. // If caller wants the expanded value, look at any
  5166. // additional values in the value list to see if one
  5167. // was returned.
  5168. //
  5169. listValueData = props.pStringValue->sz;
  5170. listByteLength = props.pStringValue->cbLength;
  5171. if ( bReturnExpandedValue ) {
  5172. //
  5173. // Skip past values in the value list looking for
  5174. // an expanded string value.
  5175. //
  5176. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5177. (cbPropertyListSize > 0) ) {
  5178. byteCount = sizeof(*props.pValue) + ALIGN_CLUSPROP(listByteLength);
  5179. cbPropertyListSize -= byteCount;
  5180. props.pb += byteCount;
  5181. if ( props.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_EXPANDED_SZ ) {
  5182. listValueData = props.pStringValue->sz;
  5183. listByteLength = props.pStringValue->cbLength;
  5184. break;
  5185. }
  5186. }
  5187. }
  5188. //
  5189. // Allocate a buffer for the string value and
  5190. // copy the value from the property list.
  5191. //
  5192. valueData = (LPWSTR) LocalAlloc( LMEM_FIXED, listByteLength );
  5193. if ( valueData == NULL ) {
  5194. return(ERROR_NOT_ENOUGH_MEMORY);
  5195. }
  5196. CopyMemory( valueData, listValueData, listByteLength );
  5197. *pszPropertyValue = valueData;
  5198. }
  5199. //
  5200. // We found the property so return success.
  5201. //
  5202. return(ERROR_SUCCESS);
  5203. } else {
  5204. //
  5205. // Skip the name (value header + size of data).
  5206. //
  5207. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5208. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5209. props.pb += sizeof(*props.pValue) + byteCount;
  5210. //
  5211. // Skip it's value list (one or more values + endmark).
  5212. //
  5213. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5214. (cbPropertyListSize > 0) ) {
  5215. byteCount = sizeof(*props.pValue) + ALIGN_CLUSPROP(props.pValue->cbLength);
  5216. cbPropertyListSize -= byteCount;
  5217. props.pb += byteCount;
  5218. }
  5219. cbPropertyListSize -= sizeof(*props.pSyntax);
  5220. props.pb += sizeof(*props.pSyntax);
  5221. }
  5222. }
  5223. return(ERROR_FILE_NOT_FOUND);
  5224. } // ClRtlpFindSzProperty
  5225. DWORD
  5226. WINAPI
  5227. ClRtlFindDwordProperty(
  5228. IN const PVOID pPropertyList,
  5229. IN DWORD cbPropertyListSize,
  5230. IN LPCWSTR pszPropertyName,
  5231. OUT LPDWORD pdwPropertyValue
  5232. )
  5233. /*++
  5234. Routine Description:
  5235. Finds the specified DWORD property in the Property List buffer pointed at
  5236. by pPropertyList.
  5237. Arguments:
  5238. pPropertyList - a property list.
  5239. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5240. pszPropertyName - the property name to look for in the buffer.
  5241. pdwPropertyValue - the matching DWORD value found.
  5242. Return Value:
  5243. ERROR_SUCCESS if successful.
  5244. ERROR_INVALID_DATA -
  5245. ERROR_FILE_NOT_FOUND -
  5246. A Win32 error code on failure.
  5247. --*/
  5248. {
  5249. CLUSPROP_BUFFER_HELPER props;
  5250. LPWSTR valueData;
  5251. DWORD itemCount;
  5252. DWORD byteCount;
  5253. props.pb = (LPBYTE) pPropertyList;
  5254. itemCount = *(props.pdw++);
  5255. cbPropertyListSize -= sizeof(DWORD);
  5256. while ( itemCount-- &&
  5257. ((LONG)cbPropertyListSize > 0) ) {
  5258. //
  5259. // If we found the specified property, validate the entry and return
  5260. // the value to the caller.
  5261. //
  5262. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5263. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5264. //
  5265. // Calculate the size of the name and move to the value.
  5266. //
  5267. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5268. props.pb += sizeof(*props.pValue) + byteCount;
  5269. //
  5270. // Make sure this is a dword property.
  5271. //
  5272. if ( props.pDwordValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_DWORD ) {
  5273. 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 );
  5274. return(ERROR_INVALID_DATA);
  5275. }
  5276. //
  5277. // If caller wants the value, allocate a buffer for it.
  5278. //
  5279. if ( pdwPropertyValue ) {
  5280. *pdwPropertyValue = props.pDwordValue->dw;
  5281. }
  5282. //
  5283. // We found the property so return success.
  5284. //
  5285. return(ERROR_SUCCESS);
  5286. } else {
  5287. //
  5288. // Skip the name (value header + size of data).
  5289. //
  5290. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5291. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5292. props.pb += sizeof(*props.pValue) + byteCount;
  5293. //
  5294. // Skip it's value list and endmark.
  5295. //
  5296. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5297. (cbPropertyListSize > 0) ) {
  5298. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5299. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5300. props.pb += sizeof(*props.pValue) + byteCount;
  5301. }
  5302. cbPropertyListSize -= sizeof(*props.pSyntax);
  5303. props.pb += sizeof(*props.pSyntax);
  5304. }
  5305. }
  5306. return(ERROR_FILE_NOT_FOUND);
  5307. } // ClRtlFindDwordProperty
  5308. DWORD
  5309. WINAPI
  5310. ClRtlFindLongProperty(
  5311. IN const PVOID pPropertyList,
  5312. IN DWORD cbPropertyListSize,
  5313. IN LPCWSTR pszPropertyName,
  5314. OUT LPLONG plPropertyValue
  5315. )
  5316. /*++
  5317. Routine Description:
  5318. Finds the specified dword in the Value List buffer pointed at by Buffer.
  5319. Arguments:
  5320. pPropertyList - a property list.
  5321. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5322. pszPropertyName - the property name to look for in the buffer.
  5323. plPropertyValue - the matching long value found.
  5324. Return Value:
  5325. ERROR_SUCCESS if successful.
  5326. ERROR_INVALID_DATA -
  5327. ERROR_FILE_NOT_FOUND -
  5328. A Win32 error code on failure.
  5329. --*/
  5330. {
  5331. CLUSPROP_BUFFER_HELPER props;
  5332. LPWSTR valueData;
  5333. DWORD itemCount;
  5334. DWORD byteCount;
  5335. props.pb = (LPBYTE) pPropertyList;
  5336. itemCount = *(props.pdw++);
  5337. cbPropertyListSize -= sizeof(DWORD);
  5338. while ( itemCount-- &&
  5339. (cbPropertyListSize > 0) ) {
  5340. //
  5341. // If we found the specified property, validate the entry and return
  5342. // the value to the caller.
  5343. //
  5344. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5345. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5346. //
  5347. // Calculate the size of the name and move to the value.
  5348. //
  5349. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5350. props.pb += sizeof(*props.pValue) + byteCount;
  5351. //
  5352. // Make sure this is a long property.
  5353. //
  5354. if ( props.pLongValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_DWORD ) {
  5355. 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 );
  5356. return(ERROR_INVALID_DATA);
  5357. }
  5358. //
  5359. // If caller wants the value, allocate a buffer for it.
  5360. //
  5361. if ( plPropertyValue) {
  5362. *plPropertyValue = props.pLongValue->l;
  5363. }
  5364. //
  5365. // We found the property so return success.
  5366. //
  5367. return(ERROR_SUCCESS);
  5368. } else {
  5369. //
  5370. // Skip the name (value header + size of data).
  5371. //
  5372. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5373. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5374. props.pb += sizeof(*props.pValue) + byteCount;
  5375. //
  5376. // Skip it's value list and endmark.
  5377. //
  5378. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5379. (cbPropertyListSize > 0) ) {
  5380. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5381. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5382. props.pb += sizeof(*props.pValue) + byteCount;
  5383. }
  5384. cbPropertyListSize -= sizeof(*props.pSyntax);
  5385. props.pb += sizeof(*props.pSyntax);
  5386. }
  5387. }
  5388. return(ERROR_FILE_NOT_FOUND);
  5389. } // ClRtlFindLongProperty
  5390. DWORD
  5391. WINAPI
  5392. ClRtlFindULargeIntegerProperty(
  5393. IN const PVOID pPropertyList,
  5394. IN DWORD cbPropertyListSize,
  5395. IN LPCWSTR pszPropertyName,
  5396. OUT PULARGE_INTEGER pullPropertyValue
  5397. )
  5398. /*++
  5399. Routine Description:
  5400. Finds the specified ULARGE_INTEGER property in the Property List buffer
  5401. pointed at by pPropertyList.
  5402. Arguments:
  5403. pPropertyList - a property list.
  5404. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5405. pszPropertyName - the property name to look for in the buffer.
  5406. pullPropertyValue - the matching ULARGE_INTEGER value found.
  5407. Return Value:
  5408. ERROR_SUCCESS if successful.
  5409. ERROR_INVALID_DATA -
  5410. ERROR_FILE_NOT_FOUND -
  5411. A Win32 error code on failure.
  5412. --*/
  5413. {
  5414. CLUSPROP_BUFFER_HELPER props;
  5415. LPWSTR valueData;
  5416. DWORD itemCount;
  5417. DWORD byteCount;
  5418. props.pb = (LPBYTE) pPropertyList;
  5419. itemCount = *(props.pdw++);
  5420. cbPropertyListSize -= sizeof(DWORD);
  5421. while ( itemCount-- &&
  5422. ((LONG)cbPropertyListSize > 0) ) {
  5423. //
  5424. // If we found the specified property, validate the entry and return
  5425. // the value to the caller.
  5426. //
  5427. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5428. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5429. //
  5430. // Calculate the size of the name and move to the value.
  5431. //
  5432. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5433. props.pb += sizeof(*props.pValue) + byteCount;
  5434. //
  5435. // Make sure this is a LARGE INT property.
  5436. //
  5437. if ( props.pULargeIntegerValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_LARGE_INTEGER ) {
  5438. ClRtlDbgPrint(LOG_CRITICAL,
  5439. "ClRtlFindULargeIntegerProperty: Property '%1!ls!' syntax "
  5440. "(%2!d!, %3!d!) not proper list ULARGE_INTEGER syntax.\n",
  5441. pszPropertyName,
  5442. props.pSyntax->wType,
  5443. props.pSyntax->wFormat );
  5444. return(ERROR_INVALID_DATA);
  5445. }
  5446. //
  5447. // If caller wants the value, allocate a buffer for it.
  5448. //
  5449. if ( pullPropertyValue ) {
  5450. pullPropertyValue->QuadPart = props.pULargeIntegerValue->li.QuadPart;
  5451. }
  5452. //
  5453. // We found the property so return success.
  5454. //
  5455. return(ERROR_SUCCESS);
  5456. } else {
  5457. //
  5458. // Skip the name (value header + size of data).
  5459. //
  5460. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5461. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5462. props.pb += sizeof(*props.pValue) + byteCount;
  5463. //
  5464. // Skip it's value list and endmark.
  5465. //
  5466. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5467. (cbPropertyListSize > 0) )
  5468. {
  5469. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5470. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5471. props.pb += sizeof(*props.pValue) + byteCount;
  5472. }
  5473. cbPropertyListSize -= sizeof(*props.pSyntax);
  5474. props.pb += sizeof(*props.pSyntax);
  5475. }
  5476. }
  5477. return(ERROR_FILE_NOT_FOUND);
  5478. } // ClRtlFindULargeIntegerProperty
  5479. DWORD
  5480. WINAPI
  5481. ClRtlFindLargeIntegerProperty(
  5482. IN const PVOID pPropertyList,
  5483. IN DWORD cbPropertyListSize,
  5484. IN LPCWSTR pszPropertyName,
  5485. OUT PLARGE_INTEGER pllPropertyValue
  5486. )
  5487. /*++
  5488. Routine Description:
  5489. Finds the specified LARGE_INTEGER property in the Property List buffer
  5490. pointed at by pPropertyList.
  5491. Arguments:
  5492. pPropertyList - a property list.
  5493. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5494. pszPropertyName - the property name to look for in the buffer.
  5495. pllPropertyValue - the matching ULARGE_INTEGER value found.
  5496. Return Value:
  5497. ERROR_SUCCESS if successful.
  5498. ERROR_INVALID_DATA -
  5499. ERROR_FILE_NOT_FOUND -
  5500. A Win32 error code on failure.
  5501. --*/
  5502. {
  5503. CLUSPROP_BUFFER_HELPER props;
  5504. LPWSTR valueData;
  5505. DWORD itemCount;
  5506. DWORD byteCount;
  5507. props.pb = (LPBYTE) pPropertyList;
  5508. itemCount = *(props.pdw++);
  5509. cbPropertyListSize -= sizeof(DWORD);
  5510. while ( itemCount-- &&
  5511. ((LONG)cbPropertyListSize > 0) ) {
  5512. //
  5513. // If we found the specified property, validate the entry and return
  5514. // the value to the caller.
  5515. //
  5516. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5517. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5518. //
  5519. // Calculate the size of the name and move to the value.
  5520. //
  5521. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5522. props.pb += sizeof(*props.pValue) + byteCount;
  5523. //
  5524. // Make sure this is a large int property.
  5525. //
  5526. if ( props.pLargeIntegerValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_LARGE_INTEGER ) {
  5527. ClRtlDbgPrint(LOG_CRITICAL,
  5528. "ClRtlFindLargeIntegerProperty: Property '%1!ls!' syntax "
  5529. "(%2!d!, %3!d!) not proper list ULARGE_INTEGER syntax.\n",
  5530. pszPropertyName,
  5531. props.pSyntax->wType,
  5532. props.pSyntax->wFormat );
  5533. return(ERROR_INVALID_DATA);
  5534. }
  5535. //
  5536. // If caller wants the value, allocate a buffer for it.
  5537. //
  5538. if ( pllPropertyValue ) {
  5539. pllPropertyValue->QuadPart = props.pLargeIntegerValue->li.QuadPart;
  5540. }
  5541. //
  5542. // We found the property so return success.
  5543. //
  5544. return(ERROR_SUCCESS);
  5545. } else {
  5546. //
  5547. // Skip the name (value header + size of data).
  5548. //
  5549. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5550. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5551. props.pb += sizeof(*props.pValue) + byteCount;
  5552. //
  5553. // Skip it's value list and endmark.
  5554. //
  5555. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5556. (cbPropertyListSize > 0) )
  5557. {
  5558. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5559. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5560. props.pb += sizeof(*props.pValue) + byteCount;
  5561. }
  5562. cbPropertyListSize -= sizeof(*props.pSyntax);
  5563. props.pb += sizeof(*props.pSyntax);
  5564. }
  5565. }
  5566. return(ERROR_FILE_NOT_FOUND);
  5567. } // ClRtlFindLargeIntegerProperty
  5568. DWORD
  5569. WINAPI
  5570. ClRtlFindBinaryProperty(
  5571. IN const PVOID pPropertyList,
  5572. IN DWORD cbPropertyListSize,
  5573. IN LPCWSTR pszPropertyName,
  5574. OUT LPBYTE * pbPropertyValue,
  5575. OUT LPDWORD pcbPropertyValueSize
  5576. )
  5577. /*++
  5578. Routine Description:
  5579. Finds the specified binary property in the Property List buffer pointed at
  5580. by pPropertyList.
  5581. Arguments:
  5582. pPropertyList - a property list.
  5583. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5584. pszPropertyName - the property name to look for in the buffer.
  5585. pbPropertyValue - the matching binary value found.
  5586. pcbPropertyValueSize - the length of the matching binary value found.
  5587. Return Value:
  5588. ERROR_SUCCESS if successful.
  5589. ERROR_INVALID_DATA -
  5590. ERROR_NOT_ENOUGH_MEMORY -
  5591. ERROR_FILE_NOT_FOUND -
  5592. A Win32 error code on failure.
  5593. --*/
  5594. {
  5595. CLUSPROP_BUFFER_HELPER props;
  5596. PBYTE valueData;
  5597. DWORD itemCount;
  5598. DWORD byteCount;
  5599. props.pb = (LPBYTE) pPropertyList;
  5600. itemCount = *(props.pdw++);
  5601. cbPropertyListSize -= sizeof(DWORD);
  5602. while ( itemCount-- &&
  5603. ((LONG)cbPropertyListSize > 0) ) {
  5604. //
  5605. // If we found the specified property, validate the entry and return
  5606. // the value to the caller.
  5607. //
  5608. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5609. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5610. //
  5611. // Calculate the size of the name and move to the value.
  5612. //
  5613. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5614. props.pb += sizeof(*props.pValue) + byteCount;
  5615. //
  5616. // Make sure this is a binary property.
  5617. //
  5618. if ( props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_BINARY ) {
  5619. 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 );
  5620. return(ERROR_INVALID_DATA);
  5621. }
  5622. //
  5623. // If caller wants the value, allocate a buffer for it.
  5624. //
  5625. if ( pbPropertyValue ) {
  5626. valueData = (PBYTE) LocalAlloc( LMEM_FIXED, props.pBinaryValue->cbLength );
  5627. if ( !valueData ) {
  5628. return(ERROR_NOT_ENOUGH_MEMORY);
  5629. }
  5630. CopyMemory( valueData, props.pBinaryValue->rgb, props.pBinaryValue->cbLength );
  5631. *pbPropertyValue = valueData;
  5632. }
  5633. //
  5634. // If caller wants the value size
  5635. //
  5636. if ( pcbPropertyValueSize ) {
  5637. *pcbPropertyValueSize = props.pBinaryValue->cbLength;
  5638. }
  5639. //
  5640. // We found the property so return success.
  5641. //
  5642. return(ERROR_SUCCESS);
  5643. } else {
  5644. //
  5645. // Skip the name (value header + size of data).
  5646. //
  5647. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5648. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5649. props.pb += sizeof(*props.pValue) + byteCount;
  5650. //
  5651. // Skip it's value list and endmark.
  5652. //
  5653. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5654. (cbPropertyListSize > 0) ) {
  5655. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5656. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5657. props.pb += sizeof(*props.pValue) + byteCount;
  5658. }
  5659. cbPropertyListSize -= sizeof(*props.pSyntax);
  5660. props.pb += sizeof(*props.pSyntax);
  5661. }
  5662. }
  5663. return(ERROR_FILE_NOT_FOUND);
  5664. } // ClRtlFindBinaryProperty
  5665. DWORD
  5666. WINAPI
  5667. ClRtlFindMultiSzProperty(
  5668. IN const PVOID pPropertyList,
  5669. IN DWORD cbPropertyListSize,
  5670. IN LPCWSTR pszPropertyName,
  5671. OUT LPWSTR * pszPropertyValue,
  5672. OUT LPDWORD pcbPropertyValueSize
  5673. )
  5674. /*++
  5675. Routine Description:
  5676. Finds the specified multiple string property in the Property List buffer
  5677. pointed at by pPropertyList.
  5678. Arguments:
  5679. pPropertyList - a property list.
  5680. cbPropertyListSize - the size in bytes of the data in pPropertyList.
  5681. pszPropertyName - the property name to look for in the buffer.
  5682. pszPropertyValue - the matching multiple string value found.
  5683. pcbPropertyValueSize - the length of the matching multiple string value found.
  5684. Return Value:
  5685. ERROR_SUCCESS if successful.
  5686. ERROR_INVALID_DATA -
  5687. ERROR_NOT_ENOUGH_MEMORY -
  5688. ERROR_FILE_NOT_FOUND -
  5689. A Win32 error code on failure.
  5690. --*/
  5691. {
  5692. CLUSPROP_BUFFER_HELPER props;
  5693. LPWSTR valueData;
  5694. DWORD itemCount;
  5695. DWORD byteCount;
  5696. props.pb = (LPBYTE) pPropertyList;
  5697. itemCount = *(props.pdw++);
  5698. cbPropertyListSize -= sizeof(DWORD);
  5699. while ( itemCount-- &&
  5700. ((LONG)cbPropertyListSize > 0) ) {
  5701. //
  5702. // If we found the specified property, validate the entry and return
  5703. // the value to the caller.
  5704. //
  5705. if ( (props.pName->Syntax.dw == CLUSPROP_SYNTAX_NAME) &&
  5706. (lstrcmpiW( props.pName->sz, pszPropertyName ) == 0) ) {
  5707. //
  5708. // Calculate the size of the name and move to the value.
  5709. //
  5710. byteCount = ALIGN_CLUSPROP(props.pName->cbLength);
  5711. props.pb += sizeof(*props.pValue) + byteCount;
  5712. //
  5713. // Make sure this is a multi-sz property.
  5714. //
  5715. if ( props.pStringValue->Syntax.dw != CLUSPROP_SYNTAX_LIST_VALUE_MULTI_SZ ) {
  5716. 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 );
  5717. return(ERROR_INVALID_DATA);
  5718. }
  5719. //
  5720. // If caller wants the value, allocate a buffer for it.
  5721. //
  5722. if ( pszPropertyValue ) {
  5723. valueData = (LPWSTR) LocalAlloc( LMEM_FIXED, props.pMultiSzValue->cbLength );
  5724. if ( !valueData ) {
  5725. return(ERROR_NOT_ENOUGH_MEMORY);
  5726. }
  5727. CopyMemory( valueData, props.pBinaryValue->rgb, props.pMultiSzValue->cbLength );
  5728. *pszPropertyValue = valueData;
  5729. }
  5730. //
  5731. // If caller wants the value size
  5732. //
  5733. if ( pcbPropertyValueSize ) {
  5734. *pcbPropertyValueSize = props.pMultiSzValue->cbLength;
  5735. }
  5736. //
  5737. // We found the property so return success.
  5738. //
  5739. return(ERROR_SUCCESS);
  5740. } else {
  5741. //
  5742. // Skip the name (value header + size of data).
  5743. //
  5744. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5745. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5746. props.pb += sizeof(*props.pValue) + byteCount;
  5747. //
  5748. // Skip it's value list and endmark.
  5749. //
  5750. while ( (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK) &&
  5751. (cbPropertyListSize > 0) ) {
  5752. byteCount = ALIGN_CLUSPROP(props.pValue->cbLength);
  5753. cbPropertyListSize -= sizeof(*props.pValue) + byteCount;
  5754. props.pb += sizeof(*props.pValue) + byteCount;
  5755. }
  5756. cbPropertyListSize -= sizeof(*props.pSyntax);
  5757. props.pb += sizeof(*props.pSyntax);
  5758. }
  5759. }
  5760. return(ERROR_FILE_NOT_FOUND);
  5761. } // ClRtlFindMultiSzProperty
  5762. DWORD
  5763. WINAPI
  5764. ClRtlGetBinaryValue(
  5765. IN HKEY hkeyClusterKey,
  5766. IN LPCWSTR pszValueName,
  5767. OUT LPBYTE * ppbOutValue,
  5768. OUT LPDWORD pcbOutValueSize,
  5769. IN const PCLUSTER_REG_APIS pClusterRegApis
  5770. )
  5771. /*++
  5772. Routine Description:
  5773. Queries a REG_BINARY or REG_MULTI_SZ value out of the cluster
  5774. database and allocates the necessary storage for it.
  5775. Arguments:
  5776. hkeyClusterKey - Supplies the cluster key where the value is stored
  5777. pszValueName - Supplies the name of the value.
  5778. ppbOutValue - Supplies the address of a pointer in which to return the value.
  5779. pcbOutValueSize - Supplies the address of a DWORD in which to return the
  5780. size of the value.
  5781. pfnQueryValue - Address of QueryValue function.
  5782. Return Value:
  5783. ERROR_SUCCESS - The value was read successfully.
  5784. ERROR_BAD_ARGUMENTS -
  5785. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory for the value.
  5786. Win32 error code - The operation failed.
  5787. --*/
  5788. {
  5789. LPBYTE value = NULL;
  5790. DWORD valueSize;
  5791. DWORD valueType;
  5792. DWORD status;
  5793. PVOID key = NULL;
  5794. CRegistryValueName rvn;
  5795. //
  5796. // Initialize the output parameters.
  5797. //
  5798. *ppbOutValue = NULL;
  5799. *pcbOutValueSize = 0;
  5800. if ( (hkeyClusterKey == NULL) ||
  5801. (pClusterRegApis == NULL) ||
  5802. (pClusterRegApis->pfnQueryValue == NULL) ) {
  5803. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetBinaryValue: hkeyClusterKey, pClusterRegApis, or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
  5804. return(ERROR_BAD_ARGUMENTS);
  5805. }
  5806. //
  5807. // Use the wrapper class CRegistryValueName to parse value name to see if it
  5808. // contains a backslash.
  5809. //
  5810. status = rvn.ScInit( pszValueName, NULL );
  5811. if ( status != ERROR_SUCCESS )
  5812. {
  5813. return status;
  5814. }
  5815. //
  5816. // If the value resides at a different location, open the key.
  5817. //
  5818. if ( rvn.PszKeyName() != NULL ) {
  5819. if ( (pClusterRegApis->pfnOpenKey == NULL) ||
  5820. (pClusterRegApis->pfnCloseKey == NULL) ) {
  5821. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetBinaryValue: pClusterRegApis->pfnOpenKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
  5822. return(ERROR_BAD_ARGUMENTS);
  5823. }
  5824. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  5825. rvn.PszKeyName(),
  5826. KEY_READ,
  5827. &key);
  5828. } else {
  5829. key = hkeyClusterKey;
  5830. }
  5831. //
  5832. // Dummy do-while loop to avoid gotos.
  5833. //
  5834. do
  5835. {
  5836. //
  5837. // Get the size of the value so we know how much to allocate.
  5838. //
  5839. valueSize = 0;
  5840. status = (*pClusterRegApis->pfnQueryValue)( key,
  5841. rvn.PszName(),
  5842. &valueType,
  5843. NULL,
  5844. &valueSize );
  5845. if ( (status != ERROR_SUCCESS) &&
  5846. (status != ERROR_MORE_DATA) ) {
  5847. break;
  5848. }
  5849. //if the size is zero, just return
  5850. if (valueSize == 0)
  5851. {
  5852. break;
  5853. }
  5854. //
  5855. // Allocate a buffer to read the value into.
  5856. //
  5857. value = (LPBYTE) LocalAlloc( LMEM_FIXED, valueSize );
  5858. if ( value == NULL ) {
  5859. status = ERROR_NOT_ENOUGH_MEMORY;
  5860. break;
  5861. }
  5862. //
  5863. // Read the value from the cluster database.
  5864. //
  5865. status = (*pClusterRegApis->pfnQueryValue)( key,
  5866. pszValueName,
  5867. &valueType,
  5868. (LPBYTE)value,
  5869. &valueSize );
  5870. if ( status != ERROR_SUCCESS ) {
  5871. LocalFree( value );
  5872. } else {
  5873. *ppbOutValue = value;
  5874. *pcbOutValueSize = valueSize;
  5875. }
  5876. }
  5877. while (FALSE);
  5878. //
  5879. // Close the key if we opened it.
  5880. //
  5881. if ( (rvn.PszKeyName() != NULL) &&
  5882. (key != NULL) ) {
  5883. (*pClusterRegApis->pfnCloseKey)( key );
  5884. }
  5885. return(status);
  5886. } // ClRtlGetBinaryValue
  5887. LPWSTR
  5888. WINAPI
  5889. ClRtlGetSzValue(
  5890. IN HKEY hkeyClusterKey,
  5891. IN LPCWSTR pszValueName,
  5892. IN const PCLUSTER_REG_APIS pClusterRegApis
  5893. )
  5894. /*++
  5895. Routine Description:
  5896. Queries a REG_SZ or REG_EXPAND_SZ value out of the cluster database
  5897. and allocates the necessary storage for it.
  5898. Arguments:
  5899. hkeyClusterKey - Supplies the cluster key where the value is stored
  5900. pszValueName - Supplies the name of the value.
  5901. pfnQueryValue - Address of QueryValue function.
  5902. Return Value:
  5903. A pointer to a buffer containing the value if successful.
  5904. NULL if unsuccessful. Call GetLastError() to get more details.
  5905. --*/
  5906. {
  5907. PWSTR value;
  5908. DWORD valueSize;
  5909. DWORD valueType;
  5910. DWORD status;
  5911. PVOID key = NULL;
  5912. CRegistryValueName rvn;
  5913. if ( (hkeyClusterKey == NULL) ||
  5914. (pClusterRegApis == NULL) ||
  5915. (pClusterRegApis->pfnQueryValue == NULL) ) {
  5916. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetSzValue: hkeyClusterKey, pClusterRegApis, or pClusterRegApis->pfnQueryValue == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
  5917. SetLastError(ERROR_BAD_ARGUMENTS);
  5918. return(NULL);
  5919. }
  5920. //
  5921. // Use the wrapper class CRegistryValueName to parse value name to see if it
  5922. // contains a backslash.
  5923. //
  5924. status = rvn.ScInit( pszValueName, NULL );
  5925. if ( status != ERROR_SUCCESS )
  5926. {
  5927. SetLastError(status);
  5928. return(NULL);
  5929. }
  5930. //
  5931. // If the value resides at a different location, open the key.
  5932. //
  5933. if ( rvn.PszKeyName() != NULL ) {
  5934. if ( (pClusterRegApis->pfnOpenKey == NULL) ||
  5935. (pClusterRegApis->pfnCloseKey == NULL) ) {
  5936. ClRtlDbgPrint( LOG_CRITICAL, "ClRtlGetSzValue: pClusterRegApis->pfnOpenKey or pfnCloseKey == NULL. Returning ERROR_BAD_ARGUMENTS.\n" );
  5937. SetLastError(ERROR_BAD_ARGUMENTS);
  5938. return(NULL);
  5939. }
  5940. status = (*pClusterRegApis->pfnOpenKey)( hkeyClusterKey,
  5941. rvn.PszKeyName(),
  5942. KEY_READ,
  5943. &key);
  5944. } else {
  5945. key = hkeyClusterKey;
  5946. }
  5947. //
  5948. // Dummy do-while loop to avoid gotos.
  5949. //
  5950. do
  5951. {
  5952. //
  5953. // Get the size of the value so we know how much to allocate.
  5954. //
  5955. valueSize = 0;
  5956. status = (*pClusterRegApis->pfnQueryValue)( key,
  5957. rvn.PszName(),
  5958. &valueType,
  5959. NULL,
  5960. &valueSize );
  5961. if ( (status != ERROR_SUCCESS) &&
  5962. (status != ERROR_MORE_DATA) ) {
  5963. SetLastError( status );
  5964. value = NULL;
  5965. break;
  5966. }
  5967. //
  5968. // Add on the size of the null terminator.
  5969. //
  5970. valueSize += sizeof(UNICODE_NULL);
  5971. //
  5972. // Allocate a buffer to read the string into.
  5973. //
  5974. value = (PWSTR) LocalAlloc( LMEM_FIXED, valueSize );
  5975. if ( value == NULL ) {
  5976. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5977. value = NULL;
  5978. break;
  5979. }
  5980. //
  5981. // Read the value from the cluster database.
  5982. //
  5983. status = (*pClusterRegApis->pfnQueryValue)( key,
  5984. rvn.PszName(),
  5985. &valueType,
  5986. (LPBYTE)value,
  5987. &valueSize );
  5988. if ( status != ERROR_SUCCESS ) {
  5989. LocalFree( value );
  5990. value = NULL;
  5991. } else if ( (valueType != REG_SZ) &&
  5992. (valueType != REG_EXPAND_SZ) &&
  5993. (valueType != REG_MULTI_SZ) ) {
  5994. status = ERROR_INVALID_PARAMETER;
  5995. LocalFree( value );
  5996. SetLastError( status );
  5997. value = NULL;
  5998. }
  5999. }
  6000. while (FALSE);
  6001. //
  6002. // Close the key if we opened it.
  6003. //
  6004. if ( (rvn.PszKeyName() != NULL) &&
  6005. (key != NULL) ) {
  6006. (*pClusterRegApis->pfnCloseKey)( key );
  6007. }
  6008. return(value);
  6009. } // ClRtlGetSzValue
  6010. DWORD
  6011. WINAPI
  6012. ClRtlDupParameterBlock(
  6013. OUT LPBYTE pOutParams,
  6014. IN const LPBYTE pInParams,
  6015. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
  6016. )
  6017. /*++
  6018. Routine Description:
  6019. Deallocates any buffers allocated for a parameter block that are
  6020. different than the buffers used for the input parameter block.
  6021. Arguments:
  6022. pOutParams - Parameter block to return.
  6023. pInParams - Reference parameter block.
  6024. pPropertyTable - Pointer to the property table to process.
  6025. Return Value:
  6026. ERROR_SUCCESS - Parameter block duplicated successfully.
  6027. --*/
  6028. {
  6029. DWORD status = ERROR_SUCCESS;
  6030. PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
  6031. LPWSTR UNALIGNED * ppszInValue;
  6032. DWORD * pdwInValue;
  6033. ULARGE_INTEGER * pullInValue;
  6034. LPWSTR UNALIGNED * ppszOutValue;
  6035. DWORD * pdwOutValue;
  6036. ULARGE_INTEGER * pullOutValue;
  6037. while ( propertyItem->Name != NULL ) {
  6038. switch ( propertyItem->Format ) {
  6039. case CLUSPROP_FORMAT_DWORD:
  6040. case CLUSPROP_FORMAT_LONG:
  6041. pdwInValue = (DWORD *) &pInParams[propertyItem->Offset];
  6042. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset];
  6043. *pdwOutValue = *pdwInValue;
  6044. break;
  6045. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  6046. case CLUSPROP_FORMAT_LARGE_INTEGER:
  6047. pullInValue = (ULARGE_INTEGER *) &pInParams[propertyItem->Offset];
  6048. pullOutValue = (ULARGE_INTEGER *) &pOutParams[propertyItem->Offset];
  6049. pullOutValue->u = pullInValue->u;
  6050. break;
  6051. case CLUSPROP_FORMAT_SZ:
  6052. case CLUSPROP_FORMAT_EXPAND_SZ:
  6053. ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  6054. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  6055. if ( *ppszInValue == NULL ) {
  6056. if ( propertyItem->lpDefault != NULL ) {
  6057. *ppszOutValue = (LPWSTR) LocalAlloc(
  6058. LMEM_FIXED,
  6059. (lstrlenW( (LPCWSTR) propertyItem->lpDefault ) + 1) * sizeof(WCHAR)
  6060. );
  6061. if ( *ppszOutValue == NULL ) {
  6062. status = GetLastError();
  6063. } else {
  6064. lstrcpyW( *ppszOutValue, (LPCWSTR) propertyItem->lpDefault );
  6065. }
  6066. } else {
  6067. *ppszOutValue = NULL;
  6068. }
  6069. } else {
  6070. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, (lstrlenW( *ppszInValue ) + 1) * sizeof(WCHAR) );
  6071. if ( *ppszOutValue == NULL ) {
  6072. status = GetLastError();
  6073. } else {
  6074. lstrcpyW( *ppszOutValue, *ppszInValue );
  6075. }
  6076. }
  6077. break;
  6078. case CLUSPROP_FORMAT_MULTI_SZ:
  6079. case CLUSPROP_FORMAT_BINARY:
  6080. ppszInValue = (LPWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  6081. pdwInValue = (DWORD *) &pInParams[propertyItem->Offset + sizeof(LPCWSTR)];
  6082. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  6083. pdwOutValue = (DWORD *) &pOutParams[propertyItem->Offset + sizeof(LPWSTR)];
  6084. if ( *ppszInValue == NULL ) {
  6085. if ( propertyItem->lpDefault != NULL ) {
  6086. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, propertyItem->Minimum );
  6087. if ( *ppszOutValue == NULL ) {
  6088. status = GetLastError();
  6089. *pdwOutValue = 0;
  6090. } else {
  6091. *pdwOutValue = propertyItem->Minimum;
  6092. CopyMemory( *ppszOutValue, (const PVOID) propertyItem->lpDefault, *pdwOutValue );
  6093. }
  6094. } else {
  6095. *ppszOutValue = NULL;
  6096. *pdwOutValue = 0;
  6097. }
  6098. } else {
  6099. *ppszOutValue = (LPWSTR) LocalAlloc( LMEM_FIXED, *pdwInValue );
  6100. if ( *ppszOutValue == NULL ) {
  6101. status = GetLastError();
  6102. *pdwOutValue = 0;
  6103. } else {
  6104. CopyMemory( *ppszOutValue, *ppszInValue, *pdwInValue );
  6105. *pdwOutValue = *pdwInValue;
  6106. }
  6107. }
  6108. break;
  6109. }
  6110. propertyItem++;
  6111. }
  6112. //
  6113. // If an error occurred, make sure we don't leak memory.
  6114. //
  6115. if ( status != ERROR_SUCCESS ) {
  6116. ClRtlFreeParameterBlock( pOutParams, pInParams, pPropertyTable );
  6117. }
  6118. return(status);
  6119. } // ClRtlDupParameterBlock
  6120. void
  6121. WINAPI
  6122. ClRtlFreeParameterBlock(
  6123. IN OUT LPBYTE pOutParams,
  6124. IN const LPBYTE pInParams,
  6125. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable
  6126. )
  6127. /*++
  6128. Routine Description:
  6129. Deallocates any buffers allocated for a parameter block that are
  6130. different than the buffers used for the input parameter block.
  6131. Arguments:
  6132. pOutParams - Parameter block to free.
  6133. pInParams - Reference parameter block.
  6134. pPropertyTable - Pointer to the property table to process.
  6135. Return Value:
  6136. None.
  6137. --*/
  6138. {
  6139. PRESUTIL_PROPERTY_ITEM propertyItem = pPropertyTable;
  6140. LPCWSTR UNALIGNED * ppszInValue;
  6141. LPWSTR UNALIGNED * ppszOutValue;
  6142. while ( propertyItem->Name != NULL ) {
  6143. switch ( propertyItem->Format ) {
  6144. case CLUSPROP_FORMAT_SZ:
  6145. case CLUSPROP_FORMAT_EXPAND_SZ:
  6146. case CLUSPROP_FORMAT_MULTI_SZ:
  6147. case CLUSPROP_FORMAT_BINARY:
  6148. ppszInValue = (LPCWSTR UNALIGNED *) &pInParams[propertyItem->Offset];
  6149. ppszOutValue = (LPWSTR UNALIGNED *) &pOutParams[propertyItem->Offset];
  6150. if ( (pInParams == NULL) || (*ppszInValue != *ppszOutValue) ) {
  6151. LocalFree( *ppszOutValue );
  6152. }
  6153. break;
  6154. }
  6155. propertyItem++;
  6156. }
  6157. } // ClRtlFreeParameterBlock
  6158. DWORD
  6159. WINAPI
  6160. ClRtlMarshallPropertyTable(
  6161. IN PRESUTIL_PROPERTY_ITEM pPropertyTable,
  6162. IN OUT DWORD dwSize,
  6163. IN OUT LPBYTE pBuffer,
  6164. OUT DWORD *Required
  6165. )
  6166. /*++
  6167. Routine Description
  6168. Rohit (rjain) : It marshalls the pPropertyTable into a buffer so that the
  6169. buffer can be passed as an argument to the NmUpdatePerformFixups2 handler
  6170. This function assumes that the value field in all the elements of the
  6171. table is 0.
  6172. Arguments
  6173. pPropertyTable - This table is converted to buffer
  6174. dwSize - size in bytes of the pbuffer supplied
  6175. pbuffer - byte array into which pPropertyTable is copied
  6176. Required - number of bytes required
  6177. Return Value
  6178. returns
  6179. ERROR_SUCCESS on success,
  6180. ERROR_MORE_DATA if the size of pbuffer is insufficient
  6181. ++*/
  6182. {
  6183. DWORD dwPosition=sizeof(DWORD);
  6184. PRESUTIL_PROPERTY_ITEM pPropertyItem=pPropertyTable;
  6185. BOOL copying = TRUE;
  6186. DWORD items=0;
  6187. DWORD dwNameLength;
  6188. DWORD dwKeyLength;
  6189. DWORD status=ERROR_SUCCESS;
  6190. *Required=sizeof(DWORD); // first DWORD will contain the number of items in PropertyTable
  6191. while(pPropertyItem->Name != NULL)
  6192. {
  6193. items++;
  6194. dwNameLength=(lstrlenW(pPropertyItem->Name)+1)*sizeof(WCHAR);
  6195. if(pPropertyItem->KeyName==NULL)
  6196. dwKeyLength=0;
  6197. else
  6198. dwKeyLength=(lstrlenW(pPropertyItem->KeyName)+1)*sizeof(WCHAR);
  6199. *Required+=(dwNameLength+dwKeyLength+8*sizeof(DWORD));
  6200. // if pbufer is smaller than needed, copying is turned off
  6201. // and only the required size is calculated
  6202. if ((copying && (dwSize < *Required)))
  6203. copying=FALSE;
  6204. if(copying)
  6205. {
  6206. // copy length of name and then the name itself
  6207. CopyMemory(pBuffer+dwPosition,&dwNameLength,sizeof(DWORD));
  6208. dwPosition+=(sizeof(DWORD));
  6209. CopyMemory(pBuffer+dwPosition,pPropertyItem->Name,dwNameLength);
  6210. dwPosition+=dwNameLength;
  6211. //copy length of keyname and then the keyname itself
  6212. CopyMemory(pBuffer+dwPosition,&dwKeyLength,sizeof(DWORD));
  6213. dwPosition+=(sizeof(DWORD));
  6214. if(dwKeyLength!=0)
  6215. {
  6216. CopyMemory(pBuffer+dwPosition,pPropertyItem->KeyName,dwKeyLength);
  6217. dwPosition+=dwKeyLength;
  6218. }
  6219. //now copy remaining fields
  6220. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Format),sizeof(DWORD));
  6221. dwPosition+=(sizeof(DWORD));
  6222. // ISSUE-2000/11/21-charlwi
  6223. // this needs to be fixed for Large Int properties since they
  6224. // don't store their values in Default, Minimum, and Maximum
  6225. //IMP: the default value is always assumed to be a DWORD. This is
  6226. // because the values for properties in PropertyTable are stored
  6227. // in a seperate parameter list. See ClRtlSetPropertyTable
  6228. //
  6229. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Default),sizeof(DWORD));
  6230. dwPosition+=(sizeof(DWORD));
  6231. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Minimum),sizeof(DWORD));
  6232. dwPosition+=(sizeof(DWORD));
  6233. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Maximum),sizeof(DWORD));
  6234. dwPosition+=(sizeof(DWORD));
  6235. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Flags),sizeof(DWORD));
  6236. dwPosition+=(sizeof(DWORD));
  6237. CopyMemory(pBuffer+dwPosition,&(pPropertyItem->Offset),sizeof(DWORD));
  6238. dwPosition+=(sizeof(DWORD));
  6239. }
  6240. //
  6241. // Advance to the next property.
  6242. //
  6243. pPropertyItem++;
  6244. }
  6245. if(copying)
  6246. {
  6247. CopyMemory(pBuffer,&items,sizeof(DWORD));
  6248. status=ERROR_SUCCESS;
  6249. }
  6250. else
  6251. status=ERROR_MORE_DATA;
  6252. return status;
  6253. } // MarshallPropertyTable
  6254. DWORD
  6255. WINAPI
  6256. ClRtlUnmarshallPropertyTable(
  6257. IN OUT PRESUTIL_PROPERTY_ITEM *ppPropertyTable,
  6258. IN LPBYTE pBuffer
  6259. )
  6260. /*++
  6261. Routine Description
  6262. Rohit (rjain) : It unmarshalls the pBuffer into a RESUTIL_PROPERTY_ITEM table
  6263. Arguments
  6264. pPropertyTable - This is the resulting table
  6265. pbuffer - marshalled byte array
  6266. Return Value
  6267. returns
  6268. ERROR_SUCCESS on success,
  6269. Win32 error on error
  6270. ++*/
  6271. {
  6272. PRESUTIL_PROPERTY_ITEM propertyItem;
  6273. DWORD items;
  6274. DWORD dwPosition=sizeof(DWORD);
  6275. DWORD dwLength;
  6276. DWORD i;
  6277. DWORD status=ERROR_SUCCESS;
  6278. if((pBuffer==NULL) ||(ppPropertyTable==NULL))
  6279. {
  6280. ClRtlDbgPrint( LOG_CRITICAL, "[ClRtl] Uncopy PropertyTable: Bad Argumnets\r\n");
  6281. return ERROR_BAD_ARGUMENTS;
  6282. }
  6283. CopyMemory(&items,pBuffer,sizeof(DWORD));
  6284. *ppPropertyTable=(PRESUTIL_PROPERTY_ITEM)LocalAlloc(LMEM_FIXED,(items+1)*sizeof(RESUTIL_PROPERTY_ITEM));
  6285. if(*ppPropertyTable == NULL)
  6286. {
  6287. status=GetLastError();
  6288. goto FnExit;
  6289. }
  6290. propertyItem=*ppPropertyTable;
  6291. for(i=0; i<items; i++)
  6292. {
  6293. CopyMemory(&dwLength,pBuffer+dwPosition,sizeof(DWORD));
  6294. dwPosition+=sizeof(DWORD);
  6295. propertyItem->Name = NULL;
  6296. propertyItem->Name=(LPWSTR)LocalAlloc(LMEM_FIXED,dwLength);
  6297. if(propertyItem->Name == NULL)
  6298. {
  6299. status=GetLastError();
  6300. goto FnExit;
  6301. }
  6302. CopyMemory(propertyItem->Name,pBuffer+dwPosition,dwLength);
  6303. dwPosition+=dwLength;
  6304. CopyMemory(&dwLength,pBuffer+dwPosition,sizeof(DWORD));
  6305. dwPosition+=sizeof(DWORD);
  6306. propertyItem->KeyName=NULL;
  6307. if (dwLength!=0)
  6308. {
  6309. propertyItem->KeyName=(LPWSTR)LocalAlloc(LMEM_FIXED,dwLength);
  6310. if(propertyItem->KeyName == NULL)
  6311. {
  6312. status=GetLastError();
  6313. goto FnExit;
  6314. }
  6315. CopyMemory(propertyItem->KeyName,pBuffer+dwPosition,dwLength);
  6316. dwPosition+=dwLength;
  6317. }
  6318. //now rest of the fields - all DWORDS
  6319. CopyMemory(&(propertyItem->Format),pBuffer+dwPosition,sizeof(DWORD));
  6320. dwPosition+=(sizeof(DWORD));
  6321. // ISSUE-2000/11/21-charlwi
  6322. // this needs to be fixed for Large Int properties since they don't
  6323. // store their values in Default, Minimum, and Maximum
  6324. // IMP: the default value is always passed as a DWORD. This is
  6325. // because the values for properties in PropertyTable are stored
  6326. // in a seperate parameter list so the value here won't be used.
  6327. // See ClRtlSetPropertyTable
  6328. //
  6329. CopyMemory(&(propertyItem->Default),pBuffer+dwPosition,sizeof(DWORD));
  6330. dwPosition+=(sizeof(DWORD));
  6331. CopyMemory(&(propertyItem->Minimum),pBuffer+dwPosition,sizeof(DWORD));
  6332. dwPosition+=(sizeof(DWORD));
  6333. CopyMemory(&(propertyItem->Maximum),pBuffer+dwPosition,sizeof(DWORD));
  6334. dwPosition+=(sizeof(DWORD));
  6335. CopyMemory(&(propertyItem->Flags), pBuffer+dwPosition,sizeof(DWORD));
  6336. dwPosition+=(sizeof(DWORD));
  6337. CopyMemory(&(propertyItem->Offset), pBuffer+dwPosition,sizeof(DWORD));
  6338. dwPosition+=(sizeof(DWORD));
  6339. propertyItem++;
  6340. }
  6341. // the last entry is marked NULL to indicate the end of table
  6342. propertyItem->Name=NULL;
  6343. FnExit:
  6344. return status;
  6345. } // UnmarshallPropertyTable
  6346. LPWSTR
  6347. WINAPI
  6348. ClRtlExpandEnvironmentStrings(
  6349. IN LPCWSTR pszSrc
  6350. )
  6351. /*++
  6352. Routine Description:
  6353. Expands environment strings and returns an allocated buffer containing
  6354. the result.
  6355. Arguments:
  6356. pszSrc - Source string to expand.
  6357. Return Value:
  6358. A pointer to a buffer containing the value if successful.
  6359. NULL if unsuccessful. Call GetLastError() to get more details.
  6360. --*/
  6361. {
  6362. DWORD status;
  6363. DWORD cchDst = 0;
  6364. LPWSTR pszDst = NULL;
  6365. //
  6366. // Get the required length of the output string.
  6367. //
  6368. cchDst = ExpandEnvironmentStrings( pszSrc, NULL, 0 );
  6369. if ( cchDst == 0 ) {
  6370. status = GetLastError();
  6371. } else {
  6372. //
  6373. // Allocate a buffer for the expanded string.
  6374. //
  6375. pszDst = (LPWSTR) LocalAlloc( LMEM_FIXED, cchDst * sizeof(WCHAR) );
  6376. if ( pszDst == NULL ) {
  6377. status = ERROR_NOT_ENOUGH_MEMORY;
  6378. } else {
  6379. //
  6380. // Get the expanded string.
  6381. //
  6382. cchDst = ExpandEnvironmentStrings( pszSrc, pszDst, cchDst );
  6383. if ( cchDst == 0 ) {
  6384. status = GetLastError();
  6385. LocalFree( pszDst );
  6386. pszDst = NULL;
  6387. } else {
  6388. status = ERROR_SUCCESS;
  6389. }
  6390. }
  6391. }
  6392. if ( status != ERROR_SUCCESS ) {
  6393. SetLastError( status );
  6394. }
  6395. return(pszDst);
  6396. } // ClRtlExpandEnvironmentStrings
  6397. DWORD
  6398. WINAPI
  6399. ClRtlGetPropertyFormatSize(
  6400. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  6401. IN OUT LPDWORD pcbOutPropertyListSize,
  6402. IN OUT LPDWORD pnPropertyCount
  6403. )
  6404. /*++
  6405. Routine Description:
  6406. Get the total number of bytes required for this property item format.
  6407. Arguments:
  6408. pPropertyTableItem - Supplies the property table item for the property
  6409. format whose size is to be returned.
  6410. pcbOutPropertyListSize - Supplies the size of the output buffer
  6411. required to add this property to a property list.
  6412. pnPropertyCount - The count of properties is incremented.
  6413. Return Value:
  6414. ERROR_SUCCESS - Operation was successful.
  6415. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  6416. ERROR_INVALID_PARAMETER -
  6417. A Win32 error code on failure.
  6418. --*/
  6419. {
  6420. WORD formatType;
  6421. DWORD valueLength;
  6422. DWORD nameLength;
  6423. PCLUSPROP_SYNTAX propSyntax;
  6424. //
  6425. // We will return a name, value pair.
  6426. // each of which must be aligned.
  6427. //
  6428. // Get the format type.
  6429. //propSyntax = (PCLUSPROP_SYNTAX) &pPropertyTableItem->Format;
  6430. //formatType = propSyntax->wFormat;
  6431. nameLength = sizeof(CLUSPROP_PROPERTY_NAME)
  6432. + ((wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR))
  6433. + sizeof(CLUSPROP_SYNTAX); // for endmark
  6434. nameLength = ALIGN_CLUSPROP( nameLength );
  6435. valueLength = ALIGN_CLUSPROP( sizeof(CLUSPROP_WORD) );
  6436. *pcbOutPropertyListSize += (valueLength + nameLength);
  6437. *pnPropertyCount += 1;
  6438. return(ERROR_SUCCESS);
  6439. } // ClRtlGetPropertyFormatSize
  6440. DWORD
  6441. WINAPI
  6442. ClRtlGetPropertyFormat(
  6443. IN const PRESUTIL_PROPERTY_ITEM pPropertyTableItem,
  6444. IN OUT PVOID * pOutPropertyBuffer,
  6445. IN OUT LPDWORD pcbOutPropertyBufferSize
  6446. )
  6447. /*++
  6448. Routine Description:
  6449. Get the total number of bytes required for this property item format.
  6450. Arguments:
  6451. pPropertyTableItem - Supplies the property table item for the property
  6452. format whose size is to be returned.
  6453. pcbOutPropertyBuffer - Supplies the size of the output buffer
  6454. required to add this property to a property list.
  6455. pcbPropertyBufferSize - The size
  6456. Return Value:
  6457. ERROR_SUCCESS - Operation was successful.
  6458. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  6459. ERROR_INVALID_PARAMETER -
  6460. A Win32 error code on failure.
  6461. --*/
  6462. {
  6463. WORD formatType;
  6464. DWORD valueLength;
  6465. DWORD nameLength;
  6466. DWORD bytesReturned;
  6467. PCLUSPROP_SYNTAX propSyntax;
  6468. CLUSPROP_BUFFER_HELPER props;
  6469. props.pb = (LPBYTE) *pOutPropertyBuffer;
  6470. //
  6471. // We will return a name, value pair.
  6472. // each of which must be aligned.
  6473. //
  6474. // Get the format type.
  6475. propSyntax = (PCLUSPROP_SYNTAX) &pPropertyTableItem->Format;
  6476. formatType = propSyntax->wFormat;
  6477. //
  6478. // Copy the property name, which includes its syntax and length.
  6479. //
  6480. nameLength = (wcslen( pPropertyTableItem->Name ) + 1) * sizeof(WCHAR);
  6481. props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  6482. props.pName->cbLength = nameLength;
  6483. wcscpy( props.pName->sz, pPropertyTableItem->Name );
  6484. bytesReturned = sizeof(*props.pName) + ALIGN_CLUSPROP( nameLength );
  6485. *pcbOutPropertyBufferSize -= bytesReturned;
  6486. props.pb += bytesReturned;
  6487. //
  6488. // Copy the property value, syntax, length, and ENDMARK
  6489. //
  6490. props.pWordValue->Syntax.wFormat = CLUSPROP_FORMAT_WORD;
  6491. props.pWordValue->Syntax.wType = CLUSPROP_TYPE_LIST_VALUE;
  6492. props.pName->cbLength = sizeof(WORD);
  6493. props.pWordValue->w = formatType;
  6494. bytesReturned = sizeof(*props.pWordValue) + sizeof(CLUSPROP_SYNTAX);
  6495. props.pb += sizeof(*props.pWordValue);
  6496. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  6497. props.pb += sizeof(CLUSPROP_SYNTAX);
  6498. bytesReturned = sizeof(*props.pWordValue) + sizeof(CLUSPROP_SYNTAX);
  6499. *pcbOutPropertyBufferSize -= bytesReturned;
  6500. *pOutPropertyBuffer = props.pb;
  6501. return(ERROR_SUCCESS);
  6502. } // ClRtlGetPropertyFormat
  6503. DWORD
  6504. WINAPI
  6505. ClRtlGetPropertyFormats(
  6506. IN const PRESUTIL_PROPERTY_ITEM pPropertyTable,
  6507. OUT PVOID pOutPropertyFormatList,
  6508. IN DWORD cbOutPropertyFormatListSize,
  6509. OUT LPDWORD pcbBytesReturned,
  6510. OUT LPDWORD pcbRequired
  6511. )
  6512. /*++
  6513. Routine Description:
  6514. Gets the 'known' property formats for a given object - given its
  6515. property table.
  6516. Arguments:
  6517. pPropertyTable - Pointer to the property table to process.
  6518. pOutPropertyList - Supplies the output buffer.
  6519. cbOutPropertyListSize - Supplies the size of the output buffer.
  6520. pcbBytesReturned - The number of bytes returned in pOutPropertyList.
  6521. pcbRequired - The required number of bytes if pOutPropertyList is too small.
  6522. Return Value:
  6523. ERROR_SUCCESS - Operation was successful.
  6524. ERROR_BAD_ARGUMENTS - An argument passed to the function was bad.
  6525. ERROR_NOT_ENOUGH_MEMORY - Error allocating memory.
  6526. A Win32 error code on failure.
  6527. --*/
  6528. {
  6529. DWORD status = ERROR_SUCCESS;
  6530. DWORD itemCount = 0;
  6531. DWORD totalBufferLength = 0;
  6532. PVOID outBuffer = pOutPropertyFormatList;
  6533. DWORD bufferLength = cbOutPropertyFormatListSize;
  6534. PRESUTIL_PROPERTY_ITEM property;
  6535. *pcbBytesReturned = 0;
  6536. *pcbRequired = 0;
  6537. //
  6538. // Clear the output buffer
  6539. //
  6540. if ( pOutPropertyFormatList != NULL ) {
  6541. ZeroMemory( pOutPropertyFormatList, cbOutPropertyFormatListSize );
  6542. }
  6543. //
  6544. // Get the size of all properties for this object.
  6545. //
  6546. property = pPropertyTable;
  6547. while ( property->Name != NULL ) {
  6548. status = ClRtlGetPropertyFormatSize(
  6549. property,
  6550. &totalBufferLength,
  6551. &itemCount );
  6552. if ( status != ERROR_SUCCESS ) {
  6553. break;
  6554. }
  6555. property++;
  6556. }
  6557. //
  6558. // Continue only if the operations so far have been successful.
  6559. //
  6560. if ( status == ERROR_SUCCESS ) {
  6561. //
  6562. // Count for item count at front of return data and endmark.
  6563. //
  6564. totalBufferLength += sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
  6565. //
  6566. // Verify the size of all the properties
  6567. //
  6568. if ( totalBufferLength > cbOutPropertyFormatListSize ) {
  6569. *pcbRequired = totalBufferLength;
  6570. totalBufferLength = 0;
  6571. if ( pOutPropertyFormatList == NULL ) {
  6572. status = ERROR_SUCCESS;
  6573. } else {
  6574. status = ERROR_MORE_DATA;
  6575. }
  6576. } else {
  6577. *(LPDWORD)outBuffer = itemCount;
  6578. outBuffer = (PVOID)( (PUCHAR)outBuffer + sizeof(itemCount) );
  6579. bufferLength -= sizeof(itemCount);
  6580. //
  6581. // Now fetch all of the property Formats.
  6582. //
  6583. property = pPropertyTable;
  6584. while ( property->Name != NULL ) {
  6585. status = ClRtlGetPropertyFormat(
  6586. property,
  6587. &outBuffer,
  6588. &itemCount );
  6589. if ( status != ERROR_SUCCESS ) {
  6590. break;
  6591. }
  6592. property++;
  6593. }
  6594. // Don't forget the ENDMARK
  6595. *(LPDWORD)outBuffer = CLUSPROP_SYNTAX_ENDMARK;
  6596. if ( (status != ERROR_SUCCESS) &&
  6597. (status != ERROR_MORE_DATA) ) {
  6598. totalBufferLength = 0;
  6599. }
  6600. }
  6601. *pcbBytesReturned = totalBufferLength;
  6602. }
  6603. return(status);
  6604. } // ClRtlGetPropertyFormats