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.

993 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Server side support for Cluster registry database APIs
  7. Author:
  8. John Vert (jvert) 8-Mar-1996
  9. Revision History:
  10. --*/
  11. #include "apip.h"
  12. PAPI_HANDLE
  13. ApipMakeKeyHandle(
  14. IN HDMKEY Key
  15. )
  16. /*++
  17. Routine Description:
  18. Allocates and initializes an API_HANDLE structure for the
  19. specified HDMKEY.
  20. Arguments:
  21. Key - Supplies the HDMKEY.
  22. Return Value:
  23. A pointer to the initialized API_HANDLE structure on success.
  24. NULL on memory allocation failure.
  25. --*/
  26. {
  27. PAPI_HANDLE Handle;
  28. Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
  29. if (Handle == NULL) {
  30. return(NULL);
  31. }
  32. Handle->Type = API_KEY_HANDLE;
  33. Handle->Flags = 0;
  34. Handle->Key = Key;
  35. InitializeListHead(&Handle->NotifyList);
  36. return(Handle);
  37. }
  38. HKEY_RPC
  39. s_ApiGetRootKey(
  40. IN handle_t IDL_handle,
  41. IN DWORD samDesired,
  42. OUT error_status_t *Status
  43. )
  44. /*++
  45. Routine Description:
  46. Opens the registry key at the root of the cluster registry database
  47. Arguments:
  48. IDL_handle - Supplies RPC binding handle, not used.
  49. samDesired - Supplies requested security access
  50. Status - Returns error code, if any.
  51. Return Value:
  52. A handle to the opened registry key.
  53. --*/
  54. {
  55. DWORD Error;
  56. HDMKEY Key;
  57. PAPI_HANDLE Handle=NULL;
  58. *Status = RpcImpersonateClient(NULL);
  59. if (*Status != RPC_S_OK)
  60. {
  61. goto FnExit;
  62. }
  63. Key = DmGetRootKey(samDesired);
  64. RpcRevertToSelf();
  65. if (Key == NULL) {
  66. *Status = GetLastError();
  67. } else {
  68. Handle = ApipMakeKeyHandle(Key);
  69. if (Handle == NULL) {
  70. DmCloseKey(Key);
  71. *Status = ERROR_NOT_ENOUGH_MEMORY;
  72. } else {
  73. *Status = ERROR_SUCCESS;
  74. }
  75. }
  76. FnExit:
  77. return(Handle);
  78. }
  79. HKEY_RPC
  80. s_ApiCreateKey(
  81. IN HKEY_RPC hKey,
  82. IN LPCWSTR lpSubKey,
  83. IN DWORD dwOptions,
  84. IN DWORD samDesired,
  85. IN PRPC_SECURITY_ATTRIBUTES lpSecurityAttributes,
  86. OUT LPDWORD lpdwDisposition,
  87. OUT error_status_t *Status
  88. )
  89. /*++
  90. Routine Description:
  91. Creates a key in the cluster registry. If the key exists, it
  92. is opened. If it does not exist, it is created on all nodes in
  93. the cluster.
  94. Arguments:
  95. hKey - Supplies the key that the create is relative to.
  96. lpSubKey - Supplies the key name relative to hKey
  97. dwOptions - Supplies any registry option flags. The only currently
  98. supported option is REG_OPTION_VOLATILE
  99. samDesired - Supplies desired security access mask
  100. lpSecurityAttributes - Supplies security for the newly created key.
  101. Disposition - Returns whether the key was opened (REG_OPENED_EXISTING_KEY)
  102. or created (REG_CREATED_NEW_KEY)
  103. Status - Returns the error code if the function is unsuccessful.
  104. Return Value:
  105. A handle to the specified key if successful
  106. NULL otherwise.
  107. --*/
  108. {
  109. HDMKEY NewKey;
  110. PAPI_HANDLE Handle = NULL;
  111. PAPI_HANDLE RootHandle = NULL;
  112. if (hKey != NULL) {
  113. RootHandle = (PAPI_HANDLE)hKey;
  114. if (RootHandle->Type != API_KEY_HANDLE) {
  115. *Status = ERROR_INVALID_HANDLE;
  116. return(NULL);
  117. }
  118. }
  119. if (ApiState != ApiStateOnline) {
  120. *Status = ERROR_SHARING_PAUSED;
  121. return(NULL);
  122. }
  123. *Status = RpcImpersonateClient(NULL);
  124. if (*Status != RPC_S_OK)
  125. {
  126. return(NULL);
  127. }
  128. if ( ARGUMENT_PRESENT( lpSecurityAttributes ) &&
  129. (lpSecurityAttributes->RpcSecurityDescriptor.lpSecurityDescriptor != NULL) &&
  130. !RtlValidRelativeSecurityDescriptor( lpSecurityAttributes->RpcSecurityDescriptor.lpSecurityDescriptor,
  131. lpSecurityAttributes->RpcSecurityDescriptor.cbInSecurityDescriptor,
  132. 0 ) ) {
  133. *Status = ERROR_INVALID_SECURITY_DESCR;
  134. goto FnExit;
  135. }
  136. NewKey = DmCreateKey(hKey ? RootHandle->Key : NULL,
  137. lpSubKey,
  138. dwOptions,
  139. samDesired,
  140. ARGUMENT_PRESENT(lpSecurityAttributes)
  141. ? lpSecurityAttributes->RpcSecurityDescriptor.lpSecurityDescriptor
  142. : NULL,
  143. lpdwDisposition);
  144. if (NewKey == NULL) {
  145. *Status = GetLastError();
  146. } else {
  147. Handle = ApipMakeKeyHandle(NewKey);
  148. if (Handle == NULL) {
  149. DmCloseKey(NewKey);
  150. *Status = ERROR_NOT_ENOUGH_MEMORY;
  151. } else {
  152. *Status = ERROR_SUCCESS;
  153. }
  154. }
  155. FnExit:
  156. RpcRevertToSelf();
  157. return(Handle);
  158. }
  159. HKEY_RPC
  160. s_ApiOpenKey(
  161. IN HKEY_RPC hKey,
  162. IN LPCWSTR lpSubKey,
  163. IN DWORD samDesired,
  164. OUT error_status_t *Status
  165. )
  166. /*++
  167. Routine Description:
  168. Opens a key in the cluster registry. If the key exists, it
  169. is opened. If it does not exist, the call fails.
  170. Arguments:
  171. hKey - Supplies the key that the open is relative to.
  172. lpSubKey - Supplies the key name relative to hKey
  173. samDesired - Supplies desired security access mask
  174. Status - Returns the error code if the function is unsuccessful.
  175. Return Value:
  176. A handle to the specified key if successful
  177. NULL otherwise.
  178. --*/
  179. {
  180. HDMKEY NewKey;
  181. PAPI_HANDLE Handle=NULL;
  182. PAPI_HANDLE RootHandle;
  183. if (hKey != NULL) {
  184. RootHandle = (PAPI_HANDLE)hKey;
  185. if (RootHandle->Type != API_KEY_HANDLE) {
  186. *Status = ERROR_INVALID_HANDLE;
  187. return(NULL);
  188. }
  189. }
  190. *Status = RpcImpersonateClient(NULL);
  191. if (*Status != RPC_S_OK)
  192. {
  193. goto FnExit;
  194. }
  195. NewKey = DmOpenKey((hKey) ? RootHandle->Key : NULL,
  196. lpSubKey,
  197. samDesired);
  198. if (NewKey == NULL) {
  199. *Status = GetLastError();
  200. } else {
  201. Handle = ApipMakeKeyHandle(NewKey);
  202. if (Handle == NULL) {
  203. DmCloseKey(NewKey);
  204. *Status = ERROR_NOT_ENOUGH_MEMORY;
  205. } else {
  206. *Status = ERROR_SUCCESS;
  207. }
  208. }
  209. RpcRevertToSelf();
  210. FnExit:
  211. return(Handle);
  212. }
  213. error_status_t
  214. s_ApiEnumKey(
  215. IN HKEY_RPC hKey,
  216. IN DWORD dwIndex,
  217. OUT LPWSTR *KeyName,
  218. OUT PFILETIME lpftLastWriteTime
  219. )
  220. /*++
  221. Routine Description:
  222. Enumerates the subkeys of a cluster registry key.
  223. Arguments:
  224. hKey - Supplies the registry key for which the subkeys should
  225. be enumerated.
  226. dwIndex - Supplies the index to be enumerated.
  227. KeyName - Returns the name of the dwIndex subkey. The memory
  228. allocated for this buffer must be freed by the client.
  229. lpftLastWriteTime - Returns the last write time.
  230. Return Value:
  231. ERROR_SUCCESS if successful
  232. Win32 error code otherwise
  233. --*/
  234. {
  235. LONG Status;
  236. DWORD NameLength;
  237. HDMKEY DmKey;
  238. VALIDATE_KEY(DmKey, hKey);
  239. Status = DmQueryInfoKey(DmKey,
  240. NULL,
  241. &NameLength,
  242. NULL,
  243. NULL,
  244. NULL,
  245. NULL,
  246. NULL);
  247. if (Status != ERROR_SUCCESS) {
  248. return(Status);
  249. }
  250. NameLength += 1;
  251. *KeyName = MIDL_user_allocate(NameLength*sizeof(WCHAR));
  252. if (*KeyName == NULL) {
  253. return(ERROR_NOT_ENOUGH_MEMORY);
  254. }
  255. Status = DmEnumKey(DmKey,
  256. dwIndex,
  257. *KeyName,
  258. &NameLength,
  259. lpftLastWriteTime);
  260. if (Status != ERROR_SUCCESS) {
  261. MIDL_user_free(*KeyName);
  262. *KeyName = NULL;
  263. }
  264. return(Status);
  265. }
  266. DWORD
  267. s_ApiSetValue(
  268. IN HKEY_RPC hKey,
  269. IN LPCWSTR lpValueName,
  270. IN DWORD dwType,
  271. IN CONST UCHAR *lpData,
  272. IN DWORD cbData
  273. )
  274. /*++
  275. Routine Description:
  276. This routine sets the named value for the specified
  277. cluster registry key.
  278. Arguments:
  279. hKey - Supplies the cluster registry subkey whose value is to be set
  280. lpValueName - Supplies the name of the value to be set.
  281. dwType - Supplies the value data type
  282. lpData - Supplies a pointer to the value data
  283. cbData - Supplies the length of the value data.
  284. Return Value:
  285. ERROR_SUCCESS if successful
  286. Win32 error code otherwise
  287. --*/
  288. {
  289. HDMKEY DmKey;
  290. VALIDATE_KEY(DmKey, hKey);
  291. API_CHECK_INIT();
  292. return(DmSetValue(DmKey,
  293. lpValueName,
  294. dwType,
  295. lpData,
  296. cbData));
  297. }
  298. DWORD
  299. s_ApiDeleteValue(
  300. IN HKEY_RPC hKey,
  301. IN LPCWSTR lpValueName
  302. )
  303. /*++
  304. Routine Description:
  305. Removes the specified value from a given registry subkey
  306. Arguments:
  307. hKey - Supplies the key whose value is to be deleted.
  308. lpValueName - Supplies the name of the value to be removed.
  309. Return Value:
  310. If the function succeeds, the return value is ERROR_SUCCESS.
  311. If the function fails, the return value is an error value.
  312. --*/
  313. {
  314. HDMKEY DmKey;
  315. VALIDATE_KEY(DmKey, hKey);
  316. API_CHECK_INIT();
  317. return(DmDeleteValue(DmKey, lpValueName));
  318. }
  319. error_status_t
  320. s_ApiQueryValue(
  321. IN HKEY_RPC hKey,
  322. IN LPCWSTR lpValueName,
  323. OUT LPDWORD lpValueType,
  324. OUT PUCHAR lpData,
  325. IN DWORD cbData,
  326. OUT LPDWORD lpcbRequired
  327. )
  328. /*++
  329. Routine Description:
  330. Queries a named value for the specified cluster registry subkey
  331. Arguments:
  332. hKey - Supplies the subkey whose value should be queried
  333. lpValueName - Supplies the named value to be queried
  334. lpValueType - Returns the type of the value's data
  335. lpData - Returns the value's data
  336. cbData - Supplies the size (in bytes) of the lpData buffer
  337. Returns the number of bytes copied into the lpData buffer
  338. If lpData==NULL, cbData is set to the required buffer
  339. size and the function returns ERROR_SUCCESS
  340. Return Value:
  341. ERROR_SUCCESS if successful
  342. Win32 error code otherwise
  343. --*/
  344. {
  345. DWORD Status;
  346. DWORD BuffSize;
  347. HDMKEY DmKey;
  348. VALIDATE_KEY(DmKey, hKey);
  349. BuffSize = cbData;
  350. Status = DmQueryValue(DmKey,
  351. lpValueName,
  352. lpValueType,
  353. lpData,
  354. &BuffSize);
  355. if ((Status == ERROR_SUCCESS) ||
  356. (Status == ERROR_MORE_DATA)) {
  357. *lpcbRequired = BuffSize;
  358. }
  359. return(Status);
  360. }
  361. DWORD
  362. s_ApiDeleteKey(
  363. IN HKEY hKey,
  364. IN LPCWSTR lpSubKey
  365. )
  366. /*++
  367. Routine Description:
  368. Deletes the specified key. A key that has subkeys cannot
  369. be deleted.
  370. Arguments:
  371. hKey - Supplies a handle to a currently open key.
  372. lpSubKey - Points to a null-terminated string specifying the
  373. name of the key to delete. This parameter cannot be NULL,
  374. and the specified key must not have subkeys.
  375. Return Value:
  376. If the function succeeds, the return value is ERROR_SUCCESS.
  377. If the function fails, the return value is an error value.
  378. --*/
  379. {
  380. HDMKEY DmKey;
  381. VALIDATE_KEY(DmKey, hKey);
  382. API_CHECK_INIT();
  383. return(DmDeleteKey(DmKey, lpSubKey));
  384. }
  385. error_status_t
  386. s_ApiEnumValue(
  387. IN HKEY_RPC hKey,
  388. IN DWORD dwIndex,
  389. OUT LPWSTR *lpValueName,
  390. OUT LPDWORD lpType,
  391. OUT UCHAR *lpData,
  392. IN OUT LPDWORD lpcbData,
  393. OUT LPDWORD TotalSize
  394. )
  395. /*++
  396. Routine Description:
  397. Enumerates the specified value of a registry subkey
  398. Arguments:
  399. hKey - Supplies the registry key handle
  400. dwIndex - Supplies the index of the value to be enumerated
  401. lpValueName - Returns the name of the dwIndex'th value. The
  402. memory for this name is allocated on the server and must
  403. be freed by the client side.
  404. lpType - Returns the value data type
  405. lpData - Returns the value data
  406. lpcbData - Returns the number of bytes written to the lpData buffer.
  407. TotalSize - Returns the size of the data
  408. Return Value:
  409. ERROR_SUCCESS if successful
  410. Win32 error code otherwise
  411. --*/
  412. {
  413. LONG Status;
  414. DWORD OriginalNameLength;
  415. DWORD NameLength;
  416. DWORD DataLength;
  417. HDMKEY DmKey;
  418. VALIDATE_KEY(DmKey, hKey);
  419. Status = DmQueryInfoKey(DmKey,
  420. NULL,
  421. NULL,
  422. NULL,
  423. &NameLength,
  424. NULL,
  425. NULL,
  426. NULL);
  427. if (Status != ERROR_SUCCESS) {
  428. return(Status);
  429. }
  430. NameLength += 1;
  431. *lpValueName = MIDL_user_allocate(NameLength * sizeof(WCHAR));
  432. if (*lpValueName == NULL) {
  433. return(ERROR_NOT_ENOUGH_MEMORY);
  434. }
  435. *TotalSize = *lpcbData;
  436. //
  437. // Chittur Subbaraman (chitturs) - 3/13/2001
  438. //
  439. // First of all, at the beginning of this function, a big enough buffer for lpValueName
  440. // is allocated. This means that ERROR_SUCCESS or ERROR_MORE_DATA will be returned by
  441. // DmEnumValue depending ONLY on the size of the lpData buffer. This info is used by
  442. // by the clusapi layer when it makes a decision based on the return code from this
  443. // function.
  444. //
  445. // Note that *TotalSize is initialized to *lpcbData just above. The TotalSize OUT variable
  446. // allows the required lpData size to be returned without touching lpcbData. This is
  447. // important since lpcbData is declared as the sizeof lpData in the IDL file and that is
  448. // what RPC will consider the lpData buffer size as. So, it is important that if the lpData
  449. // buffer is not big enough, this function does not change the value of *lpcbData from what
  450. // it was originally at IN time.
  451. //
  452. // Strange behavior of RegEnumValue: If you supply a big enough buffer for lpValueName and
  453. // a smaller than required buffer for lpData, then RegEnumValue won't bother to fill in
  454. // lpValueName and will return ERROR_MORE_DATA. This irregular behavior is handled by
  455. // DmEnumValue.
  456. //
  457. // For reference pointers, RPC won't allow a client to pass in NULL pointers. That is why
  458. // clusapi layer uses dummy variables in case some of the parameters passed in by the
  459. // client caller is NULL.
  460. //
  461. //
  462. // Behavior of RegEnumValue (assuming lpValueName buffer is big enough):
  463. // (1) If lpData = NULL and lpcbData = NULL, then returns ERROR_SUCCESS.
  464. // (2) If lpData = NULL and lpcbData != NULL, then returns ERROR_SUCCESS and sets
  465. // *lpcbData to total buffer size required.
  466. // (3) If lpData != NULL and lpcbData != NULL, but the data buffer size is smaller than
  467. // required size, then returns ERROR_MORE_DATA and sets *lpcbData to the size required.
  468. // (4) If lpData != NULL and lpcbData != NULL and the buffer is big enough, then returns
  469. // ERROR_SUCCESS and sets *lpcbData to the size of the data copied into lpData.
  470. //
  471. // OUR GOAL: ClusterRegEnumValue == RegEnumValue.
  472. //
  473. //
  474. // The following cases are handled by this function and the clusapi layer. Note that in this
  475. // analysis, we assume that the client has called into clusapi with a big enough lpValueName
  476. // buffer size. (If this is not true, then clusapi layer handles that, check ClusterRegEnumValue.)
  477. //
  478. // Case 1: Client passes in lpData=NULL, lpcbData=NULL to ClusterRegEnumValue.
  479. //
  480. // In this case, the clusapi layer will point both lpData and lpcbData to local dummy
  481. // variables and initialize *lpcbData to 0. Thus, s_ApiEnumValue will see
  482. // both lpData and lpcbData as valid pointers. If the data value is bigger than the size of
  483. // *lpcbData, then DmEnumValue will return ERROR_MORE_DATA. In this case, *TotalSize will
  484. // contain the required buffer size and *lpcbData will be untouched. The client detects this
  485. // error code and sets the return status to ERROR_SUCCESS and *lpcbData to *TotalSize. Note
  486. // that the 2nd action has less relevance since lpcbData is pointing to a local dummy variable.
  487. // If the data value is of zero size, DmEnumValue will return ERROR_SUCCESS.
  488. // In such a case, *lpcbData will be set to *TotalSize before returning by this function.
  489. // Note that since the data size is 0, DmEnumValue would set *TotalSize to 0 and hence
  490. // *lpcbData will also be set to 0. Thus, in this case, when ApiEnumValue returns to the
  491. // clusapi layer, lpValueName will be filled in, *lpData will not be changed and *lpcbData
  492. // will be set to 0.
  493. //
  494. // Case 2: Client passes in lpData=NULL, lpcbData!=NULL and *lpcbData=0 to ClusterRegEnumValue.
  495. //
  496. // In this case, lpData alone will be pointing to a dummy clusapi buffer when ApiEnumValue
  497. // is invoked. Thus, s_ApiEnumValue will get both lpData and lpcbData as valid pointers.
  498. // If the data size is non-zero, then DmEnumValue will return ERROR_MORE_DATA and
  499. // *TotalSize will contain the size of the required buffer. When this function returns,
  500. // *lpcbData will remain untouched. As in case 1, the clusapi layer will set status
  501. // to ERROR_SUCCESS and *lpcbData to *TotalSize. Thus, the client will see the required
  502. // buffer size in *lpcbData. If the data size is zero, then it is handled as in case 1.
  503. //
  504. // Case 3: Client passes in lpData!=NULL, lpcbData!=NULL, but the data buffer size is smaller than
  505. // required.
  506. //
  507. // In this case, both lpData and lpcbData will be pointing to client buffers (or RPC buffers
  508. // representing them) at the entry to s_ApiEnumValue. DmEnumValue will return ERROR_MORE_DATA
  509. // and this function will return the size required in *TotalSize. *lpcbData will not be
  510. // touched. At the clusapi layer, *lpcbData will be set to *TotalSize and ERROR_MORE_DATA
  511. // will be returned to the client.
  512. //
  513. // Case 4: Client passes in lpData!=NULL, lpcbData!=NULL and the data buffer size is big enough.
  514. //
  515. // In this case, as in case 3, s_ApiEnumValue will have lpData and lpcbData pointing to
  516. // client buffers. DmEnumValue will return ERROR_SUCCESS, data copied to lpData and
  517. // *lpcbData will be set to *TotalSize (which is the size of the data copied into the
  518. // lpData buffer), before returning. The clusapi layer will return these values to the client.
  519. //
  520. Status = DmEnumValue(DmKey,
  521. dwIndex,
  522. *lpValueName,
  523. &NameLength,
  524. lpType,
  525. lpData,
  526. TotalSize);
  527. if (Status == ERROR_MORE_DATA) {
  528. return(Status);
  529. } else if (Status != ERROR_SUCCESS) {
  530. MIDL_user_free(*lpValueName);
  531. *lpValueName = NULL;
  532. *lpcbData = 0;
  533. } else {
  534. // This tells RPC how big the lpData buffer
  535. // is so it can copy the buffer to the client.
  536. *lpcbData = *TotalSize;
  537. }
  538. return(Status);
  539. }
  540. error_status_t
  541. s_ApiQueryInfoKey(
  542. IN HKEY_RPC hKey,
  543. OUT LPDWORD lpcSubKeys,
  544. OUT LPDWORD lpcbMaxSubKeyLen,
  545. OUT LPDWORD lpcValues,
  546. OUT LPDWORD lpcbMaxValueNameLen,
  547. OUT LPDWORD lpcbMaxValueLen,
  548. OUT LPDWORD lpcbSecurityDescriptor,
  549. OUT PFILETIME lpftLastWriteTime
  550. )
  551. /*++
  552. Routine Description:
  553. Retrieves information about a specified cluster registry key.
  554. Arguments:
  555. hKey - Supplies the handle of the key.
  556. lpcSubKeys - Points to a variable that receives the number of subkeys
  557. contained by the specified key.
  558. lpcbMaxSubKeyLen - Points to a variable that receives the length, in
  559. characters, of the key's subkey with the longest name.
  560. The count returned does not include the terminating null character.
  561. lpcValues - Points to a variable that receives the number of values
  562. associated with the key.
  563. lpcbMaxValueNameLen - Points to a variable that receives the length,
  564. in characters, of the key's longest value name. The count
  565. returned does not include the terminating null character.
  566. lpcbMaxValueLen - Points to a variable that receives the length, in
  567. bytes, of the longest data component among the key's values.
  568. lpcbSecurityDescriptor - Points to a variable that receives the length,
  569. in bytes, of the key's security descriptor.
  570. lpftLastWriteTime - Pointer to a FILETIME structure.
  571. Return Value:
  572. ERROR_SUCCESS if successful
  573. Win32 error code otherwise
  574. --*/
  575. {
  576. HDMKEY DmKey;
  577. DWORD Status;
  578. VALIDATE_KEY(DmKey, hKey);
  579. Status = DmQueryInfoKey(DmKey,
  580. lpcSubKeys,
  581. lpcbMaxSubKeyLen,
  582. lpcValues,
  583. lpcbMaxValueNameLen,
  584. lpcbMaxValueLen,
  585. lpcbSecurityDescriptor,
  586. lpftLastWriteTime);
  587. return(Status);
  588. }
  589. error_status_t
  590. s_ApiCloseKey(
  591. IN OUT HKEY_RPC *pKey
  592. )
  593. /*++
  594. Routine Description:
  595. Closes a cluster registry key
  596. Arguments:
  597. pKey - Supplies the key to be closed
  598. Returns NULL
  599. Return Value:
  600. None.
  601. --*/
  602. {
  603. HDMKEY DmKey;
  604. DWORD Status;
  605. VALIDATE_KEY(DmKey, *pKey);
  606. Status = RpcImpersonateClient(NULL);
  607. if (Status != ERROR_SUCCESS) {
  608. return(Status);
  609. }
  610. Status = DmCloseKey(DmKey);
  611. RpcRevertToSelf();
  612. LocalFree(*pKey);
  613. *pKey = NULL;
  614. return(Status);
  615. }
  616. void
  617. HKEY_RPC_rundown(
  618. IN HKEY_RPC Key
  619. )
  620. /*++
  621. Routine Description:
  622. RPC rundown routine for cluster registry keys
  623. Arguments:
  624. Key - Supplies the handle to be rundown
  625. Return Value:
  626. None.
  627. --*/
  628. {
  629. HDMKEY DmKey;
  630. //this should not call impersonate client
  631. if (((PAPI_HANDLE)(Key))->Type == API_KEY_HANDLE)
  632. {
  633. DmKey = ((PAPI_HANDLE)(Key))->Key; \
  634. DmCloseKey(DmKey);
  635. LocalFree(Key);
  636. }
  637. }
  638. DWORD
  639. s_ApiSetKeySecurity(
  640. IN HKEY hKey,
  641. IN DWORD SecurityInformation,
  642. IN PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor
  643. )
  644. /*++
  645. Routine Description:
  646. Sets the security on the specified registry key.
  647. Arguments:
  648. hKey - Supplies a handle to a currently open key.
  649. SecurityInformation - Supplies the type of security information to
  650. be set.
  651. pRpcSecurityDescriptor - Supplies the security information
  652. Return Value:
  653. If the function succeeds, the return value is ERROR_SUCCESS.
  654. If the function fails, the return value is an error value.
  655. --*/
  656. {
  657. HDMKEY DmKey;
  658. DWORD Status;
  659. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  660. VALIDATE_KEY(DmKey, hKey);
  661. API_CHECK_INIT();
  662. pSecurityDescriptor = pRpcSecurityDescriptor->lpSecurityDescriptor;
  663. if (!RtlValidRelativeSecurityDescriptor( pSecurityDescriptor,
  664. pRpcSecurityDescriptor->cbInSecurityDescriptor,0)){
  665. return(ERROR_INVALID_PARAMETER);
  666. }
  667. Status = RpcImpersonateClient(NULL);
  668. if (Status != ERROR_SUCCESS) {
  669. return(Status);
  670. }
  671. Status = DmSetKeySecurity(DmKey, SecurityInformation, pSecurityDescriptor);
  672. RpcRevertToSelf();
  673. return(Status);
  674. }
  675. DWORD
  676. s_ApiGetKeySecurity(
  677. IN HKEY hKey,
  678. IN DWORD SecurityInformation,
  679. IN PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor
  680. )
  681. /*++
  682. Routine Description:
  683. Gets the security from the specified registry key.
  684. Arguments:
  685. hKey - Supplies a handle to a currently open key.
  686. SecurityInformation - Supplies the type of security information to
  687. be retrieved.
  688. pRpcSecurityDescriptor - Returns the security information
  689. Return Value:
  690. If the function succeeds, the return value is ERROR_SUCCESS.
  691. If the function fails, the return value is an error value.
  692. --*/
  693. {
  694. HDMKEY DmKey;
  695. DWORD cbLength;
  696. DWORD Status;
  697. PSECURITY_DESCRIPTOR lpSD;
  698. VALIDATE_KEY(DmKey, hKey);
  699. API_CHECK_INIT();
  700. cbLength = pRpcSecurityDescriptor->cbInSecurityDescriptor;
  701. lpSD = LocalAlloc(LMEM_FIXED, cbLength);
  702. if (lpSD == NULL) {
  703. return(ERROR_NOT_ENOUGH_MEMORY);
  704. }
  705. Status = RpcImpersonateClient(NULL);
  706. if (Status != ERROR_SUCCESS) {
  707. LocalFree(lpSD);
  708. return(Status);
  709. }
  710. Status = DmGetKeySecurity(DmKey, SecurityInformation, lpSD, &cbLength);
  711. RpcRevertToSelf();
  712. if (Status == ERROR_SUCCESS) {
  713. Status = MapSDToRpcSD(lpSD, pRpcSecurityDescriptor);
  714. }
  715. if (Status != ERROR_SUCCESS) {
  716. pRpcSecurityDescriptor->cbInSecurityDescriptor = cbLength;
  717. pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0;
  718. }
  719. LocalFree(lpSD);
  720. return(Status);
  721. }