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.

1574 lines
39 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. if ((Key->RemoteKey == NULL) ||
  492. (Status != ERROR_SUCCESS)) {
  493. *phkResult = NULL;
  494. LocalFree(Key->RelativeName);
  495. LocalFree(Key);
  496. return(Status);
  497. }
  498. EnterCriticalSection(&Cluster->Lock);
  499. InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
  500. LeaveCriticalSection(&Cluster->Lock);
  501. *phkResult = (HKEY)Key;
  502. return(ERROR_SUCCESS);
  503. }
  504. LONG
  505. WINAPI
  506. ClusterRegOpenKey(
  507. IN HKEY hKey,
  508. IN LPCWSTR lpSubKey,
  509. IN REGSAM samDesired,
  510. OUT PHKEY phkResult
  511. )
  512. /*++
  513. Routine Description:
  514. Opens the specified key in the cluster registry.
  515. Arguments:
  516. hKey - Supplies a currently open key.
  517. lpSubKey - Points to a null-terminated string specifying the name
  518. of a subkey that this function opens or creates. The subkey
  519. specified must be a subkey of the key identified by the hKey
  520. parameter. This subkey must not begin with the backslash
  521. character ('\'). This parameter cannot be NULL.
  522. samDesired - Specifies an access mask that specifies the desired security
  523. access for the new key
  524. phkResult - Points to a variable that receives the handle of the opened
  525. or created key. Initialized to NULL on failure.
  526. Return Value:
  527. If the function succeeds, the return value is ERROR_SUCCESS.
  528. If the function fails, the return value is an error value.
  529. --*/
  530. {
  531. PCKEY Key;
  532. PCKEY ParentKey = (PCKEY)hKey;
  533. PCLUSTER Cluster = ParentKey->Cluster;
  534. error_status_t Status = ERROR_SUCCESS;
  535. //
  536. // Allocate new CKEY structure and create cluster registry key
  537. //
  538. Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
  539. if (Key == NULL) {
  540. return(ERROR_NOT_ENOUGH_MEMORY);
  541. }
  542. *phkResult = NULL;
  543. Key->Parent = ParentKey;
  544. Key->RelativeName = LocalAlloc(LMEM_FIXED, (lstrlenW(lpSubKey)+1)*sizeof(WCHAR));
  545. if (Key->RelativeName == NULL) {
  546. LocalFree(Key);
  547. return(ERROR_NOT_ENOUGH_MEMORY);
  548. }
  549. lstrcpyW(Key->RelativeName, lpSubKey);
  550. Key->SamDesired = samDesired;
  551. Key->Cluster = Cluster;
  552. InitializeListHead(&Key->ChildList);
  553. InitializeListHead(&Key->NotifyList);
  554. WRAP_NULL(Key->RemoteKey,
  555. (ApiOpenKey(ParentKey->RemoteKey,
  556. lpSubKey,
  557. samDesired,
  558. &Status)),
  559. &Status,
  560. ParentKey->Cluster);
  561. if (Status != ERROR_SUCCESS) {
  562. LocalFree(Key->RelativeName);
  563. LocalFree(Key);
  564. return(Status);
  565. }
  566. EnterCriticalSection(&Cluster->Lock);
  567. InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
  568. LeaveCriticalSection(&Cluster->Lock);
  569. *phkResult = (HKEY)Key;
  570. return(ERROR_SUCCESS);
  571. }
  572. LONG
  573. WINAPI
  574. ClusterRegDeleteKey(
  575. IN HKEY hKey,
  576. IN LPCWSTR lpSubKey
  577. )
  578. /*++
  579. Routine Description:
  580. Deletes the specified key. A key that has subkeys cannot
  581. be deleted.
  582. Arguments:
  583. hKey - Supplies a handle to a currently open key.
  584. lpSubKey - Points to a null-terminated string specifying the
  585. name of the key to delete. This parameter cannot be NULL,
  586. and the specified key must not have subkeys.
  587. Return Value:
  588. If the function succeeds, the return value is ERROR_SUCCESS.
  589. If the function fails, the return value is an error value.
  590. --*/
  591. {
  592. PCKEY Key = (PCKEY)hKey;
  593. DWORD Status;
  594. WRAP(Status,
  595. (ApiDeleteKey(Key->RemoteKey, lpSubKey)),
  596. Key->Cluster);
  597. return(Status);
  598. }
  599. LONG
  600. WINAPI
  601. ClusterRegCloseKey(
  602. IN HKEY hKey
  603. )
  604. /*++
  605. Routine Description:
  606. Closes the handle of the specified cluster registry key
  607. Arguments:
  608. hKey - Supplies the open key to close
  609. Return Value:
  610. If the function succeeds, the return value is ERROR_SUCCESS.
  611. If the function fails, the return value is an error value.
  612. --*/
  613. {
  614. PCKEY Key = (PCKEY)hKey;
  615. PCLUSTER Cluster = Key->Cluster;
  616. //
  617. // If any keys have been opened relative to this key, we need to
  618. // keep this CKEY around so that we can reconstruct the key names
  619. // if we need to reopen the handles.
  620. //
  621. // If there are no children of this key, all the storage can be
  622. // freed. Note that freeing this key may also require us to free
  623. // up its parent if the parent has been closed but not freed because
  624. // it has children.
  625. //
  626. EnterCriticalSection(&Cluster->Lock);
  627. if (Cluster->Flags & CLUS_DEAD)
  628. {
  629. if (Key->RemoteKey)
  630. RpcSmDestroyClientContext(&Key->RemoteKey);
  631. }
  632. else
  633. {
  634. ApiCloseKey(&Key->RemoteKey);
  635. }
  636. //
  637. // Remove any notifications posted against this key.
  638. //
  639. RundownNotifyEvents(&Key->NotifyList, L"");
  640. if (IsListEmpty(&Key->ChildList)) {
  641. FreeKey(Key);
  642. }
  643. LeaveCriticalSection(&Cluster->Lock);
  644. //
  645. // If this key was the last thing keeping the cluster structure
  646. // around, we can clean it up now.
  647. //
  648. CleanupCluster(Cluster);
  649. return(ERROR_SUCCESS);
  650. }
  651. VOID
  652. FreeKey(
  653. IN PCKEY Key
  654. )
  655. /*++
  656. Routine Description:
  657. Frees up the storage for a key and removes it from its
  658. parent's ChildList. If this is the last key in its parent's
  659. ChildList, this routine calls itself recursively to free
  660. the parent storage.
  661. Arguments:
  662. Key - Supplies the CKEY to be freed.
  663. Return Value:
  664. None.
  665. --*/
  666. {
  667. RemoveEntryList(&Key->ParentList);
  668. if (Key->Parent != NULL) {
  669. //
  670. // This is not a root key, so see if we need to free the
  671. // parent.
  672. //
  673. if ((Key->Parent->RemoteKey == NULL) &&
  674. (IsListEmpty(&Key->Parent->ChildList))) {
  675. FreeKey(Key->Parent);
  676. }
  677. LocalFree(Key->RelativeName);
  678. }
  679. LocalFree(Key);
  680. }
  681. LONG
  682. WINAPI
  683. ClusterRegEnumKey(
  684. IN HKEY hKey,
  685. IN DWORD dwIndex,
  686. OUT LPWSTR lpszName,
  687. IN OUT LPDWORD lpcchName,
  688. OUT PFILETIME lpftLastWriteTime
  689. )
  690. /*++
  691. Routine Description:
  692. Enumerates subkeys of the specified open cluster registry key.
  693. The function retrieves information about one subkey each time it is called.
  694. Arguments:
  695. hKey - Supplies a currently open key or NULL. If NULL is specified,
  696. the root of the cluster registry is enumerated.
  697. dwIndex - Supplies the index of the subkey to retrieve. This parameter
  698. should be zero for the first call to the RegEnumKeyEx function
  699. and then incremented for subsequent calls. Because subkeys are
  700. not ordered, any new subkey will have an arbitrary index. This
  701. means that the function may return subkeys in any order.
  702. lpszName - Points to a buffer that receives the name of the subkey,
  703. including the terminating null character. The function copies
  704. only the name of the subkey, not the full key hierarchy, to
  705. the buffer.
  706. lpcchName - Points to a variable that specifies the size, in characters,
  707. of the buffer specified by the lpszName parameter. This size should
  708. include the terminating null character. When the function returns,
  709. the variable pointed to by lpcchName contains the number of characters
  710. stored in the buffer. The count returned does not include the
  711. terminating null character.
  712. lpftLastWriteTime - Points to a variable that receives the time the
  713. enumerated subkey was last written to.
  714. Return Value:
  715. If the function succeeds, the return value is ERROR_SUCCESS.
  716. If the function fails, the return value is an error value.
  717. --*/
  718. {
  719. PCKEY Key = (PCKEY)hKey;
  720. LONG Status;
  721. FILETIME LastWriteTime;
  722. LPWSTR KeyName=NULL;
  723. DWORD dwNameLen;
  724. WRAP(Status,
  725. (ApiEnumKey(Key->RemoteKey,
  726. dwIndex,
  727. &KeyName,
  728. &LastWriteTime)),
  729. Key->Cluster);
  730. if (Status != ERROR_SUCCESS) {
  731. return(Status);
  732. }
  733. MylstrcpynW(lpszName, KeyName, *lpcchName);
  734. dwNameLen = lstrlenW(KeyName);
  735. if (*lpcchName < (dwNameLen + 1)) {
  736. if (lpszName != NULL) {
  737. Status = ERROR_MORE_DATA;
  738. }
  739. }
  740. *lpcchName = dwNameLen;
  741. MIDL_user_free(KeyName);
  742. return(Status);
  743. }
  744. DWORD
  745. WINAPI
  746. ClusterRegSetValue(
  747. IN HKEY hKey,
  748. IN LPCWSTR lpszValueName,
  749. IN DWORD dwType,
  750. IN CONST BYTE* lpData,
  751. IN DWORD cbData
  752. )
  753. /*++
  754. Routine Description:
  755. Sets the named value for the given resource.
  756. Arguments:
  757. hKey - Supplies the handle of the cluster registry key.
  758. lpszValueName - Supplies a pointer to a string containing
  759. the name of the value to set. If a value with this
  760. name is not already present in the resource, the function
  761. adds it to the resource.
  762. dwType - Supplies the type of information to be stored as the
  763. value's data. This parameter can be one of the following values:
  764. Value Meaning
  765. REG_BINARY Binary data in any form.
  766. REG_DWORD A 32-bit number.
  767. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  768. references to environment variables (for example, "%PATH%").
  769. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  770. by two null characters.
  771. REG_NONE No defined value type.
  772. REG_SZ A null-terminated Unicode string.
  773. lpData - Supplies a pointer to a buffer containing the data
  774. to be stored with the specified value name.
  775. cbData - Supplies the size, in bytes, of the information
  776. pointed to by the lpData parameter. If the data
  777. is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ,
  778. cbData must include the size of the terminating null character.
  779. Return value:
  780. If the function succeeds, the return value is ERROR_SUCCESS.
  781. If the function fails, the return value is an error value.
  782. --*/
  783. {
  784. PCKEY Key = (PCKEY)hKey;
  785. DWORD Status;
  786. WRAP(Status,
  787. (ApiSetValue(Key->RemoteKey,
  788. lpszValueName,
  789. dwType,
  790. lpData,
  791. cbData)),
  792. Key->Cluster);
  793. return(Status);
  794. }
  795. DWORD
  796. WINAPI
  797. ClusterRegDeleteValue(
  798. IN HKEY hKey,
  799. IN LPCWSTR lpszValueName
  800. )
  801. /*++
  802. Routine Description:
  803. Removes the specified value from a given registry subkey
  804. Arguments:
  805. hKey - Supplies the key whose value is to be deleted.
  806. lpszValueName - Supplies the name of the value to be removed.
  807. Return Value:
  808. If the function succeeds, the return value is ERROR_SUCCESS.
  809. If the function fails, the return value is an error value.
  810. --*/
  811. {
  812. PCKEY Key = (PCKEY)hKey;
  813. DWORD Status;
  814. WRAP(Status,
  815. (ApiDeleteValue(Key->RemoteKey, lpszValueName)),
  816. Key->Cluster);
  817. return(Status);
  818. }
  819. LONG
  820. WINAPI
  821. ClusterRegQueryValue(
  822. IN HKEY hKey,
  823. IN LPCWSTR lpszValueName,
  824. OUT LPDWORD lpdwValueType,
  825. OUT LPBYTE lpData,
  826. IN OUT LPDWORD lpcbData
  827. )
  828. /*++
  829. Routine Description:
  830. Retrieves the type and data for a specified value name associated with
  831. an open cluster registry key.
  832. Arguments:
  833. hKey - Supplies the handle of the cluster registry key.
  834. lpszValueName - Supplies a pointer to a string containing the
  835. name of the value to be queried.
  836. lpdwValueType - Points to a variable that receives the key's value
  837. type. The value returned through this parameter will
  838. be one of the following:
  839. Value Meaning
  840. REG_BINARY Binary data in any form.
  841. REG_DWORD A 32-bit number.
  842. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  843. references to environment variables (for example, "%PATH%").
  844. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  845. by two null characters.
  846. REG_NONE No defined value type.
  847. REG_SZ A null-terminated Unicode string.
  848. The lpdwValueType parameter can be NULL if the type is not required
  849. lpData - Points to a buffer that receives the value's data. This parameter
  850. can be NULL if the data is not required.
  851. lpcbData - Points to a variable that specifies the size, in bytes, of the buffer
  852. pointed to by the lpData parameter. When the function returns, this
  853. variable contains the size of the data copied to lpData.
  854. If the buffer specified by lpData parameter is not large enough to hold
  855. the data, the function returns the value ERROR_MORE_DATA, and stores the
  856. required buffer size, in bytes, into the variable pointed to by
  857. lpcbData.
  858. If lpData is NULL, and lpcbData is non-NULL, the function returns
  859. ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable
  860. pointed to by lpcbData. This lets an application determine the best way
  861. to allocate a buffer for the value key's data.
  862. If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, then
  863. lpData will also include the size of the terminating null character.
  864. The lpcbData parameter can be NULL only if lpData is NULL.
  865. Return Value:
  866. If the function succeeds, the return value is ERROR_SUCCESS.
  867. If the function fails, the return value is an error value.
  868. --*/
  869. {
  870. DWORD Dummy1;
  871. DWORD Dummy2;
  872. DWORD Required;
  873. PCKEY Key = (PCKEY)hKey;
  874. DWORD Status;
  875. LPBYTE TempData;
  876. DWORD BufferSize;
  877. if (lpdwValueType == NULL) {
  878. lpdwValueType = &Dummy1;
  879. }
  880. if (lpData == NULL) {
  881. TempData = (LPBYTE)&Dummy2;
  882. BufferSize = 0;
  883. } else {
  884. TempData = lpData;
  885. BufferSize = *lpcbData;
  886. }
  887. WRAP(Status,
  888. (ApiQueryValue(Key->RemoteKey,
  889. lpszValueName,
  890. lpdwValueType,
  891. TempData,
  892. BufferSize,
  893. &Required)),
  894. Key->Cluster);
  895. if ((Status == ERROR_SUCCESS) ||
  896. (Status == ERROR_MORE_DATA)) {
  897. if ((Status == ERROR_MORE_DATA) &&
  898. (lpData == NULL)) {
  899. //
  900. // Map this error to success to match the spec.
  901. //
  902. Status = ERROR_SUCCESS;
  903. }
  904. *lpcbData = Required;
  905. }
  906. return(Status);
  907. }
  908. DWORD
  909. WINAPI
  910. ClusterRegEnumValue(
  911. IN HKEY hKey,
  912. IN DWORD dwIndex,
  913. OUT LPWSTR lpszValueName,
  914. IN OUT LPDWORD lpcchValueName,
  915. IN LPDWORD lpdwType,
  916. OUT LPBYTE lpData,
  917. IN OUT LPDWORD lpcbData
  918. )
  919. /*++
  920. Routine Description:
  921. Enumerates the properties of the given resource.
  922. Arguments:
  923. hKey - Supplies the handle of the key
  924. dwIndex - Specifies the index of the value to retrieve. This parameter
  925. should be zero for the first call to the EnumClusterResourceValue
  926. function and then be incremented for subsequent calls. Because
  927. properties are not ordered, any new value will have an arbitrary
  928. index. This means that the function may return properties in any
  929. order.
  930. lpszValueName - Points to a buffer that receives the name of the value,
  931. including the terminating null character.
  932. lpcchValueName - Points to a variable that specifies the size, in characters,
  933. of the buffer pointed to by the lpszValueName parameter. This size
  934. should include the terminating null character. When the function returns,
  935. the variable pointed to by lpcchValueName contains the number of
  936. characters stored in the buffer. The count returned does not include
  937. the terminating null character.
  938. lpdwType - Points to a variable that receives the type code for the value entry.
  939. The type code can be one of the following values:
  940. Value Meaning
  941. REG_BINARY Binary data in any form.
  942. REG_DWORD A 32-bit number.
  943. REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
  944. references to environment variables (for example, "%PATH%").
  945. REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
  946. by two null characters.
  947. REG_NONE No defined value type.
  948. REG_SZ A null-terminated Unicode string.
  949. The lpdwType parameter can be NULL if the type code is not required.
  950. lpData - Points to a buffer that receives the data for the value entry.
  951. This parameter can be NULL if the data is not required.
  952. lpcbData - Points to a variable that specifies the size, in bytes, of the
  953. buffer pointed to by the lpData parameter. When the function
  954. returns, the variable pointed to by the lpcbData parameter contains
  955. the number of bytes stored in the buffer. This parameter can be NULL
  956. only if lpData is NULL.
  957. Return Value:
  958. If the function succeeds, the return value is ERROR_SUCCESS.
  959. If the function fails, the return value is an error value.
  960. --*/
  961. {
  962. PCKEY Key = (PCKEY)hKey;
  963. LONG Status;
  964. LPWSTR ValueName=NULL;
  965. DWORD TotalSize;
  966. DWORD DummyType;
  967. BYTE DummyData;
  968. DWORD DummycbData;
  969. DWORD dwNameLen;
  970. if (lpdwType == NULL) {
  971. lpdwType = &DummyType;
  972. }
  973. if (lpcbData == NULL) {
  974. if (lpData != NULL) {
  975. return(ERROR_INVALID_PARAMETER);
  976. }
  977. DummycbData = 0;
  978. lpcbData = &DummycbData;
  979. }
  980. if (lpData == NULL) {
  981. lpData = &DummyData;
  982. }
  983. WRAP(Status,
  984. (ApiEnumValue(Key->RemoteKey,
  985. dwIndex,
  986. &ValueName,
  987. lpdwType,
  988. lpData,
  989. lpcbData,
  990. &TotalSize)),
  991. Key->Cluster);
  992. if ((Status != ERROR_SUCCESS) &&
  993. (Status != ERROR_MORE_DATA)) {
  994. return(Status);
  995. }
  996. if (Status == ERROR_MORE_DATA) {
  997. *lpcbData = TotalSize;
  998. if (lpData == &DummyData) {
  999. Status = ERROR_SUCCESS;
  1000. }
  1001. }
  1002. MylstrcpynW(lpszValueName, ValueName, *lpcchValueName);
  1003. dwNameLen = lstrlenW(ValueName);
  1004. if (*lpcchValueName < (dwNameLen + 1)) {
  1005. if (lpszValueName != NULL) {
  1006. Status = ERROR_MORE_DATA;
  1007. }
  1008. }
  1009. *lpcchValueName = dwNameLen;
  1010. MIDL_user_free(ValueName);
  1011. return(Status);
  1012. }
  1013. LONG
  1014. WINAPI
  1015. ClusterRegQueryInfoKey(
  1016. HKEY hKey,
  1017. LPDWORD lpcSubKeys,
  1018. LPDWORD lpcchMaxSubKeyLen,
  1019. LPDWORD lpcValues,
  1020. LPDWORD lpcchMaxValueNameLen,
  1021. LPDWORD lpcbMaxValueLen,
  1022. LPDWORD lpcbSecurityDescriptor,
  1023. PFILETIME lpftLastWriteTime
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. Retrieves information about a specified cluster registry key.
  1028. Arguments:
  1029. hKey - Supplies the handle of the key.
  1030. lpcSubKeys - Points to a variable that receives the number of subkeys
  1031. contained by the specified key. This parameter can be NULL.
  1032. lpcchMaxSubKeyLen - Points to a variable that receives the length, in
  1033. characters, of the key's subkey with the longest name. The count
  1034. returned does not include the terminating null character. This parameter can be NULL.
  1035. lpcValues - Points to a variable that receives the number of values
  1036. associated with the key. This parameter can be NULL.
  1037. lpcchMaxValueNameLen - Points to a variable that receives the length,
  1038. in characters, of the key's longest value name. The count returned
  1039. does not include the terminating null character. This parameter can be NULL.
  1040. lpcbMaxValueLen - Points to a variable that receives the length, in
  1041. bytes, of the longest data component among the key's values. This parameter can be NULL.
  1042. lpcbSecurityDescriptor - Points to a variable that receives the length,
  1043. in bytes, of the key's security descriptor. This parameter can be NULL.
  1044. lpftLastWriteTime - Pointer to a FILETIME structure. This parameter can be NULL.
  1045. Return Value:
  1046. ERROR_SUCCESS if successful
  1047. Win32 error code otherwise
  1048. --*/
  1049. {
  1050. DWORD SubKeys;
  1051. DWORD MaxSubKeyLen;
  1052. DWORD Values;
  1053. DWORD MaxValueNameLen;
  1054. DWORD MaxValueLen;
  1055. DWORD SecurityDescriptor;
  1056. DWORD Status;
  1057. FILETIME LastWriteTime;
  1058. PCKEY Key = (PCKEY)hKey;
  1059. WRAP(Status,
  1060. ApiQueryInfoKey(Key->RemoteKey,
  1061. &SubKeys,
  1062. &MaxSubKeyLen,
  1063. &Values,
  1064. &MaxValueNameLen,
  1065. &MaxValueLen,
  1066. &SecurityDescriptor,
  1067. &LastWriteTime),
  1068. Key->Cluster);
  1069. if (Status == ERROR_SUCCESS) {
  1070. if (ARGUMENT_PRESENT(lpcSubKeys)) {
  1071. *lpcSubKeys = SubKeys;
  1072. }
  1073. if (ARGUMENT_PRESENT(lpcchMaxSubKeyLen)) {
  1074. *lpcchMaxSubKeyLen = MaxSubKeyLen;
  1075. }
  1076. if (ARGUMENT_PRESENT(lpcValues)) {
  1077. *lpcValues = Values;
  1078. }
  1079. if (ARGUMENT_PRESENT(lpcchMaxValueNameLen)) {
  1080. *lpcchMaxValueNameLen = MaxValueNameLen;
  1081. }
  1082. if (ARGUMENT_PRESENT(lpcbMaxValueLen)) {
  1083. *lpcbMaxValueLen = MaxValueLen;
  1084. }
  1085. if (ARGUMENT_PRESENT(lpcbSecurityDescriptor)) {
  1086. *lpcbSecurityDescriptor = SecurityDescriptor;
  1087. }
  1088. if (ARGUMENT_PRESENT(lpftLastWriteTime)) {
  1089. *lpftLastWriteTime = LastWriteTime;
  1090. }
  1091. }
  1092. return(Status);
  1093. }
  1094. LONG
  1095. WINAPI
  1096. ClusterRegGetKeySecurity(
  1097. HKEY hKey,
  1098. SECURITY_INFORMATION RequestedInformation,
  1099. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1100. LPDWORD lpcbSecurityDescriptor
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. Retrieves a copy of the security descriptor protecting
  1105. the specified cluster registry key.
  1106. Arguments:
  1107. hKey - Supplies the handle of the key
  1108. RequestedInformation - Specifies a SECURITY_INFORMATION structure that
  1109. indicates the requested security information.
  1110. pSecurityDescriptor - Points to a buffer that receives a copy of the
  1111. requested security descriptor.
  1112. lpcbSecurityDescriptor - Points to a variable that specifies the size,
  1113. in bytes, of the buffer pointed to by the pSecurityDescriptor parameter.
  1114. When the function returns, the variable contains the number of bytes
  1115. written to the buffer.
  1116. Return Value:
  1117. ERROR_SUCCESS if successful
  1118. Win32 error code otherwise
  1119. --*/
  1120. {
  1121. PCKEY Key = (PCKEY)hKey;
  1122. RPC_SECURITY_DESCRIPTOR RpcSD;
  1123. DWORD Status;
  1124. //
  1125. // Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
  1126. //
  1127. RpcSD.lpSecurityDescriptor = pSecurityDescriptor;
  1128. RpcSD.cbInSecurityDescriptor = *lpcbSecurityDescriptor;
  1129. RpcSD.cbOutSecurityDescriptor = 0;
  1130. WRAP(Status,
  1131. (ApiGetKeySecurity(Key->RemoteKey,
  1132. RequestedInformation,
  1133. &RpcSD)),
  1134. Key->Cluster);
  1135. //
  1136. // Extract the size of the SECURITY_DESCRIPTOR from the RPCable version.
  1137. //
  1138. *lpcbSecurityDescriptor = RpcSD.cbOutSecurityDescriptor;
  1139. return Status;
  1140. }
  1141. LONG
  1142. WINAPI
  1143. ClusterRegSetKeySecurity(
  1144. HKEY hKey,
  1145. SECURITY_INFORMATION SecurityInformation,
  1146. PSECURITY_DESCRIPTOR pSecurityDescriptor
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. Sets the security of an open cluster registry key.
  1151. Arguments:
  1152. hKey - Supplies the cluster registry key
  1153. SecurityInformation - Specifies a SECURITY_INFORMATION structure that
  1154. indicates the contents of the supplied security descriptor.
  1155. pSecurityDescriptor - Points to a SECURITY_DESCRIPTOR structure that
  1156. specifies the security attributes to set for the specified key.
  1157. Return Value:
  1158. ERROR_SUCCESS if successful
  1159. Win32 error code otherwise
  1160. --*/
  1161. {
  1162. PCKEY Key = (PCKEY)hKey;
  1163. RPC_SECURITY_DESCRIPTOR RpcSD;
  1164. DWORD Status;
  1165. //
  1166. // Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
  1167. //
  1168. RpcSD.lpSecurityDescriptor = NULL;
  1169. Status = MapSDToRpcSD(pSecurityDescriptor,&RpcSD);
  1170. if (Status != ERROR_SUCCESS) {
  1171. return(Status);
  1172. }
  1173. WRAP(Status,
  1174. (ApiSetKeySecurity(Key->RemoteKey,
  1175. SecurityInformation,
  1176. &RpcSD)),
  1177. Key->Cluster);
  1178. //
  1179. // Free the buffer allocated by MapSDToRpcSD.
  1180. //
  1181. LocalFree(RpcSD.lpSecurityDescriptor);
  1182. return(Status);
  1183. }