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.

1059 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. edithive.c
  5. Abstract:
  6. Provides functionality for dumping and editing registry hive files from
  7. user-mode.
  8. Author:
  9. John Vert (jvert) 26-Mar-1992
  10. Revision History:
  11. --*/
  12. #include "edithive.h"
  13. #include "nturtl.h"
  14. extern GENERIC_MAPPING CmpKeyMapping;
  15. extern LIST_ENTRY CmpHiveListHead; // List of CMHIVEs
  16. #define SECURITY_CELL_LENGTH(pDescriptor) \
  17. FIELD_OFFSET(CM_KEY_SECURITY,Descriptor) + \
  18. RtlLengthSecurityDescriptor(pDescriptor)
  19. NTSTATUS
  20. EhpAttachSecurity(
  21. IN PHHIVE Hive,
  22. IN HCELL_INDEX Cell
  23. );
  24. PVOID
  25. EhpAllocate(
  26. ULONG Size
  27. );
  28. VOID
  29. EhpFree(
  30. PVOID MemoryBlock
  31. );
  32. BOOLEAN
  33. EhpFileRead (
  34. HANDLE FileHandle,
  35. PULONG FileOffset,
  36. PVOID DataBuffer,
  37. ULONG DataLength
  38. );
  39. BOOLEAN
  40. EhpFileWrite(
  41. HANDLE FileHandle,
  42. PULONG FileOffset,
  43. PVOID DataBuffer,
  44. ULONG DataLength
  45. );
  46. BOOLEAN
  47. EhpFileFlush (
  48. HANDLE FileHandle
  49. );
  50. VOID
  51. CmpGetObjectSecurity(
  52. IN HCELL_INDEX Cell,
  53. IN PHHIVE Hive,
  54. OUT PCM_KEY_SECURITY *Security,
  55. OUT PHCELL_INDEX SecurityCell OPTIONAL
  56. )
  57. /*++
  58. Routine Description:
  59. This routine maps in the security cell of a registry object.
  60. Arguments:
  61. Cell - Supplies the cell index of the object.
  62. Hive - Supplies the hive the object's cell is in.
  63. Security - Returns a pointer to the security cell of the object.
  64. SecurityCell - Returns the index of the security cell
  65. Return Value:
  66. NONE.
  67. --*/
  68. {
  69. HCELL_INDEX CellIndex;
  70. PCM_KEY_NODE Node;
  71. //
  72. // Map the node we need to get the security descriptor for
  73. //
  74. Node = (PCM_KEY_NODE) HvGetCell(Hive, Cell);
  75. CellIndex = Node->u1.s1.Security;
  76. //
  77. // Map in the security descriptor cell
  78. //
  79. *Security = (PCM_KEY_SECURITY) HvGetCell(Hive, CellIndex);
  80. if (ARGUMENT_PRESENT(SecurityCell)) {
  81. *SecurityCell = CellIndex;
  82. }
  83. return;
  84. }
  85. VOID
  86. EhCloseHive(
  87. IN HANDLE HiveHandle
  88. )
  89. /*++
  90. Routine Description:
  91. Closes a hive, including writing all the data out to disk and freeing
  92. the relevant structures.
  93. Arguments:
  94. HiveHandle - Supplies a handle to the hive control structure
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. HvSyncHive((PHHIVE)HiveHandle);
  100. NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_PRIMARY]);
  101. NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_ALTERNATE]);
  102. NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_LOG]);
  103. CmpFree((PCMHIVE)HiveHandle, sizeof(CMHIVE));
  104. }
  105. HANDLE
  106. EhOpenHive(
  107. IN PUNICODE_STRING FileName,
  108. OUT PHANDLE RootHandle,
  109. IN PUNICODE_STRING RootName,
  110. IN ULONG HiveType
  111. )
  112. /*++
  113. Routine Description:
  114. Opens an existing hive. If the filename does not exist it will be
  115. created.
  116. WARNING: Allocate FileName large enough to acomodate .log or
  117. .alt extension.
  118. Arguments:
  119. FileName - Supplies the NULL-terminated filename to open as a hive.
  120. HiveType - TYPE_SIMPLE = no log or alternate
  121. TYPE_LOG = log
  122. TYPE_ALT = alternate
  123. Return Value:
  124. != NULL - Handle to the opened hive.
  125. == NULL - Indicates file could not be opened.
  126. --*/
  127. {
  128. NTSTATUS Status;
  129. HANDLE File;
  130. BOOLEAN Allocate;
  131. PCMHIVE Hive;
  132. IO_STATUS_BLOCK IoStatus;
  133. ULONG CreateDisposition;
  134. OBJECT_ATTRIBUTES ObjectAttributes;
  135. PCM_KEY_NODE RootNode;
  136. HANDLE Handle;
  137. HANDLE Primary;
  138. HANDLE Log;
  139. HANDLE Alt;
  140. ULONG FileType;
  141. ULONG Disposition;
  142. ULONG SecondaryDisposition;
  143. ULONG Operation;
  144. Alt = NULL;
  145. Log = NULL;
  146. InitializeListHead(&CmpHiveListHead);
  147. switch (HiveType) {
  148. case TYPE_SIMPLE:
  149. Status = CmpOpenHiveFiles(
  150. FileName,
  151. NULL,
  152. &Primary,
  153. NULL,
  154. &Disposition,
  155. &SecondaryDisposition,
  156. TRUE,
  157. NULL
  158. );
  159. if (!NT_SUCCESS(Status))
  160. {
  161. return NULL;
  162. }
  163. FileType = HFILE_TYPE_PRIMARY;
  164. break;
  165. case TYPE_LOG:
  166. Status = CmpOpenHiveFiles(
  167. FileName,
  168. L".log",
  169. &Primary,
  170. &Log,
  171. &Disposition,
  172. &SecondaryDisposition,
  173. TRUE,
  174. NULL
  175. );
  176. if (!NT_SUCCESS(Status))
  177. {
  178. return NULL;
  179. }
  180. if (Log == NULL) {
  181. return NULL;
  182. }
  183. FileType = HFILE_TYPE_LOG;
  184. break;
  185. case TYPE_ALT:
  186. Status = CmpOpenHiveFiles(
  187. FileName,
  188. L".alt",
  189. &Primary,
  190. &Alt,
  191. &Disposition,
  192. &SecondaryDisposition,
  193. TRUE,
  194. NULL
  195. );
  196. if (!NT_SUCCESS(Status))
  197. {
  198. return NULL;
  199. }
  200. if (Alt == NULL) {
  201. return NULL;
  202. }
  203. FileType = HFILE_TYPE_ALTERNATE;
  204. break;
  205. default:
  206. return NULL;
  207. }
  208. //
  209. // Initialize hive
  210. //
  211. if (Disposition == FILE_CREATED) {
  212. Operation = HINIT_CREATE;
  213. Allocate = TRUE;
  214. } else {
  215. Operation = HINIT_FILE;
  216. Allocate = FALSE;
  217. }
  218. if ( ! CmpInitializeHive(
  219. &Hive,
  220. Operation,
  221. FALSE,
  222. FileType,
  223. NULL,
  224. Primary,
  225. Alt,
  226. Log,
  227. NULL,
  228. NULL
  229. ))
  230. {
  231. return NULL;
  232. }
  233. if (!Allocate) {
  234. *RootHandle = (HANDLE)(Hive->Hive.BaseBlock->RootCell);
  235. RootNode = (PCM_KEY_NODE)HvGetCell(
  236. (PHHIVE)Hive, Hive->Hive.BaseBlock->RootCell);
  237. RootName->Length = RootName->MaximumLength = RootNode->NameLength;
  238. RootName->Buffer = RootNode->Name;
  239. } else {
  240. RtlInitUnicodeString(RootName, L"HiveRoot");
  241. *RootHandle = (HANDLE)HCELL_NIL;
  242. HvSyncHive((PHHIVE)Hive);
  243. }
  244. return((HANDLE)Hive);
  245. }
  246. NTSTATUS
  247. EhEnumerateKey(
  248. IN HANDLE HiveHandle,
  249. IN HANDLE CellHandle,
  250. IN ULONG Index,
  251. IN KEY_INFORMATION_CLASS KeyInformationClass,
  252. IN PVOID KeyInformation,
  253. IN ULONG Length,
  254. IN PULONG ResultLength
  255. )
  256. /*++
  257. Routine Description:
  258. Enumerate sub keys, return data on Index'th entry.
  259. CmEnumerateKey returns the name of the Index'th sub key of the open
  260. key specified. The value STATUS_NO_MORE_ENTRIES will be
  261. returned if value of Index is larger than the number of sub keys.
  262. Note that Index is simply a way to select among child keys. Two calls
  263. to CmEnumerateKey with the same Index are NOT guaranteed to return
  264. the same results.
  265. If KeyInformation is not long enough to hold all requested data,
  266. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  267. set to the number of bytes actually required.
  268. Arguments:
  269. Hive - supplies a pointer to the hive control structure for the hive
  270. Cell - supplies index of node to whose sub keys are to be found
  271. Index - Specifies the (0-based) number of the sub key to be returned.
  272. KeyInformationClass - Specifies the type of information returned in
  273. Buffer. One of the following types:
  274. KeyBasicInformation - return last write time, title index, and name.
  275. (see KEY_BASIC_INFORMATION structure)
  276. KeyNodeInformation - return last write time, title index, name, class.
  277. (see KEY_NODE_INFORMATION structure)
  278. KeyInformation -Supplies pointer to buffer to receive the data.
  279. Length - Length of KeyInformation in bytes.
  280. ResultLength - Number of bytes actually written into KeyInformation.
  281. Return Value:
  282. NTSTATUS - Result code from call, among the following:
  283. <TBS>
  284. --*/
  285. {
  286. CM_KEY_CONTROL_BLOCK kcb;
  287. kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  288. kcb.Delete = FALSE;
  289. kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
  290. kcb.KeyCell = (HCELL_INDEX)CellHandle;
  291. kcb.RefCount = 1;
  292. return(CmEnumerateKey(&kcb,
  293. Index,
  294. KeyInformationClass,
  295. KeyInformation,
  296. Length,
  297. ResultLength));
  298. }
  299. NTSTATUS
  300. EhEnumerateValueKey(
  301. IN HANDLE HiveHandle,
  302. IN HANDLE CellHandle,
  303. IN ULONG Index,
  304. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  305. IN PVOID KeyValueInformation,
  306. IN ULONG Length,
  307. IN PULONG ResultLength
  308. )
  309. /*++
  310. Routine Description:
  311. The value entries of an open key may be enumerated.
  312. CmEnumerateValueKey returns the name of the Index'th value
  313. entry of the open key specified by KeyHandle. The value
  314. STATUS_NO_MORE_ENTRIES will be returned if value of Index is
  315. larger than the number of sub keys.
  316. Note that Index is simply a way to select among value
  317. entries. Two calls to NtEnumerateValueKey with the same Index
  318. are NOT guaranteed to return the same results.
  319. If KeyValueInformation is not long enough to hold all requested data,
  320. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  321. set to the number of bytes actually required.
  322. Arguments:
  323. Hive - supplies a handle to the hive
  324. Cell - supplies handle to node whose sub keys are to be found
  325. Index - Specifies the (0-based) number of the sub key to be returned.
  326. KeyValueInformationClass - Specifies the type of information returned
  327. in Buffer. One of the following types:
  328. KeyValueBasicInformation - return time of last write,
  329. title index, and name. (See KEY_VALUE_BASIC_INFORMATION)
  330. KeyValueFullInformation - return time of last write,
  331. title index, name, class. (See KEY_VALUE_FULL_INFORMATION)
  332. KeyValueInformation -Supplies pointer to buffer to receive the data.
  333. Length - Length of KeyValueInformation in bytes.
  334. ResultLength - Number of bytes actually written into KeyValueInformation.
  335. Return Value:
  336. NTSTATUS - Result code from call, among the following:
  337. <TBS>
  338. --*/
  339. {
  340. CM_KEY_CONTROL_BLOCK kcb;
  341. kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  342. kcb.Delete = FALSE;
  343. kcb.KeyHive = (PHHIVE)&(((PCMHIVE)HiveHandle)->Hive);
  344. kcb.KeyCell = (HCELL_INDEX)CellHandle;
  345. kcb.RefCount = 1;
  346. return(CmEnumerateValueKey(&kcb,
  347. Index,
  348. KeyValueInformationClass,
  349. KeyValueInformation,
  350. Length,
  351. ResultLength));
  352. }
  353. NTSTATUS
  354. EhOpenChildByNumber(
  355. IN HANDLE HiveHandle,
  356. IN HANDLE CellHandle,
  357. IN ULONG Index,
  358. IN NODE_TYPE Type,
  359. OUT PHANDLE ChildCell
  360. )
  361. /*++
  362. Routine Description:
  363. Return the cell index of the Nth child cell.
  364. Arguments:
  365. HiveHandle - handle of hive control structure for hive of interest
  366. CellHandle - handle for parent cell
  367. Index - number of desired child
  368. Type - type of the child object
  369. ChildCell - supplies a pointer to a variable to receive the
  370. HCELL_INDEX of the Index'th child.
  371. Return Value:
  372. status
  373. --*/
  374. {
  375. return(CmpFindChildByNumber(&((PCMHIVE)HiveHandle)->Hive,
  376. (HCELL_INDEX)CellHandle,
  377. Index,
  378. Type,
  379. (PHCELL_INDEX)ChildCell));
  380. }
  381. NTSTATUS
  382. EhSetValueKey(
  383. IN HANDLE HiveHandle,
  384. IN HANDLE CellHandle,
  385. IN PUNICODE_STRING ValueName,
  386. IN ULONG TitleIndex OPTIONAL,
  387. IN ULONG Type,
  388. IN PVOID Data,
  389. IN ULONG DataSize
  390. )
  391. /*++
  392. Routine Description:
  393. A value entry may be created or replaced with EhSetValueKey.
  394. If a value entry with a Value ID (i.e. name) matching the
  395. one specified by ValueName exists, it is deleted and replaced
  396. with the one specified. If no such value entry exists, a new
  397. one is created. NULL is a legal Value ID. While Value IDs must
  398. be unique within any given key, the same Value ID may appear
  399. in many different keys.
  400. Arguments:
  401. HiveHandle - handle of hive control structure for hive of interest
  402. CellHandle - handle for parent cell
  403. ValueName - The unique (relative to the containing key) name
  404. of the value entry. May be NULL.
  405. TitleIndex - Supplies the title index for ValueName. The title
  406. index specifies the index of the localized alias for the ValueName.
  407. Type - The integer type number of the value entry.
  408. Data - Pointer to buffer with actual data for the value entry.
  409. DataSize - Size of Data buffer.
  410. Return Value:
  411. NTSTATUS - Result code from call, among the following:
  412. <TBS>
  413. --*/
  414. {
  415. CM_KEY_CONTROL_BLOCK kcb;
  416. kcb.Delete = FALSE;
  417. kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  418. kcb.KeyHive = (PHHIVE)&(((PCMHIVE)HiveHandle)->Hive);
  419. kcb.KeyCell = (HCELL_INDEX)CellHandle;
  420. kcb.FullName.Length = 0;
  421. kcb.FullName.MaximumLength = 0;
  422. kcb.FullName.Buffer = NULL;
  423. return(CmSetValueKey(&kcb,
  424. *ValueName,
  425. TitleIndex,
  426. Type,
  427. Data,
  428. DataSize));
  429. }
  430. NTSTATUS
  431. EhOpenChildByName(
  432. HANDLE HiveHandle,
  433. HANDLE CellHandle,
  434. PUNICODE_STRING Name,
  435. PHANDLE ChildCell
  436. )
  437. /*++
  438. Routine Description:
  439. Find the child subkey cell specified by Name.
  440. Arguments:
  441. HiveHandle - handle of hive control structure for hive of interest
  442. CellHandle - handle for parent cell
  443. Name - name of child object to find
  444. ChildCell - pointer to variable to receive cell index of child
  445. Return Value:
  446. status
  447. --*/
  448. {
  449. PHCELL_INDEX Index;
  450. return(CmpFindChildByName(&((PCMHIVE)HiveHandle)->Hive,
  451. (HCELL_INDEX)CellHandle,
  452. *Name,
  453. KeyBodyNode,
  454. (PHCELL_INDEX)ChildCell,
  455. &Index));
  456. }
  457. NTSTATUS
  458. EhCreateChild(
  459. IN HANDLE HiveHandle,
  460. IN HANDLE CellHandle,
  461. IN PUNICODE_STRING Name,
  462. OUT PHANDLE ChildCell,
  463. OUT PULONG Disposition OPTIONAL
  464. )
  465. /*++
  466. Routine Description:
  467. Attempts to open the given child subkey specified by name. If the
  468. child does not exist, it is created.
  469. Arguments:
  470. HiveHandle - handle of hive control structure for hive of interest
  471. CellHandle - handle for parent cell
  472. Name - name of child object to create
  473. ChildCell - pointer to variable to receive cell index of child
  474. Disposition - This optional parameter is a pointer to a variable
  475. that will receive a value indicating whether a new Registry
  476. key was created or an existing one opened:
  477. REG_CREATED_NEW_KEY - A new Registry Key was created
  478. REG_OPENED_EXISTING_KEY - An existing Registry Key was opened
  479. Return Value:
  480. status
  481. --*/
  482. {
  483. PHCELL_INDEX Index;
  484. NTSTATUS Status;
  485. PHHIVE Hive;
  486. HCELL_INDEX NewCell;
  487. HCELL_INDEX NewListCell;
  488. HCELL_INDEX OldListCell;
  489. PHCELL_INDEX NewList;
  490. PHCELL_INDEX OldList;
  491. PCM_KEY_NODE Child;
  492. PCM_KEY_NODE Parent;
  493. PCM_KEY_SECURITY Security;
  494. HANDLE Handle;
  495. ULONG oldcount;
  496. Hive = &((PCMHIVE)HiveHandle)->Hive;
  497. if ((HCELL_INDEX)CellHandle == HCELL_NIL) {
  498. if (Hive->BaseBlock->RootCell != HCELL_NIL) {
  499. *ChildCell = (HANDLE)(Hive->BaseBlock->RootCell);
  500. if (ARGUMENT_PRESENT(Disposition)) {
  501. *Disposition = REG_OPENED_EXISTING_KEY;
  502. }
  503. return(STATUS_SUCCESS);
  504. } else {
  505. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  506. }
  507. } else {
  508. Parent = (PCM_KEY_NODE)HvGetCell(Hive, (HCELL_INDEX)CellHandle);
  509. Status = CmpFindChildByName(Hive,
  510. (HCELL_INDEX)CellHandle,
  511. *Name,
  512. KeyBodyNode,
  513. (PHCELL_INDEX)ChildCell,
  514. &Index);
  515. }
  516. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  517. NewCell = HvAllocateCell(Hive,
  518. CmpHKeyNodeSize(Hive,Name->Length),
  519. Stable);
  520. if (NewCell != HCELL_NIL) {
  521. *ChildCell = (HANDLE)NewCell;
  522. Child = (PCM_KEY_NODE)HvGetCell(Hive, NewCell);
  523. Child->Signature = CM_KEY_NODE_SIGNATURE;
  524. Child->Flags = 0;
  525. KeQuerySystemTime(&(Child->LastWriteTime));
  526. Child->Spare = 0;
  527. Child->Parent = (HCELL_INDEX)CellHandle;
  528. Child->ValueList.Count = 0;
  529. Child->ValueList.List = HCELL_NIL;
  530. Child->u1.s1.Security = HCELL_NIL;
  531. Child->u1.s1.Class = HCELL_NIL;
  532. Child->NameLength = Name->Length;
  533. Child->ClassLength = 0;
  534. Child->SubKeyCounts[Stable] = 0;
  535. Child->SubKeyCounts[Volatile] = 0;
  536. Child->SubKeyLists[Stable] = HCELL_NIL;
  537. Child->SubKeyLists[Volatile] = HCELL_NIL;
  538. Child->MaxValueDataLen = 0;
  539. Child->MaxNameLen = 0;
  540. Child->MaxValueNameLen = 0;
  541. Child->MaxClassLen = 0;
  542. if((HCELL_INDEX)CellHandle == HCELL_NIL) {
  543. Hive->BaseBlock->RootCell = NewCell;
  544. Status = EhpAttachSecurity(Hive, NewCell);
  545. } else {
  546. Child->u1.s1.Security = Parent->u1.s1.Security;
  547. Security = (PCM_KEY_SECURITY)HvGetCell(Hive, Child->u1.s1.Security);
  548. ++Security->ReferenceCount;
  549. }
  550. RtlMoveMemory(
  551. &(Child->Name[0]),
  552. Name->Buffer,
  553. Name->Length
  554. );
  555. Status = STATUS_SUCCESS;
  556. } else {
  557. Status = STATUS_INSUFFICIENT_RESOURCES;
  558. return(Status);
  559. }
  560. if (ARGUMENT_PRESENT(Disposition)) {
  561. *Disposition = REG_CREATED_NEW_KEY;
  562. }
  563. if ((HCELL_INDEX)CellHandle != HCELL_NIL) {
  564. //
  565. // put newly created child into parent's sub key list
  566. //
  567. if (! CmpAddSubKey(Hive, (HCELL_INDEX)CellHandle, NewCell)) {
  568. CmpFreeKeyByCell(Hive, NewCell, FALSE);
  569. return STATUS_INSUFFICIENT_RESOURCES;
  570. }
  571. Parent = (PCM_KEY_NODE)HvGetCell(Hive, (HCELL_INDEX)CellHandle);
  572. if (Parent->MaxNameLen < Name->Length) {
  573. Parent->MaxNameLen = Name->Length;
  574. }
  575. Parent->MaxClassLen = 0;
  576. }
  577. } else {
  578. Status = STATUS_SUCCESS;
  579. if (ARGUMENT_PRESENT(Disposition)) {
  580. *Disposition = REG_OPENED_EXISTING_KEY;
  581. }
  582. }
  583. return(Status);
  584. }
  585. NTSTATUS
  586. EhQueryKey(
  587. IN HANDLE HiveHandle,
  588. IN HANDLE KeyHandle,
  589. IN KEY_INFORMATION_CLASS KeyInformationClass,
  590. IN PVOID KeyInformation,
  591. IN ULONG Length,
  592. IN PULONG ResultLength
  593. )
  594. /*++
  595. Routine Description:
  596. Data about the class of a key, and the numbers and sizes of its
  597. children and value entries may be queried with CmQueryKey.
  598. NOTE: The returned lengths are guaranteed to be at least as
  599. long as the described values, but may be longer in
  600. some circumstances.
  601. Arguments:
  602. Hive - supplies a handle to the hive control structure for the hive
  603. Cell - supplies handle of node to whose sub keys are to be found
  604. KeyInformationClass - Specifies the type of information
  605. returned in Buffer. One of the following types:
  606. KeyBasicInformation - return last write time, title index, and name.
  607. (See KEY_BASIC_INFORMATION)
  608. KeyNodeInformation - return last write time, title index, name, class.
  609. (See KEY_NODE_INFORMATION)
  610. KeyFullInformation - return all data except for name and security.
  611. (See KEY_FULL_INFORMATION)
  612. KeyInformation -Supplies pointer to buffer to receive the data.
  613. Length - Length of KeyInformation in bytes.
  614. ResultLength - Number of bytes actually written into KeyInformation.
  615. Return Value:
  616. NTSTATUS - Result code from call, among the following:
  617. <TBS>
  618. --*/
  619. {
  620. CM_KEY_CONTROL_BLOCK Kcb;
  621. Kcb.Delete = FALSE;
  622. Kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  623. Kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
  624. Kcb.KeyCell = (HCELL_INDEX)KeyHandle;
  625. Kcb.FullName.Length = 0;
  626. Kcb.FullName.MaximumLength = 0;
  627. Kcb.FullName.Buffer = NULL;
  628. return(CmQueryKey(&Kcb,
  629. KeyInformationClass,
  630. KeyInformation,
  631. Length,
  632. ResultLength));
  633. }
  634. PSECURITY_DESCRIPTOR
  635. EhGetKeySecurity(
  636. IN HANDLE HiveHandle,
  637. IN HANDLE KeyHandle
  638. )
  639. {
  640. PCM_KEY_SECURITY Security;
  641. CmpGetObjectSecurity((HCELL_INDEX)KeyHandle,
  642. &((PCMHIVE)HiveHandle)->Hive,
  643. &Security,
  644. NULL);
  645. return(&Security->Descriptor);
  646. }
  647. NTSTATUS
  648. EhQueryValueKey(
  649. IN HANDLE HiveHandle,
  650. IN HANDLE KeyHandle,
  651. IN PUNICODE_STRING ValueName,
  652. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  653. IN PVOID KeyValueInformation,
  654. IN ULONG Length,
  655. IN PULONG ResultLength
  656. )
  657. /*++
  658. Routine Description:
  659. The ValueName, TitleIndex, Type, and Data for any one of a key's
  660. value entries may be queried with CmQueryValueKey.
  661. If KeyValueInformation is not long enough to hold all requested data,
  662. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  663. set to the number of bytes actually required.
  664. Arguments:
  665. Hive - supplies a pointer to the hive control structure for the hive
  666. Cell - supplies index of node to whose sub keys are to be found
  667. ValueName - The name of the value entry to return data for.
  668. KeyValueInformationClass - Specifies the type of information
  669. returned in KeyValueInformation. One of the following types:
  670. KeyValueBasicInformation - return time of last write, title
  671. index, and name. (See KEY_VALUE_BASIC_INFORMATION)
  672. KeyValueFullInformation - return time of last write, title
  673. index, name, class. (See KEY_VALUE_FULL_INFORMATION)
  674. KeyValueInformation -Supplies pointer to buffer to receive the data.
  675. Length - Length of KeyValueInformation in bytes.
  676. ResultLength - Number of bytes actually written into KeyValueInformation.
  677. Return Value:
  678. NTSTATUS - Result code from call, among the following:
  679. <TBS>
  680. --*/
  681. {
  682. CM_KEY_CONTROL_BLOCK kcb;
  683. kcb.Delete = FALSE;
  684. kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  685. kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
  686. kcb.KeyCell = (HCELL_INDEX)KeyHandle;
  687. kcb.FullName.Length = 0;
  688. kcb.FullName.MaximumLength = 0;
  689. kcb.FullName.Buffer = NULL;
  690. return(CmQueryValueKey(&kcb,
  691. *ValueName,
  692. KeyValueInformationClass,
  693. KeyValueInformation,
  694. Length,
  695. ResultLength));
  696. }
  697. NTSTATUS
  698. EhDeleteValueKey(
  699. IN HANDLE HiveHandle,
  700. IN HANDLE CellHandle,
  701. IN PUNICODE_STRING ValueName // RAW
  702. )
  703. /*++
  704. Routine Description:
  705. One of the value entries of a registry key may be removed with this call.
  706. The value entry with ValueName matching ValueName is removed from the key.
  707. If no such entry exists, an error is returned.
  708. Arguments:
  709. Hive - Supplies a handle to the hive control structure
  710. Cell - Supplies a handle to the registry key to be operated on
  711. ValueName - The name of the value to be deleted. NULL is a legal name.
  712. Return Value:
  713. NTSTATUS - Result code from call, among the following:
  714. <TBS>
  715. --*/
  716. {
  717. CM_KEY_CONTROL_BLOCK kcb;
  718. kcb.Delete = FALSE;
  719. kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
  720. kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
  721. kcb.KeyCell = (HCELL_INDEX)CellHandle;
  722. kcb.FullName.Length = 0;
  723. kcb.FullName.MaximumLength = 0;
  724. kcb.FullName.Buffer = NULL;
  725. return(CmDeleteValueKey(&kcb, *ValueName));
  726. }
  727. NTSTATUS
  728. EhpAttachSecurity(
  729. IN PHHIVE Hive,
  730. IN HCELL_INDEX Cell
  731. )
  732. /*++
  733. Routine Description:
  734. Creates a security descriptor cell and attaches it to the given
  735. node.
  736. Arguments:
  737. Hive - Supplies a pointer to the hive control structure.
  738. Cell - Supplies the cell index of the node to attach the security
  739. descriptor to.
  740. Return Value:
  741. None.
  742. --*/
  743. {
  744. NTSTATUS Status;
  745. HANDLE Token;
  746. HCELL_INDEX SecurityCell;
  747. PCM_KEY_NODE Node;
  748. PCM_KEY_SECURITY Security;
  749. PSECURITY_DESCRIPTOR Descriptor;
  750. ULONG DescriptorLength;
  751. HANDLE Handle;
  752. Status = NtOpenProcessToken( NtCurrentProcess(),
  753. TOKEN_QUERY,
  754. &Token );
  755. if (!NT_SUCCESS(Status)) {
  756. return(Status);
  757. }
  758. Status = RtlNewSecurityObject( NULL,
  759. NULL,
  760. &Descriptor,
  761. FALSE,
  762. Token,
  763. &CmpKeyMapping );
  764. if (!NT_SUCCESS(Status)) {
  765. return(Status);
  766. }
  767. Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
  768. SecurityCell = HvAllocateCell(Hive,
  769. SECURITY_CELL_LENGTH(Descriptor),
  770. Stable);
  771. if (SecurityCell == HCELL_NIL) {
  772. return STATUS_INSUFFICIENT_RESOURCES;
  773. }
  774. Node->u1.s1.Security = SecurityCell;
  775. Security = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell);
  776. DescriptorLength = RtlLengthSecurityDescriptor(Descriptor);
  777. Security->Signature = CM_KEY_SECURITY_SIGNATURE;
  778. Security->ReferenceCount = 1;
  779. Security->DescriptorLength = DescriptorLength;
  780. RtlMoveMemory( &Security->Descriptor,
  781. Descriptor,
  782. DescriptorLength );
  783. Security->Flink = Security->Blink = SecurityCell;
  784. return(STATUS_SUCCESS);
  785. }
  786.