Leaked source code of windows server 2003
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.

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