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.

1585 lines
41 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Provides interface for managing cluster registry
  7. Author:
  8. John Vert (jvert) 19-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "clusapip.h"
  12. //
  13. // Function prototypes for routines local to this module
  14. //
  15. VOID
  16. FreeKey(
  17. IN PCKEY Key
  18. );
  19. HKEY
  20. OpenClusterRelative(
  21. IN HCLUSTER hCluster,
  22. IN LPCWSTR RelativeName,
  23. IN LPCWSTR SpecificName,
  24. IN DWORD samDesired
  25. );
  26. HKEY
  27. WINAPI
  28. GetClusterKey(
  29. IN HCLUSTER hCluster,
  30. IN REGSAM samDesired
  31. )
  32. /*++
  33. Routine Description:
  34. Opens the the root of the cluster registry subtree
  35. for the given cluster.
  36. Arguments:
  37. hCluster - Supplies a handle to the cluster
  38. samDesired - Specifies an access mask that describes the desired
  39. security access for the new key.
  40. Return Value:
  41. A cluster registry key handle to the root of the registry subtree
  42. for the given cluster
  43. If unsuccessful, NULL is returned and GetLastError() provides the
  44. specific error code.
  45. --*/
  46. {
  47. PCLUSTER Cluster = (PCLUSTER)hCluster;
  48. PCKEY Key;
  49. error_status_t Status = ERROR_SUCCESS;
  50. //
  51. // Allocate new CKEY structure and connect to cluster registry.
  52. //
  53. Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
  54. if (Key == NULL) {
  55. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  56. return(NULL);
  57. }
  58. Key->Parent = NULL;
  59. Key->RelativeName = NULL;
  60. Key->SamDesired = samDesired;
  61. Key->Cluster = Cluster;
  62. InitializeListHead(&Key->ChildList);
  63. InitializeListHead(&Key->NotifyList);
  64. WRAP_NULL(Key->RemoteKey,
  65. (ApiGetRootKey(Cluster->RpcBinding,
  66. samDesired,
  67. &Status)),
  68. &Status,
  69. Cluster);
  70. if ((Key->RemoteKey == NULL) ||
  71. (Status != ERROR_SUCCESS)) {
  72. LocalFree(Key);
  73. SetLastError(Status);
  74. return(NULL);
  75. }
  76. EnterCriticalSection(&Cluster->Lock);
  77. InsertHeadList(&Cluster->KeyList, &Key->ParentList);
  78. LeaveCriticalSection(&Cluster->Lock);
  79. return((HKEY)Key);
  80. }
  81. HKEY
  82. WINAPI
  83. GetClusterNodeKey(
  84. IN HNODE hNode,
  85. IN REGSAM samDesired
  86. )
  87. /*++
  88. Routine Description:
  89. Opens the the root of the cluster registry subtree
  90. for the given node
  91. Arguments:
  92. hNode - Supplies a handle to the node
  93. samDesired - Specifies an access mask that describes the desired
  94. security access for the new key.
  95. Return Value:
  96. A cluster registry key handle to the root of the registry subtree
  97. for the given node
  98. If unsuccessful, NULL is returned and GetLastError() provides the
  99. specific error code.
  100. --*/
  101. {
  102. PCNODE Node = (PCNODE)hNode;
  103. HCLUSTER Cluster = (HCLUSTER)Node->Cluster;
  104. DWORD Status;
  105. LPWSTR Guid=NULL;
  106. HKEY NodeKey;
  107. WRAP(Status,
  108. (ApiGetNodeId(Node->hNode, &Guid)),
  109. Node->Cluster);
  110. if (Status != ERROR_SUCCESS) {
  111. SetLastError(Status);
  112. return(NULL);
  113. }
  114. NodeKey = OpenClusterRelative(Cluster,
  115. CLUSREG_KEYNAME_NODES,
  116. Guid,
  117. samDesired);
  118. if (NodeKey == NULL) {
  119. Status = GetLastError();
  120. }
  121. MIDL_user_free(Guid);
  122. if (NodeKey == NULL) {
  123. SetLastError(Status);
  124. }
  125. return(NodeKey);
  126. }
  127. HKEY
  128. WINAPI
  129. GetClusterGroupKey(
  130. IN HGROUP hGroup,
  131. IN REGSAM samDesired
  132. )
  133. /*++
  134. Routine Description:
  135. Opens the the root of the cluster registry subtree
  136. for the given group
  137. Arguments:
  138. hResource - Supplies a handle to the group
  139. samDesired - Specifies an access mask that describes the desired
  140. security access for the new key.
  141. Return Value:
  142. A cluster registry key handle to the root of the registry subtree
  143. for the given group
  144. If unsuccessful, NULL is returned and GetLastError() provides the
  145. specific error code.
  146. --*/
  147. {
  148. PCGROUP Group = (PCGROUP)hGroup;
  149. HCLUSTER Cluster = (HCLUSTER)Group->Cluster;
  150. DWORD Status;
  151. LPWSTR Guid=NULL;
  152. HKEY GroupKey;
  153. WRAP(Status,
  154. (ApiGetGroupId(Group->hGroup, &Guid)),
  155. Group->Cluster);
  156. if (Status != ERROR_SUCCESS) {
  157. SetLastError(Status);
  158. return(NULL);
  159. }
  160. GroupKey = OpenClusterRelative(Cluster,
  161. CLUSREG_KEYNAME_GROUPS,
  162. Guid,
  163. samDesired);
  164. if (GroupKey == NULL) {
  165. Status = GetLastError();
  166. }
  167. MIDL_user_free(Guid);
  168. if (GroupKey == NULL) {
  169. SetLastError(Status);
  170. }
  171. return(GroupKey);
  172. }
  173. HKEY
  174. WINAPI
  175. GetClusterResourceKey(
  176. IN HRESOURCE hResource,
  177. IN REGSAM samDesired
  178. )
  179. /*++
  180. Routine Description:
  181. Opens the the root of the cluster registry subtree
  182. for the given resource.
  183. Arguments:
  184. hResource - Supplies a handle to the resource
  185. samDesired - Specifies an access mask that describes the desired
  186. security access for the new key.
  187. Return Value:
  188. A cluster registry key handle to the root of the registry subtree
  189. for the given resource
  190. If unsuccessful, NULL is returned and GetLastError() provides the
  191. specific error code.
  192. --*/
  193. {
  194. PCRESOURCE Resource = (PCRESOURCE)hResource;
  195. HCLUSTER Cluster = (HCLUSTER)Resource->Cluster;
  196. DWORD Status;
  197. LPWSTR Guid=NULL;
  198. HKEY ResKey;
  199. WRAP(Status,
  200. (ApiGetResourceId(Resource->hResource, &Guid)),
  201. Resource->Cluster);
  202. if (Status != ERROR_SUCCESS) {
  203. SetLastError(Status);
  204. return(NULL);
  205. }
  206. ResKey = OpenClusterRelative(Cluster,
  207. CLUSREG_KEYNAME_RESOURCES,
  208. Guid,
  209. samDesired);
  210. if (ResKey == NULL) {
  211. Status = GetLastError();
  212. }
  213. MIDL_user_free(Guid);
  214. if (ResKey == NULL) {
  215. SetLastError(Status);
  216. }
  217. return(ResKey);
  218. }
  219. HKEY
  220. WINAPI
  221. GetClusterResourceTypeKey(
  222. IN HCLUSTER hCluster,
  223. IN LPCWSTR lpszTypeName,
  224. IN REGSAM samDesired
  225. )
  226. /*++
  227. Routine Description:
  228. Opens the the root of the cluster registry subtree
  229. for the given resource type.
  230. Arguments:
  231. hCluster - Supplies the cluster the open is relative to.
  232. lpszTypeName - Supplies the resource type name.
  233. samDesired - Specifies an access mask that describes the desired
  234. security access for the new key.
  235. Return Value:
  236. A cluster registry key handle to the root of the registry subtree
  237. for the given resource type.
  238. If unsuccessful, NULL is returned and GetLastError() provides the
  239. specific error code.
  240. --*/
  241. {
  242. return(OpenClusterRelative(hCluster,
  243. CLUSREG_KEYNAME_RESOURCE_TYPES,
  244. lpszTypeName,
  245. samDesired));
  246. }
  247. HKEY
  248. WINAPI
  249. GetClusterNetworkKey(
  250. IN HNETWORK hNetwork,
  251. IN REGSAM samDesired
  252. )
  253. /*++
  254. Routine Description:
  255. Opens the the root of the cluster registry subtree
  256. for the given network.
  257. Arguments:
  258. hNetwork - Supplies a handle to the network.
  259. samDesired - Specifies an access mask that describes the desired
  260. security access for the new key.
  261. Return Value:
  262. A cluster registry key handle to the root of the registry subtree
  263. for the given network.
  264. If unsuccessful, NULL is returned and GetLastError() provides the
  265. specific error code.
  266. --*/
  267. {
  268. PCNETWORK Network = (PCNETWORK)hNetwork;
  269. HCLUSTER Cluster = (HCLUSTER)Network->Cluster;
  270. DWORD Status;
  271. LPWSTR Guid=NULL;
  272. HKEY NetworkKey;
  273. WRAP(Status,
  274. (ApiGetNetworkId(Network->hNetwork, &Guid)),
  275. Network->Cluster);
  276. if (Status != ERROR_SUCCESS) {
  277. SetLastError(Status);
  278. return(NULL);
  279. }
  280. NetworkKey = OpenClusterRelative(Cluster,
  281. CLUSREG_KEYNAME_NETWORKS,
  282. Guid,
  283. samDesired);
  284. if (NetworkKey == NULL) {
  285. Status = GetLastError();
  286. }
  287. MIDL_user_free(Guid);
  288. if (NetworkKey == NULL) {
  289. SetLastError(Status);
  290. }
  291. return(NetworkKey);
  292. }
  293. HKEY
  294. WINAPI
  295. GetClusterNetInterfaceKey(
  296. IN HNETINTERFACE hNetInterface,
  297. IN REGSAM samDesired
  298. )
  299. /*++
  300. Routine Description:
  301. Opens the the root of the cluster registry subtree
  302. for the given network interface.
  303. Arguments:
  304. hNetInterface - Supplies a handle to the network interface.
  305. samDesired - Specifies an access mask that describes the desired
  306. security access for the new key.
  307. Return Value:
  308. A cluster registry key handle to the root of the registry subtree
  309. for the given network interface.
  310. If unsuccessful, NULL is returned and GetLastError() provides the
  311. specific error code.
  312. --*/
  313. {
  314. PCNETINTERFACE NetInterface = (PCNETINTERFACE)hNetInterface;
  315. HCLUSTER Cluster = (HCLUSTER)NetInterface->Cluster;
  316. DWORD Status;
  317. LPWSTR Guid=NULL;
  318. HKEY NetInterfaceKey;
  319. WRAP(Status,
  320. (ApiGetNetInterfaceId(NetInterface->hNetInterface, &Guid)),
  321. NetInterface->Cluster);
  322. if (Status != ERROR_SUCCESS) {
  323. SetLastError(Status);
  324. return(NULL);
  325. }
  326. NetInterfaceKey = OpenClusterRelative(Cluster,
  327. CLUSREG_KEYNAME_NETINTERFACES,
  328. Guid,
  329. samDesired);
  330. if (NetInterfaceKey == NULL) {
  331. Status = GetLastError();
  332. }
  333. MIDL_user_free(Guid);
  334. if (NetInterfaceKey == NULL) {
  335. SetLastError(Status);
  336. }
  337. return(NetInterfaceKey);
  338. }
  339. HKEY
  340. OpenClusterRelative(
  341. IN HCLUSTER Cluster,
  342. IN LPCWSTR RelativeName,
  343. IN LPCWSTR SpecificName,
  344. IN DWORD samDesired
  345. )
  346. /*++
  347. Routine Description:
  348. Helper routine for the functions that open cluster object keys.
  349. (GetCluster*Key)
  350. Arguments:
  351. Cluster - Supplies the cluster the key should be opened in.
  352. RelativeName - Supplies the first part of the relative name
  353. (i.e. L"Resources")
  354. SpecificName - Supplies the name of the object.
  355. Return Value:
  356. An open registry key if successful
  357. NULL if unsuccessful. LastError will be set to a Win32 error code
  358. --*/
  359. {
  360. LPWSTR Buff;
  361. HKEY ClusterKey;
  362. HKEY Key;
  363. LONG Status;
  364. Buff = LocalAlloc(LMEM_FIXED, (lstrlenW(RelativeName)+lstrlenW(SpecificName)+2)*sizeof(WCHAR));
  365. if ( Buff == NULL ) {
  366. return(NULL);
  367. }
  368. lstrcpyW(Buff, RelativeName);
  369. lstrcatW(Buff, L"\\");
  370. lstrcatW(Buff, SpecificName);
  371. ClusterKey = GetClusterKey(Cluster, KEY_READ);
  372. if (ClusterKey == NULL) {
  373. Status = GetLastError();
  374. LocalFree(Buff);
  375. SetLastError(Status);
  376. return(NULL);
  377. }
  378. Status = ClusterRegOpenKey(ClusterKey,
  379. Buff,
  380. samDesired,
  381. &Key);
  382. LocalFree(Buff);
  383. ClusterRegCloseKey(ClusterKey);
  384. if (Status == ERROR_SUCCESS) {
  385. return(Key);
  386. } else {
  387. SetLastError(Status);
  388. return(NULL);
  389. }
  390. }
  391. LONG
  392. WINAPI
  393. ClusterRegCreateKey(
  394. IN HKEY hKey,
  395. IN LPCWSTR lpSubKey,
  396. IN DWORD dwOptions,
  397. IN REGSAM samDesired,
  398. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  399. OUT PHKEY phkResult,
  400. OUT OPTIONAL LPDWORD lpdwDisposition
  401. )
  402. /*++
  403. Routine Description:
  404. Creates the specified key in the cluster registry. If the
  405. key already exists in the registry, the function opens it.
  406. Arguments:
  407. hKey - Supplies a currently open key.
  408. lpSubKey - Points to a null-terminated string specifying the name
  409. of a subkey that this function opens or creates. The subkey
  410. specified must be a subkey of the key identified by the hKey
  411. parameter. This subkey must not begin with the backslash
  412. character ('\'). This parameter cannot be NULL.
  413. dwOptions - Specifies special options for this key. Valid options are:
  414. REG_OPTION_VOLATILE - This key is volatile; the information is
  415. stored in memory and is not preserved when
  416. the system is restarted.
  417. samDesired - Specifies an access mask that specifies the desired security
  418. access for the new key
  419. lpSecurityAttributes - The lpSecurityDescriptor member of the structure
  420. specifies a security descriptor for the new key. If
  421. lpSecurityAttributes is NULL, the key gets a default security
  422. descriptor. Since cluster registry handles are not inheritable,
  423. the bInheritHandle field of the SECURITY_ATTRIBUTES structure
  424. must be FALSE.
  425. phkResult - Points to a variable that receives the handle of the opened
  426. or created key
  427. lpdwDisposition - Points to a variable that receives one of the following
  428. disposition values:
  429. Value Meaning
  430. REG_CREATED_NEW_KEY The key did not exist and was created.
  431. REG_OPENED_EXISTING_KEY The key existed and was simply opened
  432. without being changed.
  433. Return Value:
  434. If the function succeeds, the return value is ERROR_SUCCESS.
  435. If the function fails, the return value is an error value.
  436. --*/
  437. {
  438. PCKEY Key;
  439. PCKEY ParentKey = (PCKEY)hKey;
  440. PCLUSTER Cluster = ParentKey->Cluster;
  441. PRPC_SECURITY_ATTRIBUTES pRpcSA;
  442. RPC_SECURITY_ATTRIBUTES RpcSA;
  443. error_status_t Status = ERROR_SUCCESS;
  444. DWORD Disposition;
  445. if (lpdwDisposition == NULL) {
  446. lpdwDisposition = &Disposition;
  447. }
  448. //
  449. // Allocate new CKEY structure and create cluster registry key
  450. //
  451. Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
  452. if (Key == NULL) {
  453. return(ERROR_NOT_ENOUGH_MEMORY);
  454. }
  455. Key->Parent = ParentKey;
  456. Key->RelativeName = LocalAlloc(LMEM_FIXED, (lstrlenW(lpSubKey)+1)*sizeof(WCHAR));
  457. if (Key->RelativeName == NULL) {
  458. LocalFree(Key);
  459. return(ERROR_NOT_ENOUGH_MEMORY);
  460. }
  461. lstrcpyW(Key->RelativeName, lpSubKey);
  462. Key->SamDesired = samDesired;
  463. Key->Cluster = Cluster;
  464. InitializeListHead(&Key->ChildList);
  465. InitializeListHead(&Key->NotifyList);
  466. if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
  467. DWORD Error;
  468. pRpcSA = &RpcSA;
  469. Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
  470. if( Error != ERROR_SUCCESS ) {
  471. LocalFree(Key->RelativeName);
  472. LocalFree(Key);
  473. return Error;
  474. }
  475. } else {
  476. //
  477. // No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
  478. //
  479. pRpcSA = NULL;
  480. }
  481. WRAP_NULL(Key->RemoteKey,
  482. (ApiCreateKey(ParentKey->RemoteKey,
  483. lpSubKey,
  484. dwOptions,
  485. samDesired,
  486. pRpcSA,
  487. lpdwDisposition,
  488. &Status)),
  489. &Status,
  490. ParentKey->Cluster);
  491. //
  492. // Free the RPC_SECURITY_DESCRIPTOR buffer allocated by MapSAToRpcSA.
  493. //
  494. if ( pRpcSA ) {
  495. //
  496. // RtlFreeHeap accepts a NULL base address
  497. //
  498. RtlFreeHeap( RtlProcessHeap(),
  499. 0,
  500. pRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor );
  501. }
  502. if ((Key->RemoteKey == NULL) ||
  503. (Status != ERROR_SUCCESS)) {
  504. *phkResult = NULL;
  505. LocalFree(Key->RelativeName);
  506. LocalFree(Key);
  507. return(Status);
  508. }
  509. EnterCriticalSection(&Cluster->Lock);
  510. InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
  511. LeaveCriticalSection(&Cluster->Lock);
  512. *phkResult = (HKEY)Key;
  513. return(ERROR_SUCCESS);
  514. }
  515. LONG
  516. WINAPI
  517. ClusterRegOpenKey(
  518. IN HKEY hKey,
  519. IN LPCWSTR lpSubKey,
  520. IN REGSAM samDesired,
  521. OUT PHKEY phkResult
  522. )
  523. /*++
  524. Routine Description:
  525. Opens the specified key in the cluster registry.
  526. Arguments:
  527. hKey - Supplies a currently open key.
  528. lpSubKey - Points to a null-terminated string specifying the name
  529. of a subkey that this function opens or creates. The subkey
  530. specified must be a subkey of the key identified by the hKey
  531. parameter. This subkey must not begin with the backslash
  532. character ('\'). This parameter cannot be NULL.
  533. samDesired - Specifies an access mask that specifies the desired security
  534. access for the new key
  535. phkResult - Points to a variable that receives the handle of the opened
  536. or created key. Initialized to NULL on failure.
  537. Return Value:
  538. If the function succeeds, the return value is ERROR_SUCCESS.
  539. If the function fails, the return value is an error value.
  540. --*/
  541. {
  542. PCKEY Key;
  543. PCKEY ParentKey = (PCKEY)hKey;
  544. PCLUSTER Cluster = ParentKey->Cluster;
  545. error_status_t Status = ERROR_SUCCESS;
  546. //
  547. // Allocate new CKEY structure and create cluster registry key
  548. //
  549. Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
  550. if (Key == NULL) {
  551. return(ERROR_NOT_ENOUGH_MEMORY);
  552. }
  553. *phkResult = NULL;
  554. Key->Parent = ParentKey;
  555. Key->RelativeName = LocalAlloc(LMEM_FIXED, (lstrlenW(lpSubKey)+1)*sizeof(WCHAR));
  556. if (Key->RelativeName == NULL) {
  557. LocalFree(Key);
  558. return(ERROR_NOT_ENOUGH_MEMORY);
  559. }
  560. lstrcpyW(Key->RelativeName, lpSubKey);
  561. Key->SamDesired = samDesired;
  562. Key->Cluster = Cluster;
  563. InitializeListHead(&Key->ChildList);
  564. InitializeListHead(&Key->NotifyList);
  565. WRAP_NULL(Key->RemoteKey,
  566. (ApiOpenKey(ParentKey->RemoteKey,
  567. lpSubKey,
  568. samDesired,
  569. &Status)),
  570. &Status,
  571. ParentKey->Cluster);
  572. if (Status != ERROR_SUCCESS) {
  573. LocalFree(Key->RelativeName);
  574. LocalFree(Key);
  575. return(Status);
  576. }
  577. EnterCriticalSection(&Cluster->Lock);
  578. InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
  579. LeaveCriticalSection(&Cluster->Lock);
  580. *phkResult = (HKEY)Key;
  581. return(ERROR_SUCCESS);
  582. }
  583. LONG
  584. WINAPI
  585. ClusterRegDeleteKey(
  586. IN HKEY hKey,
  587. IN LPCWSTR lpSubKey
  588. )
  589. /*++
  590. Routine Description:
  591. Deletes the specified key. A key that has subkeys cannot
  592. be deleted.
  593. Arguments:
  594. hKey - Supplies a handle to a currently open key.
  595. lpSubKey - Points to a null-terminated string specifying the
  596. name of the key to delete. This parameter cannot be NULL,
  597. and the specified key must not have subkeys.
  598. Return Value:
  599. If the function succeeds, the return value is ERROR_SUCCESS.
  600. If the function fails, the return value is an error value.
  601. --*/
  602. {
  603. PCKEY Key = (PCKEY)hKey;
  604. DWORD Status;
  605. WRAP(Status,
  606. (ApiDeleteKey(Key->RemoteKey, lpSubKey)),
  607. Key->Cluster);
  608. return(Status);
  609. }
  610. LONG
  611. WINAPI
  612. ClusterRegCloseKey(
  613. IN HKEY hKey
  614. )
  615. /*++
  616. Routine Description:
  617. Closes the handle of the specified cluster registry key
  618. Arguments:
  619. hKey - Supplies the open key to close
  620. Return Value:
  621. If the function succeeds, the return value is ERROR_SUCCESS.
  622. If the function fails, the return value is an error value.
  623. --*/
  624. {
  625. PCKEY Key = (PCKEY)hKey;
  626. PCLUSTER Cluster = Key->Cluster;
  627. //
  628. // If any keys have been opened relative to this key, we need to
  629. // keep this CKEY around so that we can reconstruct the key names
  630. // if we need to reopen the handles.
  631. //
  632. // If there are no children of this key, all the storage can be
  633. // freed. Note that freeing this key may also require us to free
  634. // up its parent if the parent has been closed but not freed because
  635. // it has children.
  636. //
  637. EnterCriticalSection(&Cluster->Lock);
  638. if (Cluster->Flags & CLUS_DEAD)
  639. {
  640. if (Key->RemoteKey)
  641. RpcSmDestroyClientContext(&Key->RemoteKey);
  642. }
  643. else
  644. {
  645. ApiCloseKey(&Key->RemoteKey);
  646. }
  647. //
  648. // Remove any notifications posted against this key.
  649. //
  650. RundownNotifyEvents(&Key->NotifyList, L"");
  651. if (IsListEmpty(&Key->ChildList)) {
  652. FreeKey(Key);
  653. }
  654. LeaveCriticalSection(&Cluster->Lock);
  655. //
  656. // If this key was the last thing keeping the cluster structure
  657. // around, we can clean it up now.
  658. //
  659. CleanupCluster(Cluster);
  660. return(ERROR_SUCCESS);
  661. }
  662. VOID
  663. FreeKey(
  664. IN PCKEY Key
  665. )
  666. /*++
  667. Routine Description:
  668. Frees up the storage for a key and removes it from its
  669. parent's ChildList. If this is the last key in its parent's
  670. ChildList, this routine calls itself recursively to free
  671. the parent storage.
  672. Arguments:
  673. Key - Supplies the CKEY to be freed.
  674. Return Value:
  675. None.
  676. --*/
  677. {
  678. RemoveEntryList(&Key->ParentList);
  679. if (Key->Parent != NULL) {
  680. //
  681. // This is not a root key, so see if we need to free the
  682. // parent.
  683. //
  684. if ((Key->Parent->RemoteKey == NULL) &&
  685. (IsListEmpty(&Key->Parent->ChildList))) {
  686. FreeKey(Key->Parent);
  687. }
  688. LocalFree(Key->RelativeName);
  689. }
  690. LocalFree(Key);
  691. }
  692. LONG
  693. WINAPI
  694. ClusterRegEnumKey(
  695. IN HKEY hKey,
  696. IN DWORD dwIndex,
  697. OUT LPWSTR lpszName,
  698. IN OUT LPDWORD lpcchName,
  699. OUT PFILETIME lpftLastWriteTime
  700. )
  701. /*++
  702. Routine Description:
  703. Enumerates subkeys of the specified open cluster registry key.
  704. The function retrieves information about one subkey each time it is called.
  705. Arguments:
  706. hKey - Supplies a currently open key or NULL. If NULL is specified,
  707. the root of the cluster registry is enumerated.
  708. dwIndex - Supplies the index of the subkey to retrieve. This parameter
  709. should be zero for the first call to the RegEnumKeyEx function
  710. and then incremented for subsequent calls. Because subkeys are
  711. not ordered, any new subkey will have an arbitrary index. This
  712. means that the function may return subkeys in any order.
  713. lpszName - Points to a buffer that receives the name of the subkey,
  714. including the terminating null character. The function copies
  715. only the name of the subkey, not the full key hierarchy, to
  716. the buffer.
  717. lpcchName - Points to a variable that specifies the size, in characters,
  718. of the buffer specified by the lpszName parameter. This size should
  719. include the terminating null character. When the function returns,
  720. the variable pointed to by lpcchName contains the number of characters
  721. stored in the buffer. The count returned does not include the
  722. terminating null character.
  723. lpftLastWriteTime - Points to a variable that receives the time the
  724. enumerated subkey was last written to.
  725. Return Value:
  726. If the function succeeds, the return value is ERROR_SUCCESS.
  727. If the function fails, the return value is an error value.
  728. --*/
  729. {
  730. PCKEY Key = (PCKEY)hKey;
  731. LONG Status;
  732. FILETIME LastWriteTime;
  733. LPWSTR KeyName=NULL;
  734. DWORD dwNameLen;
  735. WRAP(Status,
  736. (ApiEnumKey(Key->RemoteKey,
  737. dwIndex,
  738. &KeyName,
  739. &LastWriteTime)),
  740. Key->Cluster);
  741. if (Status != ERROR_SUCCESS) {
  742. return(Status);
  743. }
  744. MylstrcpynW(lpszName, KeyName, *lpcchName);
  745. dwNameLen = lstrlenW(KeyName);
  746. if (*lpcchName < (dwNameLen + 1)) {
  747. if (lpszName != NULL) {
  748. Status = ERROR_MORE_DATA;
  749. }
  750. }
  751. *lpcchName = dwNameLen;
  752. MIDL_user_free(KeyName);
  753. return(Status);
  754. }
  755. DWORD
  756. WINAPI
  757. ClusterRegSetValue(
  758. IN HKEY hKey,
  759. IN LPCWSTR lpszValueName,
  760. IN DWORD dwType,
  761. IN CONST BYTE* lpData,
  762. IN DWORD cbData
  763. )
  764. /*++
  765. Routine Description:
  766. Sets the named value for the given resource.
  767. Arguments:
  768. hKey - Supplies the handle of the cluster registry key.
  769. lpszValueName - Supplies a pointer to a string containing
  770. the name of the value to set. If a value with this
  771. name is not already present in the resource, the function
  772. adds it to the resource.
  773. dwType - Supplies the type of information to be stored as the
  774. value's data. This parameter can be one of the following values:
  775. Value Meaning
  776. REG_BINARY Binary data in any form.
  777. REG_DWORD A 32-bit number.
  778. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  779. references to environment variables (for example, "%PATH%").
  780. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  781. by two null characters.
  782. REG_NONE No defined value type.
  783. REG_SZ A null-terminated Unicode string.
  784. lpData - Supplies a pointer to a buffer containing the data
  785. to be stored with the specified value name.
  786. cbData - Supplies the size, in bytes, of the information
  787. pointed to by the lpData parameter. If the data
  788. is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ,
  789. cbData must include the size of the terminating null character.
  790. Return value:
  791. If the function succeeds, the return value is ERROR_SUCCESS.
  792. If the function fails, the return value is an error value.
  793. --*/
  794. {
  795. PCKEY Key = (PCKEY)hKey;
  796. DWORD Status;
  797. WRAP(Status,
  798. (ApiSetValue(Key->RemoteKey,
  799. lpszValueName,
  800. dwType,
  801. lpData,
  802. cbData)),
  803. Key->Cluster);
  804. return(Status);
  805. }
  806. DWORD
  807. WINAPI
  808. ClusterRegDeleteValue(
  809. IN HKEY hKey,
  810. IN LPCWSTR lpszValueName
  811. )
  812. /*++
  813. Routine Description:
  814. Removes the specified value from a given registry subkey
  815. Arguments:
  816. hKey - Supplies the key whose value is to be deleted.
  817. lpszValueName - Supplies the name of the value to be removed.
  818. Return Value:
  819. If the function succeeds, the return value is ERROR_SUCCESS.
  820. If the function fails, the return value is an error value.
  821. --*/
  822. {
  823. PCKEY Key = (PCKEY)hKey;
  824. DWORD Status;
  825. WRAP(Status,
  826. (ApiDeleteValue(Key->RemoteKey, lpszValueName)),
  827. Key->Cluster);
  828. return(Status);
  829. }
  830. LONG
  831. WINAPI
  832. ClusterRegQueryValue(
  833. IN HKEY hKey,
  834. IN LPCWSTR lpszValueName,
  835. OUT LPDWORD lpdwValueType,
  836. OUT LPBYTE lpData,
  837. IN OUT LPDWORD lpcbData
  838. )
  839. /*++
  840. Routine Description:
  841. Retrieves the type and data for a specified value name associated with
  842. an open cluster registry key.
  843. Arguments:
  844. hKey - Supplies the handle of the cluster registry key.
  845. lpszValueName - Supplies a pointer to a string containing the
  846. name of the value to be queried.
  847. lpdwValueType - Points to a variable that receives the key's value
  848. type. The value returned through this parameter will
  849. be one of the following:
  850. Value Meaning
  851. REG_BINARY Binary data in any form.
  852. REG_DWORD A 32-bit number.
  853. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  854. references to environment variables (for example, "%PATH%").
  855. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  856. by two null characters.
  857. REG_NONE No defined value type.
  858. REG_SZ A null-terminated Unicode string.
  859. The lpdwValueType parameter can be NULL if the type is not required
  860. lpData - Points to a buffer that receives the value's data. This parameter
  861. can be NULL if the data is not required.
  862. lpcbData - Points to a variable that specifies the size, in bytes, of the buffer
  863. pointed to by the lpData parameter. When the function returns, this
  864. variable contains the size of the data copied to lpData.
  865. If the buffer specified by lpData parameter is not large enough to hold
  866. the data, the function returns the value ERROR_MORE_DATA, and stores the
  867. required buffer size, in bytes, into the variable pointed to by
  868. lpcbData.
  869. If lpData is NULL, and lpcbData is non-NULL, the function returns
  870. ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable
  871. pointed to by lpcbData. This lets an application determine the best way
  872. to allocate a buffer for the value key's data.
  873. If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, then
  874. lpData will also include the size of the terminating null character.
  875. The lpcbData parameter can be NULL only if lpData is NULL.
  876. Return Value:
  877. If the function succeeds, the return value is ERROR_SUCCESS.
  878. If the function fails, the return value is an error value.
  879. --*/
  880. {
  881. DWORD Dummy1;
  882. DWORD Dummy2;
  883. DWORD Required;
  884. PCKEY Key = (PCKEY)hKey;
  885. DWORD Status;
  886. LPBYTE TempData;
  887. DWORD BufferSize;
  888. if (lpdwValueType == NULL) {
  889. lpdwValueType = &Dummy1;
  890. }
  891. if (lpData == NULL) {
  892. TempData = (LPBYTE)&Dummy2;
  893. BufferSize = 0;
  894. } else {
  895. TempData = lpData;
  896. BufferSize = *lpcbData;
  897. }
  898. WRAP(Status,
  899. (ApiQueryValue(Key->RemoteKey,
  900. lpszValueName,
  901. lpdwValueType,
  902. TempData,
  903. BufferSize,
  904. &Required)),
  905. Key->Cluster);
  906. if ((Status == ERROR_SUCCESS) ||
  907. (Status == ERROR_MORE_DATA)) {
  908. if ((Status == ERROR_MORE_DATA) &&
  909. (lpData == NULL)) {
  910. //
  911. // Map this error to success to match the spec.
  912. //
  913. Status = ERROR_SUCCESS;
  914. }
  915. *lpcbData = Required;
  916. }
  917. return(Status);
  918. }
  919. DWORD
  920. WINAPI
  921. ClusterRegEnumValue(
  922. IN HKEY hKey,
  923. IN DWORD dwIndex,
  924. OUT LPWSTR lpszValueName,
  925. IN OUT LPDWORD lpcchValueName,
  926. IN LPDWORD lpdwType,
  927. OUT LPBYTE lpData,
  928. IN OUT LPDWORD lpcbData
  929. )
  930. /*++
  931. Routine Description:
  932. Enumerates the properties of the given resource.
  933. Arguments:
  934. hKey - Supplies the handle of the key
  935. dwIndex - Specifies the index of the value to retrieve. This parameter
  936. should be zero for the first call to the EnumClusterResourceValue
  937. function and then be incremented for subsequent calls. Because
  938. properties are not ordered, any new value will have an arbitrary
  939. index. This means that the function may return properties in any
  940. order.
  941. lpszValueName - Points to a buffer that receives the name of the value,
  942. including the terminating null character.
  943. lpcchValueName - Points to a variable that specifies the size, in characters,
  944. of the buffer pointed to by the lpszValueName parameter. This size
  945. should include the terminating null character. When the function returns,
  946. the variable pointed to by lpcchValueName contains the number of
  947. characters stored in the buffer. The count returned does not include
  948. the terminating null character.
  949. lpdwType - Points to a variable that receives the type code for the value entry.
  950. The type code can be one of the following values:
  951. Value Meaning
  952. REG_BINARY Binary data in any form.
  953. REG_DWORD A 32-bit number.
  954. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  955. references to environment variables (for example, "%PATH%").
  956. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  957. by two null characters.
  958. REG_NONE No defined value type.
  959. REG_SZ A null-terminated Unicode string.
  960. The lpdwType parameter can be NULL if the type code is not required.
  961. lpData - Points to a buffer that receives the data for the value entry.
  962. This parameter can be NULL if the data is not required.
  963. lpcbData - Points to a variable that specifies the size, in bytes, of the
  964. buffer pointed to by the lpData parameter. When the function
  965. returns, the variable pointed to by the lpcbData parameter contains
  966. the number of bytes stored in the buffer. This parameter can be NULL
  967. only if lpData is NULL.
  968. Return Value:
  969. If the function succeeds, the return value is ERROR_SUCCESS.
  970. If the function fails, the return value is an error value.
  971. --*/
  972. {
  973. PCKEY Key = (PCKEY)hKey;
  974. LONG Status;
  975. LPWSTR ValueName=NULL;
  976. DWORD TotalSize;
  977. DWORD DummyType;
  978. BYTE DummyData;
  979. DWORD DummycbData;
  980. DWORD dwNameLen;
  981. if (lpdwType == NULL) {
  982. lpdwType = &DummyType;
  983. }
  984. if (lpcbData == NULL) {
  985. if (lpData != NULL) {
  986. return(ERROR_INVALID_PARAMETER);
  987. }
  988. DummycbData = 0;
  989. lpcbData = &DummycbData;
  990. }
  991. if (lpData == NULL) {
  992. lpData = &DummyData;
  993. }
  994. WRAP(Status,
  995. (ApiEnumValue(Key->RemoteKey,
  996. dwIndex,
  997. &ValueName,
  998. lpdwType,
  999. lpData,
  1000. lpcbData,
  1001. &TotalSize)),
  1002. Key->Cluster);
  1003. if ((Status != ERROR_SUCCESS) &&
  1004. (Status != ERROR_MORE_DATA)) {
  1005. return(Status);
  1006. }
  1007. if (Status == ERROR_MORE_DATA) {
  1008. *lpcbData = TotalSize;
  1009. if (lpData == &DummyData) {
  1010. Status = ERROR_SUCCESS;
  1011. }
  1012. }
  1013. MylstrcpynW(lpszValueName, ValueName, *lpcchValueName);
  1014. dwNameLen = lstrlenW(ValueName);
  1015. if (*lpcchValueName < (dwNameLen + 1)) {
  1016. if (lpszValueName != NULL) {
  1017. Status = ERROR_MORE_DATA;
  1018. }
  1019. }
  1020. *lpcchValueName = dwNameLen;
  1021. MIDL_user_free(ValueName);
  1022. return(Status);
  1023. }
  1024. LONG
  1025. WINAPI
  1026. ClusterRegQueryInfoKey(
  1027. HKEY hKey,
  1028. LPDWORD lpcSubKeys,
  1029. LPDWORD lpcchMaxSubKeyLen,
  1030. LPDWORD lpcValues,
  1031. LPDWORD lpcchMaxValueNameLen,
  1032. LPDWORD lpcbMaxValueLen,
  1033. LPDWORD lpcbSecurityDescriptor,
  1034. PFILETIME lpftLastWriteTime
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. Retrieves information about a specified cluster registry key.
  1039. Arguments:
  1040. hKey - Supplies the handle of the key.
  1041. lpcSubKeys - Points to a variable that receives the number of subkeys
  1042. contained by the specified key. This parameter can be NULL.
  1043. lpcchMaxSubKeyLen - Points to a variable that receives the length, in
  1044. characters, of the key's subkey with the longest name. The count
  1045. returned does not include the terminating null character. This parameter can be NULL.
  1046. lpcValues - Points to a variable that receives the number of values
  1047. associated with the key. This parameter can be NULL.
  1048. lpcchMaxValueNameLen - Points to a variable that receives the length,
  1049. in characters, of the key's longest value name. The count returned
  1050. does not include the terminating null character. This parameter can be NULL.
  1051. lpcbMaxValueLen - Points to a variable that receives the length, in
  1052. bytes, of the longest data component among the key's values. This parameter can be NULL.
  1053. lpcbSecurityDescriptor - Points to a variable that receives the length,
  1054. in bytes, of the key's security descriptor. This parameter can be NULL.
  1055. lpftLastWriteTime - Pointer to a FILETIME structure. This parameter can be NULL.
  1056. Return Value:
  1057. ERROR_SUCCESS if successful
  1058. Win32 error code otherwise
  1059. --*/
  1060. {
  1061. DWORD SubKeys;
  1062. DWORD MaxSubKeyLen;
  1063. DWORD Values;
  1064. DWORD MaxValueNameLen;
  1065. DWORD MaxValueLen;
  1066. DWORD SecurityDescriptor;
  1067. DWORD Status;
  1068. FILETIME LastWriteTime;
  1069. PCKEY Key = (PCKEY)hKey;
  1070. WRAP(Status,
  1071. ApiQueryInfoKey(Key->RemoteKey,
  1072. &SubKeys,
  1073. &MaxSubKeyLen,
  1074. &Values,
  1075. &MaxValueNameLen,
  1076. &MaxValueLen,
  1077. &SecurityDescriptor,
  1078. &LastWriteTime),
  1079. Key->Cluster);
  1080. if (Status == ERROR_SUCCESS) {
  1081. if (ARGUMENT_PRESENT(lpcSubKeys)) {
  1082. *lpcSubKeys = SubKeys;
  1083. }
  1084. if (ARGUMENT_PRESENT(lpcchMaxSubKeyLen)) {
  1085. *lpcchMaxSubKeyLen = MaxSubKeyLen;
  1086. }
  1087. if (ARGUMENT_PRESENT(lpcValues)) {
  1088. *lpcValues = Values;
  1089. }
  1090. if (ARGUMENT_PRESENT(lpcchMaxValueNameLen)) {
  1091. *lpcchMaxValueNameLen = MaxValueNameLen;
  1092. }
  1093. if (ARGUMENT_PRESENT(lpcbMaxValueLen)) {
  1094. *lpcbMaxValueLen = MaxValueLen;
  1095. }
  1096. if (ARGUMENT_PRESENT(lpcbSecurityDescriptor)) {
  1097. *lpcbSecurityDescriptor = SecurityDescriptor;
  1098. }
  1099. if (ARGUMENT_PRESENT(lpftLastWriteTime)) {
  1100. *lpftLastWriteTime = LastWriteTime;
  1101. }
  1102. }
  1103. return(Status);
  1104. }
  1105. LONG
  1106. WINAPI
  1107. ClusterRegGetKeySecurity(
  1108. HKEY hKey,
  1109. SECURITY_INFORMATION RequestedInformation,
  1110. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1111. LPDWORD lpcbSecurityDescriptor
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. Retrieves a copy of the security descriptor protecting
  1116. the specified cluster registry key.
  1117. Arguments:
  1118. hKey - Supplies the handle of the key
  1119. RequestedInformation - Specifies a SECURITY_INFORMATION structure that
  1120. indicates the requested security information.
  1121. pSecurityDescriptor - Points to a buffer that receives a copy of the
  1122. requested security descriptor.
  1123. lpcbSecurityDescriptor - Points to a variable that specifies the size,
  1124. in bytes, of the buffer pointed to by the pSecurityDescriptor parameter.
  1125. When the function returns, the variable contains the number of bytes
  1126. written to the buffer.
  1127. Return Value:
  1128. ERROR_SUCCESS if successful
  1129. Win32 error code otherwise
  1130. --*/
  1131. {
  1132. PCKEY Key = (PCKEY)hKey;
  1133. RPC_SECURITY_DESCRIPTOR RpcSD;
  1134. DWORD Status;
  1135. //
  1136. // Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
  1137. //
  1138. RpcSD.lpSecurityDescriptor = pSecurityDescriptor;
  1139. RpcSD.cbInSecurityDescriptor = *lpcbSecurityDescriptor;
  1140. RpcSD.cbOutSecurityDescriptor = 0;
  1141. WRAP(Status,
  1142. (ApiGetKeySecurity(Key->RemoteKey,
  1143. RequestedInformation,
  1144. &RpcSD)),
  1145. Key->Cluster);
  1146. //
  1147. // Extract the size of the SECURITY_DESCRIPTOR from the RPCable version.
  1148. //
  1149. *lpcbSecurityDescriptor = RpcSD.cbOutSecurityDescriptor;
  1150. return Status;
  1151. }
  1152. LONG
  1153. WINAPI
  1154. ClusterRegSetKeySecurity(
  1155. HKEY hKey,
  1156. SECURITY_INFORMATION SecurityInformation,
  1157. PSECURITY_DESCRIPTOR pSecurityDescriptor
  1158. )
  1159. /*++
  1160. Routine Description:
  1161. Sets the security of an open cluster registry key.
  1162. Arguments:
  1163. hKey - Supplies the cluster registry key
  1164. SecurityInformation - Specifies a SECURITY_INFORMATION structure that
  1165. indicates the contents of the supplied security descriptor.
  1166. pSecurityDescriptor - Points to a SECURITY_DESCRIPTOR structure that
  1167. specifies the security attributes to set for the specified key.
  1168. Return Value:
  1169. ERROR_SUCCESS if successful
  1170. Win32 error code otherwise
  1171. --*/
  1172. {
  1173. PCKEY Key = (PCKEY)hKey;
  1174. RPC_SECURITY_DESCRIPTOR RpcSD;
  1175. DWORD Status;
  1176. //
  1177. // Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
  1178. //
  1179. RpcSD.lpSecurityDescriptor = NULL;
  1180. Status = MapSDToRpcSD(pSecurityDescriptor,&RpcSD);
  1181. if (Status != ERROR_SUCCESS) {
  1182. return(Status);
  1183. }
  1184. WRAP(Status,
  1185. (ApiSetKeySecurity(Key->RemoteKey,
  1186. SecurityInformation,
  1187. &RpcSD)),
  1188. Key->Cluster);
  1189. //
  1190. // Free the buffer allocated by MapSDToRpcSD.
  1191. //
  1192. LocalFree(RpcSD.lpSecurityDescriptor);
  1193. return(Status);
  1194. }