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.

1791 lines
50 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. regredir.c
  5. Abstract:
  6. This module contains the APis to redirect 32bit registry calls. All 32bit wow process must
  7. use following set of wowregistry APIs to manipulate registry so that 32-bit and 64-bit registry
  8. can co exist in the same system registry.
  9. Some functionality hasn't been optimized yet. After successful implementation those need to
  10. be optimized.
  11. Author:
  12. ATM Shafiqul Khalid (askhalid) 15-Oct-1999
  13. Revision History:
  14. --*/
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <ntregapi.h>
  21. #include <stdlib.h>
  22. #include "regremap.h"
  23. #include "wow64reg.h"
  24. #include "wow64reg\reflectr.h"
  25. //#include "wow64.h"
  26. PVOID
  27. Wow64AllocateTemp(
  28. SIZE_T Size
  29. );
  30. #ifdef WOW64_LOG_REGISTRY
  31. WCHAR TempBuff[MAX_PATH];
  32. DWORD TempLen = MAX_PATH;
  33. NTSTATUS //should move to the regremap.h header
  34. ObjectAttributesToKeyName (
  35. POBJECT_ATTRIBUTES ObjectAttributes,
  36. PWCHAR AbsPath,
  37. BOOL *bPatched,
  38. DWORD *ParentLen
  39. );
  40. #endif
  41. #ifdef LOG_REGISTRY
  42. void
  43. LogMsgKeyHandle (
  44. char *str,
  45. HANDLE hKey,
  46. DWORD res
  47. )
  48. {
  49. WCHAR AbsPath[MAX_PATH];
  50. DWORD Len = MAX_PATH;
  51. HandleToKeyName (hKey, AbsPath, &Len);
  52. LOGPRINT( (ERRORLOG, "\nDEBUG: requested Node:%S Status:%x, Msg:%s", AbsPath, res, str));
  53. };
  54. #endif
  55. //
  56. // Need to move in the header file
  57. //
  58. NTSTATUS
  59. RemapNtCreateKey(
  60. OUT PHANDLE phPatchedHandle,
  61. IN ACCESS_MASK DesiredAccess,
  62. IN POBJECT_ATTRIBUTES ObjectAttributes,
  63. IN ULONG TitleIndex,
  64. IN PUNICODE_STRING Class OPTIONAL,
  65. IN ULONG CreateOptions,
  66. OUT PULONG Disposition OPTIONAL
  67. );
  68. NTSTATUS
  69. Wow64NtCreateKey(
  70. OUT PHANDLE KeyHandle,
  71. IN ACCESS_MASK DesiredAccess,
  72. IN POBJECT_ATTRIBUTES ObjectAttributes,
  73. IN ULONG TitleIndex,
  74. IN PUNICODE_STRING Class OPTIONAL,
  75. IN ULONG CreateOptions,
  76. OUT PULONG Disposition OPTIONAL
  77. )
  78. /*++
  79. Routine Description:
  80. An existing registry key may be opened, or a new one created,
  81. with NtCreateKey.
  82. If the specified key does not exist, an attempt is made to create it.
  83. For the create attempt to succeed, the new node must be a direct
  84. child of the node referred to by KeyHandle. If the node exists,
  85. it is opened. Its value is not affected in any way.
  86. Share access is computed from desired access.
  87. NOTE:
  88. If CreateOptions has REG_OPTION_BACKUP_RESTORE set, then
  89. DesiredAccess will be ignored. If the caller has the
  90. privilege SeBackupPrivilege asserted, a handle with
  91. KEY_READ | ACCESS_SYSTEM_SECURITY will be returned.
  92. If SeRestorePrivilege, then same but KEY_WRITE rather
  93. than KEY_READ. If both, then both access sets. If neither
  94. privilege is asserted, then the call will fail.
  95. Arguments:
  96. KeyHandle - Receives a Handle which is used to access the
  97. specified key in the Registration Database.
  98. DesiredAccess - Specifies the access rights desired.
  99. ObjectAttributes - Specifies the attributes of the key being opened.
  100. Note that a key name must be specified. If a Root Directory is
  101. specified, the name is relative to the root. The name of the
  102. object must be within the name space allocated to the Registry,
  103. that is, all names beginning "\Registry". RootHandle, if
  104. present, must be a handle to "\", or "\Registry", or a key
  105. under "\Registry".
  106. RootHandle must have been opened for KEY_CREATE_SUB_KEY access
  107. if a new node is to be created.
  108. NOTE: Object manager will capture and probe this argument.
  109. TitleIndex - Specifies the index of the localized alias for
  110. the name of the key. The title index specifies the index of
  111. the localized alias for the name. Ignored if the key
  112. already exists.
  113. Class - Specifies the object class of the key. (To the registry
  114. this is just a string.) Ignored if NULL.
  115. CreateOptions - Optional control values:
  116. REG_OPTION_VOLATILE - Object is not to be stored across boots.
  117. Disposition - This optional parameter is a pointer to a variable
  118. that will receive a value indicating whether a new Registry
  119. key was created or an existing one opened:
  120. REG_CREATED_NEW_KEY - A new Registry Key was created
  121. REG_OPENED_EXISTING_KEY - An existing Registry Key was opened
  122. Return Value:
  123. NTSTATUS - Result code from call, among the following:
  124. <TBS>
  125. --*/
  126. {
  127. NTSTATUS St;
  128. BOOL bRet = FALSE;
  129. ULONG Disposition_Temp;
  130. try {
  131. if ( Disposition == NULL )
  132. Disposition = &Disposition_Temp;
  133. St = RemapNtCreateKey (
  134. KeyHandle,
  135. DesiredAccess,
  136. ObjectAttributes,
  137. TitleIndex,
  138. Class ,
  139. CreateOptions,
  140. Disposition
  141. );
  142. if (!NT_SUCCESS(St))
  143. bRet = TRUE;
  144. if (!bRet)
  145. if ( *KeyHandle != NULL)
  146. bRet = TRUE;
  147. //
  148. // if total failure for thunked key, try if you can pull that key from 64bit hive.
  149. // May be reflector should be running
  150. //
  151. if (!bRet ) {
  152. //
  153. // 2nd try only if no patch is required.
  154. // i.e., success with NULL handle returned
  155. //
  156. St = NtCreateKey(
  157. KeyHandle,
  158. (~KEY_WOW64_RES) & DesiredAccess,
  159. ObjectAttributes,
  160. TitleIndex,
  161. Class ,
  162. CreateOptions,
  163. Disposition
  164. );
  165. }
  166. #ifdef WOW64_LOG_REGISTRY
  167. TempLen = MAX_PATH;
  168. ObjectAttributesToKeyName (
  169. ObjectAttributes,
  170. TempBuff,
  171. &bRet,
  172. NULL);
  173. Wow64RegDbgPrint (( "\nNtCreateKeyEx IN:[%S]", TempBuff));
  174. HandleToKeyName (*KeyHandle, TempBuff, &TempLen);
  175. Wow64RegDbgPrint (( "\nNtCreateKeyEx OUT:[%S] Status:%x F:%x", TempBuff, DesiredAccess));
  176. #endif
  177. if (NT_SUCCESS(St))
  178. Wow64RegSetKeyDirty (*KeyHandle ); // Need some clean/sync up on exit
  179. if ( *Disposition == REG_CREATED_NEW_KEY )
  180. UpdateKeyTag ( *KeyHandle,TAG_KEY_ATTRIBUTE_32BIT_WRITE );
  181. } except( NULL, EXCEPTION_EXECUTE_HANDLER){
  182. St = GetExceptionCode ();
  183. }
  184. return St;
  185. }
  186. NTSTATUS
  187. Wow64NtDeleteKey(
  188. IN HANDLE KeyHandle
  189. )
  190. /*++
  191. Routine Description:
  192. A registry key may be marked for delete, causing it to be removed
  193. from the system. It will remain in the name space until the last
  194. handle to it is closed.
  195. Arguments:
  196. KeyHandle - Specifies the handle of the Key to delete, must have
  197. been opened for DELETE access.
  198. Return Value:
  199. NTSTATUS - Result code from call, among the following:
  200. <TBS>
  201. --*/
  202. {
  203. NTSTATUS St;
  204. HKEY hRemap = Wow64OpenRemappedKeyOnReflection (KeyHandle);
  205. St = NtDeleteKey(
  206. KeyHandle
  207. );
  208. if (NT_SUCCESS (St) && ( hRemap != NULL ) )
  209. Wow64RegDeleteKey (hRemap, NULL);
  210. if ( hRemap != NULL )
  211. NtClose ( hRemap );
  212. return St;
  213. }
  214. NTSTATUS
  215. Wow64NtDeleteValueKey(
  216. IN HANDLE KeyHandle,
  217. IN PUNICODE_STRING ValueName
  218. )
  219. /*++
  220. Routine Description:
  221. One of the value entries of a registry key may be removed with this
  222. call. To remove the entire key, call NtDeleteKey.
  223. The value entry with ValueName matching ValueName is removed from the key.
  224. If no such entry exists, an error is returned.
  225. Arguments:
  226. KeyHandle - Specifies the handle of the key containing the value
  227. entry of interest. Must have been opend for KEY_SET_VALUE access.
  228. ValueName - The name of the value to be deleted. NULL is a legal name.
  229. Return Value:
  230. NTSTATUS - Result code from call, among the following:
  231. <TBS>
  232. --*/
  233. {
  234. NTSTATUS St;
  235. St = NtDeleteValueKey(
  236. KeyHandle,
  237. ValueName
  238. );
  239. if (NT_SUCCESS(St))
  240. Wow64RegSetKeyDirty (KeyHandle ); // Need some clean/sync up on exit
  241. return St;
  242. }
  243. NTSTATUS
  244. Wow64NtEnumerateKey(
  245. IN HANDLE KeyHandle,
  246. IN ULONG Index,
  247. IN KEY_INFORMATION_CLASS KeyInformationClass,
  248. IN PVOID KeyInformation,
  249. IN ULONG Length,
  250. IN PULONG ResultLength
  251. )
  252. /*++
  253. Routine Description:
  254. The sub keys of an open key may be enumerated with NtEnumerateKey.
  255. NtEnumerateKey returns the name of the Index'th sub key of the open
  256. key specified by KeyHandle. The value STATUS_NO_MORE_ENTRIES will be
  257. returned if value of Index is larger than the number of sub keys.
  258. Note that Index is simply a way to select among child keys. Two calls
  259. to NtEnumerateKey with the same Index are NOT guaranteed to return
  260. the same results.
  261. If KeyInformation is not long enough to hold all requested data,
  262. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  263. set to the number of bytes actually required.
  264. Arguments:
  265. KeyHandle - Handle of the key whose sub keys are to be enumerated. Must
  266. be open for KEY_ENUMERATE_SUB_KEY access.
  267. Index - Specifies the (0-based) number of the sub key to be returned.
  268. KeyInformationClass - Specifies the type of information returned in
  269. Buffer. One of the following types:
  270. KeyBasicInformation - return last write time, title index, and name.
  271. (see KEY_BASIC_INFORMATION structure)
  272. KeyNodeInformation - return last write time, title index, name, class.
  273. (see KEY_NODE_INFORMATION structure)
  274. KeyInformation -Supplies pointer to buffer to receive the data.
  275. Length - Length of KeyInformation in bytes.
  276. ResultLength - Number of bytes actually written into KeyInformation.
  277. Return Value:
  278. NTSTATUS - Result code from call, among the following:
  279. <TBS>
  280. --*/
  281. {
  282. //
  283. // if the handle is to ISN node then time to enumerate the right one
  284. //
  285. BOOL bRealigned=FALSE;
  286. PVOID pTempKeyInfo;
  287. NTSTATUS RetVal;
  288. try {
  289. if ( (SIZE_T)(KeyInformation) & (0x07) ) {
  290. // allocate a buffer with correct alignment, to pass to the Win64 API
  291. pTempKeyInfo = KeyInformation;
  292. KeyInformation = Wow64AllocateTemp(Length);
  293. RtlCopyMemory(KeyInformation, pTempKeyInfo, Length);
  294. bRealigned = TRUE;
  295. }
  296. RetVal = NtEnumerateKey(
  297. KeyHandle,
  298. Index,
  299. KeyInformationClass,
  300. KeyInformation,
  301. Length,
  302. ResultLength
  303. );
  304. if (!NT_ERROR(RetVal) && bRealigned) {
  305. RtlCopyMemory((PVOID)pTempKeyInfo, KeyInformation, Length);
  306. }
  307. } except( NULL, EXCEPTION_EXECUTE_HANDLER){
  308. RetVal = GetExceptionCode ();
  309. }
  310. return RetVal;
  311. }
  312. NTSTATUS
  313. Wow64NtEnumerateValueKey(
  314. IN HANDLE KeyHandle,
  315. IN ULONG Index,
  316. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  317. IN PVOID KeyValueInformation,
  318. IN ULONG Length,
  319. IN PULONG ResultLength
  320. )
  321. /*++
  322. Routine Description:
  323. The value entries of an open key may be enumerated
  324. with NtEnumerateValueKey.
  325. NtEnumerateValueKey returns the name of the Index'th value
  326. entry of the open key specified by KeyHandle. The value
  327. STATUS_NO_MORE_ENTRIES will be returned if value of Index is
  328. larger than the number of sub keys.
  329. Note that Index is simply a way to select among value
  330. entries. Two calls to NtEnumerateValueKey with the same Index
  331. are NOT guaranteed to return the same results.
  332. If KeyValueInformation is not long enough to hold all requested data,
  333. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  334. set to the number of bytes actually required.
  335. Arguments:
  336. KeyHandle - Handle of the key whose value entries are to be enumerated.
  337. Must have been opened with KEY_QUERY_VALUE access.
  338. Index - Specifies the (0-based) number of the sub key to be returned.
  339. KeyValueInformationClass - Specifies the type of information returned
  340. in Buffer. One of the following types:
  341. KeyValueBasicInformation - return time of last write,
  342. title index, and name. (See KEY_VALUE_BASIC_INFORMATION)
  343. KeyValueFullInformation - return time of last write,
  344. title index, name, class. (See KEY_VALUE_FULL_INFORMATION)
  345. KeyValueInformation -Supplies pointer to buffer to receive the data.
  346. Length - Length of KeyValueInformation in bytes.
  347. ResultLength - Number of bytes actually written into KeyValueInformation.
  348. Return Value:
  349. NTSTATUS - Result code from call, among the following:
  350. <TBS>
  351. --*/
  352. {
  353. return NtEnumerateValueKey(
  354. KeyHandle,
  355. Index,
  356. KeyValueInformationClass,
  357. KeyValueInformation,
  358. Length,
  359. ResultLength
  360. );
  361. }
  362. NTSTATUS
  363. Wow64NtFlushKey(
  364. IN HANDLE KeyHandle
  365. )
  366. /*++
  367. Routine Description:
  368. Changes made by NtCreateKey or NtSetKey may be flushed to disk with
  369. NtFlushKey.
  370. NtFlushKey will not return to its caller until any changed data
  371. associated with KeyHandle has been written to permanent store.
  372. WARNING: NtFlushKey will flush the entire registry tree, and thus will
  373. burn cycles and I/O.
  374. Arguments:
  375. KeyHandle - Handle of open key to be flushed.
  376. Return Value:
  377. NTSTATUS - Result code from call, among the following:
  378. <TBS>
  379. --*/
  380. {
  381. return NtFlushKey(
  382. KeyHandle
  383. );
  384. }
  385. NTSTATUS
  386. Wow64NtInitializeRegistry(
  387. IN USHORT BootCondition
  388. )
  389. /*++
  390. Routine Description:
  391. This routine is called in 2 situations:
  392. 1) It is called from SM after autocheck (chkdsk) has
  393. run and the paging files have been opened. It's function is
  394. to bind in memory hives to their files, and to open any other
  395. files yet to be used.
  396. 2) It is called from SC after the current boot has been accepted
  397. and the control set used for the boot process should be saved
  398. as the LKG control set.
  399. After this routine accomplishes the work of situation #1 and
  400. #2, further requests for such work will not be carried out.
  401. Arguments:
  402. BootCondition -
  403. REG_INIT_BOOT_SM - The routine has been called from SM
  404. in situation #1.
  405. REG_INIT_BOOT_SETUP - The routine has been called to perform
  406. situation #1 work but has been called
  407. from setup and needs to do some special
  408. work.
  409. REG_INIT_BOOT_ACCEPTED_BASE + Num
  410. (where 0 < Num < 1000) - The routine has been called
  411. in situation #2. "Num" is the
  412. number of the control set
  413. to which the boot control set
  414. should be saved.
  415. Return Value:
  416. NTSTATUS - Result code from call, among the following:
  417. STATUS_SUCCESS - it worked
  418. STATUS_ACCESS_DENIED - the routine has already done the work
  419. requested and will not do it again.
  420. --*/
  421. {
  422. return NtInitializeRegistry(
  423. BootCondition
  424. );
  425. }
  426. NTSTATUS
  427. Wow64NtNotifyChangeKey(
  428. IN HANDLE KeyHandle,
  429. IN HANDLE Event OPTIONAL,
  430. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  431. IN PVOID ApcContext OPTIONAL,
  432. OUT PIO_STATUS_BLOCK IoStatusBlock,
  433. IN ULONG CompletionFilter,
  434. IN BOOLEAN WatchTree,
  435. OUT PVOID Buffer,
  436. IN ULONG BufferSize,
  437. IN BOOLEAN Asynchronous
  438. )
  439. /*++
  440. Routine Description:
  441. Notification of key creation, deletion, and modification may be
  442. obtained by calling NtNotifyChangeKey.
  443. NtNotifyChangeKey monitors changes to a key - if the key or
  444. subtree specified by KeyHandle are modified, the service notifies
  445. its caller. It also returns the name(s) of the key(s) that changed.
  446. All names are specified relative to the key that the handle represents
  447. (therefore a NULL name represents that key). The service completes
  448. once the key or subtree has been modified based on the supplied
  449. CompletionFilter. The service is a "single shot" and therefore
  450. needs to be reinvoked to watch the key for further changes.
  451. The operation of this service begins by opening a key for KEY_NOTIFY
  452. access. Once the handle is returned, the NtNotifyChangeKey service
  453. may be invoked to begin watching the values and subkeys of the
  454. specified key for changes. The first time the service is invoked,
  455. the BufferSize parameter supplies not only the size of the user's
  456. Buffer, but also the size of the buffer that will be used by the
  457. Registry to store names of keys that have changed. Likewise, the
  458. CompletionFilter and WatchTree parameters on the first call indicate
  459. how notification should operate for all calls using the supplied
  460. KeyHandle. These two parameters are ignored on subsequent calls
  461. to the API with the same instance of KeyHandle.
  462. Once a modification is made that should be reported, the Registry will
  463. complete the service. The names of the files that have changed since
  464. the last time the service was called will be placed into the caller's
  465. output Buffer. The Information field of IoStatusBlock will contain
  466. the number of bytes placed in Buffer, or zero if too many keys have
  467. changed since the last time the service was called, in which case
  468. the application must Query and Enumerate the key and sub keys to
  469. discover changes. The Status field of IoStatusBlock will contain
  470. the actual status of the call.
  471. If Asynchronous is TRUE, then Event, if specified, will be set to
  472. the Signaled state. If no Event parameter was specified, then
  473. KeyHandle will be set to the Signaled state. If an ApcRoutine
  474. was specified, it is invoked with the ApcContext and the address of the
  475. IoStatusBlock as its arguments. If Asynchronous is FALSE, Event,
  476. ApcRoutine, and ApcContext are ignored.
  477. This service requires KEY_NOTIFY access to the key that was
  478. actually modified
  479. The notify "session" is terminated by closing KeyHandle.
  480. Arguments:
  481. KeyHandle-- Supplies a handle to an open key. This handle is
  482. effectively the notify handle, because only one set of
  483. notify parameters may be set against it.
  484. Event - An optional handle to an event to be set to the
  485. Signaled state when the operation completes.
  486. ApcRoutine - An optional procedure to be invoked once the
  487. operation completes. For more information about this
  488. parameter see the NtReadFile system service description.
  489. If PreviousMode == Kernel, this parameter is an optional
  490. pointer to a WORK_QUEUE_ITEM to be queued when the notify
  491. is signaled.
  492. ApcContext - A pointer to pass as an argument to the ApcRoutine,
  493. if one was specified, when the operation completes. This
  494. argument is required if an ApcRoutine was specified.
  495. If PreviousMode == Kernel, this parameter is an optional
  496. WORK_QUEUE_TYPE describing the queue to be used. This argument
  497. is required if an ApcRoutine was specified.
  498. IoStatusBlock - A variable to receive the final completion status.
  499. For more information about this parameter see the NtCreateFile
  500. system service description.
  501. CompletionFilter -- Specifies a set of flags that indicate the
  502. types of operations on the key or its value that cause the
  503. call to complete. The following are valid flags for this parameter:
  504. REG_NOTIFY_CHANGE_NAME -- Specifies that the call should be
  505. completed if a subkey is added or deleted.
  506. REG_NOTIFY_CHANGE_ATTRIBUTES -- Specifies that the call should
  507. be completed if the attributes (e.g.: ACL) of the key or
  508. any subkey are changed.
  509. REG_NOTIFY_CHANGE_LAST_SET -- Specifies that the call should be
  510. completed if the lastWriteTime of the key or any of its
  511. subkeys is changed. (Ie. if the value of the key or any
  512. subkey is changed).
  513. REG_NOTIFY_CHANGE_SECURITY -- Specifies that the call should be
  514. completed if the security information (e.g. ACL) on the key
  515. or any subkey is changed.
  516. WatchTree -- A BOOLEAN value that, if TRUE, specifies that all
  517. changes in the subtree of this key should also be reported.
  518. If FALSE, only changes to this key, its value, and its immediate
  519. subkeys (but not their values nor their subkeys) are reported.
  520. Buffer -- A variable to receive the name(s) of the key(s) that
  521. changed. See REG_NOTIFY_INFORMATION.
  522. BufferSize -- Specifies the length of Buffer.
  523. Asynchronous -- If FALSE, call will not return until
  524. complete (synchronous) if TRUE, call may return STATUS_PENDING.
  525. Obs:
  526. Since NtNotifyChangeMultipleKeys, this routine is kept only for bacwards compatibility
  527. Return Value:
  528. NTSTATUS - Result code from call, among the following:
  529. <TBS>
  530. --*/
  531. {
  532. return NtNotifyChangeKey(
  533. KeyHandle,
  534. Event ,
  535. ApcRoutine ,
  536. ApcContext ,
  537. IoStatusBlock,
  538. CompletionFilter,
  539. WatchTree,
  540. Buffer,
  541. BufferSize,
  542. Asynchronous
  543. );
  544. }
  545. NTSTATUS
  546. Wow64NtNotifyChangeMultipleKeys(
  547. IN HANDLE MasterKeyHandle,
  548. IN ULONG Count,
  549. IN OBJECT_ATTRIBUTES SlaveObjects[],
  550. IN HANDLE Event OPTIONAL,
  551. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  552. IN PVOID ApcContext OPTIONAL,
  553. OUT PIO_STATUS_BLOCK IoStatusBlock,
  554. IN ULONG CompletionFilter,
  555. IN BOOLEAN WatchTree,
  556. OUT PVOID Buffer,
  557. IN ULONG BufferSize,
  558. IN BOOLEAN Asynchronous
  559. )
  560. /*++
  561. Routine Description:
  562. Notificaion of creation, deletion and modification on multiple keys
  563. may be obtained with NtNotifyChangeMultipleKeys.
  564. NtNotifyMultipleKeys monitors changes to any of the MasterKeyHandle
  565. or one of SlaveObjects and/or their subtrees, whichever occurs first.
  566. When an event on these keys is triggered, the notification is considered
  567. fulfilled, and has to be "armed" again, in order to watch for further
  568. changes.
  569. The mechanism is similar to the one described in NtNotifyChangeKey.
  570. The MasterKeyHandle key, give the caller control over the lifetime
  571. of the notification. The notification will live as long as the caller
  572. keeps the MasterKeyHandle open, or an event is triggered.
  573. The caller doesn't have to open the SlaveKeys. He will provide the
  574. routine with an array of OBJECT_ATTRIBUTES, describing the slave objects.
  575. The routine will open the objects, and ensure keep a reference on them
  576. untill the back-end side will close them.
  577. The notify "session" is terminated by closing MasterKeyHandle.
  578. Obs:
  579. For the time being, the routine supports only one slave object. When more
  580. than one slave object is provided, the routine will signal an error of
  581. STATUS_INVALID_PARAMETER.
  582. However, the interface is designed for future enhancements (taking an
  583. array of slave objects), that may be provided with future versions(w2001).
  584. When no slave object is supplied (i.e. Count == 0) we have the identical
  585. behavior as for NtNotifyChangeKey.
  586. Arguments:
  587. MasterKeyHandle - Supplies a handle to an open key. This handle is
  588. the "master handle". It has control overthe lifetime of the
  589. notification.
  590. Count - Number of slave objects. For the time being, this should be 1
  591. SlaveObjects - Array of slave objects. Only the attributes of the
  592. objects are provided, so the caller doesn't have to take care
  593. of them.
  594. Event,ApcRoutine,ApcContext,IoStatusBlock,CompletionFilter,WatchTree,
  595. Buffer,BufferSize,Asynchronous - same as for NtNotifyChangeKey
  596. Return Value:
  597. NTSTATUS - Result code from call, among the following:
  598. <TBS>
  599. --*/
  600. {
  601. return NtNotifyChangeMultipleKeys(
  602. MasterKeyHandle,
  603. Count,
  604. SlaveObjects,
  605. Event,
  606. ApcRoutine,
  607. ApcContext,
  608. IoStatusBlock,
  609. CompletionFilter,
  610. WatchTree,
  611. Buffer,
  612. BufferSize,
  613. Asynchronous
  614. );
  615. }
  616. NTSTATUS
  617. Wow64NtOpenKey(
  618. OUT PHANDLE KeyHandle,
  619. IN ACCESS_MASK DesiredAccess,
  620. IN POBJECT_ATTRIBUTES ObjectAttributes
  621. )
  622. /*++
  623. Routine Description:
  624. A registry key which already exists may be opened with NtOpenKey.
  625. Share access is computed from desired access.
  626. Arguments:
  627. KeyHandle - Receives a Handle which is used to access the
  628. specified key in the Registration Database.
  629. DesiredAccess - Specifies the access rights desired.
  630. ObjectAttributes - Specifies the attributes of the key being opened.
  631. Note that a key name must be specified. If a Root Directory
  632. is specified, the name is relative to the root. The name of
  633. the object must be within the name space allocated to the
  634. Registry, that is, all names beginning "\Registry". RootHandle,
  635. if present, must be a handle to "\", or "\Registry", or a
  636. key under "\Registry". If the specified key does not exist, or
  637. access requested is not allowed, the operation will fail.
  638. NOTE: Object manager will capture and probe this argument.
  639. Return Value:
  640. NTSTATUS - Result code from call, among the following:
  641. <TBS>
  642. --*/
  643. {
  644. NTSTATUS St;
  645. BOOL bRet = FALSE;
  646. try {
  647. St = OpenIsnNodeByObjectAttributes (
  648. ObjectAttributes,
  649. DesiredAccess,
  650. KeyHandle );
  651. if (!NT_SUCCESS(St))
  652. bRet = TRUE;
  653. if ( !bRet )
  654. if ( *KeyHandle != NULL)
  655. bRet = TRUE;
  656. if ( !bRet ) {
  657. St = NtOpenKey(
  658. KeyHandle,
  659. (~KEY_WOW64_RES) & DesiredAccess,
  660. ObjectAttributes
  661. );
  662. }
  663. #ifdef WOW64_LOG_REGISTRY
  664. TempLen = MAX_PATH;
  665. ObjectAttributesToKeyName (
  666. ObjectAttributes,
  667. TempBuff,
  668. &bRet,
  669. NULL
  670. );
  671. Wow64RegDbgPrint (( "\nNtOpenKeyEx IN:[%S]", TempBuff));
  672. HandleToKeyName (*KeyHandle, TempBuff, &TempLen);
  673. Wow64RegDbgPrint (( "\nNtOpenKeyEx OUT:[%S] Status:%x F:%x", TempBuff, St, DesiredAccess));
  674. #endif
  675. } except( NULL, EXCEPTION_EXECUTE_HANDLER){
  676. St = GetExceptionCode ();
  677. }
  678. return St;
  679. }
  680. NTSTATUS
  681. Wow64NtQueryKey(
  682. IN HANDLE KeyHandle,
  683. IN KEY_INFORMATION_CLASS KeyInformationClass,
  684. IN PVOID KeyInformation,
  685. IN ULONG Length,
  686. IN PULONG ResultLength
  687. )
  688. /*++
  689. Routine Description:
  690. Data about the class of a key, and the numbers and sizes of its
  691. children and value entries may be queried with NtQueryKey.
  692. If KeyValueInformation is not long enough to hold all requested data,
  693. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  694. set to the number of bytes actually required.
  695. NOTE: The returned lengths are guaranteed to be at least as
  696. long as the described values, but may be longer in
  697. some circumstances.
  698. Arguments:
  699. KeyHandle - Handle of the key to query data for. Must have been
  700. opened for KEY_QUERY_KEY access.
  701. KeyInformationClass - Specifies the type of information
  702. returned in Buffer. One of the following types:
  703. KeyBasicInformation - return last write time, title index, and name.
  704. (See KEY_BASIC_INFORMATION)
  705. KeyNodeInformation - return last write time, title index, name, class.
  706. (See KEY_NODE_INFORMATION)
  707. KeyFullInformation - return all data except for name and security.
  708. (See KEY_FULL_INFORMATION)
  709. KeyInformation -Supplies pointer to buffer to receive the data.
  710. Length - Length of KeyInformation in bytes.
  711. ResultLength - Number of bytes actually written into KeyInformation.
  712. Return Value:
  713. NTSTATUS - Result code from call, among the following:
  714. <TBS>
  715. --*/
  716. {
  717. BOOL bRealigned=FALSE;
  718. PVOID pTempKeyInfo;
  719. NTSTATUS RetVal;
  720. try {
  721. if ( (SIZE_T)(KeyInformation) & (0x07) ) {
  722. // allocate a buffer with correct alignment, to pass to the Win64 API
  723. pTempKeyInfo = KeyInformation;
  724. KeyInformation = Wow64AllocateTemp(Length);
  725. RtlCopyMemory(KeyInformation, pTempKeyInfo, Length);
  726. bRealigned = TRUE;
  727. }
  728. RetVal = NtQueryKey(
  729. KeyHandle,
  730. KeyInformationClass,
  731. KeyInformation,
  732. Length,
  733. ResultLength
  734. );
  735. if (!NT_ERROR(RetVal) && bRealigned) {
  736. RtlCopyMemory((PVOID)pTempKeyInfo, KeyInformation, Length);
  737. }
  738. } except( NULL, EXCEPTION_EXECUTE_HANDLER){
  739. RetVal = GetExceptionCode ();
  740. }
  741. return RetVal;
  742. }
  743. NTSTATUS
  744. Wow64NtQueryValueKey(
  745. IN HANDLE KeyHandle,
  746. IN PUNICODE_STRING ValueName,
  747. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  748. IN PVOID KeyValueInformation,
  749. IN ULONG Length,
  750. IN PULONG ResultLength
  751. )
  752. /*++
  753. Routine Description:
  754. The ValueName, TitleIndex, Type, and Data for any one of a key's
  755. value entries may be queried with NtQueryValueKey.
  756. If KeyValueInformation is not long enough to hold all requested data,
  757. STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
  758. set to the number of bytes actually required.
  759. Arguments:
  760. KeyHandle - Handle of the key whose value entries are to be
  761. enumerated. Must be open for KEY_QUERY_VALUE access.
  762. Index - Specifies the (0-based) number of the sub key to be returned.
  763. ValueName - The name of the value entry to return data for.
  764. KeyValueInformationClass - Specifies the type of information
  765. returned in KeyValueInformation. One of the following types:
  766. KeyValueBasicInformation - return time of last write, title
  767. index, and name. (See KEY_VALUE_BASIC_INFORMATION)
  768. KeyValueFullInformation - return time of last write, title
  769. index, name, class. (See KEY_VALUE_FULL_INFORMATION)
  770. KeyValueInformation -Supplies pointer to buffer to receive the data.
  771. Length - Length of KeyValueInformation in bytes.
  772. ResultLength - Number of bytes actually written into KeyValueInformation.
  773. Return Value:
  774. NTSTATUS - Result code from call, among the following:
  775. <TBS>
  776. TMP: The IopQueryRegsitryValues() routine in the IO system assumes
  777. STATUS_OBJECT_NAME_NOT_FOUND is returned if the value being queried
  778. for does not exist.
  779. --*/
  780. {
  781. BOOL bRealigned=FALSE;
  782. PVOID pTempKeyInfo;
  783. NTSTATUS RetVal;
  784. try {
  785. if ( (SIZE_T)(KeyValueInformation) & (0x07) ) {
  786. // allocate a buffer with correct alignment, to pass to the Win64 API
  787. pTempKeyInfo = KeyValueInformation;
  788. KeyValueInformation = Wow64AllocateTemp(Length);
  789. RtlCopyMemory(KeyValueInformation, pTempKeyInfo, Length);
  790. bRealigned = TRUE;
  791. }
  792. RetVal = NtQueryValueKey(
  793. KeyHandle,
  794. ValueName,
  795. KeyValueInformationClass,
  796. KeyValueInformation,
  797. Length,
  798. ResultLength
  799. );
  800. if (!NT_ERROR(RetVal) && bRealigned) {
  801. RtlCopyMemory((PVOID)pTempKeyInfo, KeyValueInformation, Length);
  802. }
  803. } except( NULL, EXCEPTION_EXECUTE_HANDLER){
  804. RetVal = GetExceptionCode ();
  805. }
  806. return RetVal;
  807. }
  808. NTSTATUS
  809. Wow64NtRestoreKey(
  810. IN HANDLE KeyHandle,
  811. IN HANDLE FileHandle,
  812. IN ULONG Flags
  813. )
  814. /*++
  815. Routine Description:
  816. A file in the format created by NtSaveKey may be loaded into
  817. the system's active registry with NtRestoreKey. An entire subtree
  818. is created in the active registry as a result. All of the
  819. data for the new sub-tree, including such things as security
  820. descriptors, will be read from the source file. The data will
  821. not be interpreted in any way.
  822. This call (unlike NtLoadKey, see below) copies the data. The
  823. system will NOT be using the source file after the call returns.
  824. If the flag REG_WHOLE_HIVE_VOLATILE is specified, a new hive
  825. can be created. It will be a memory only copy. The restore
  826. must be done to the root of a hive (e.g. \registry\user\<name>)
  827. If the flag is NOT set, then the target of the restore must
  828. be an existing hive. The restore can be done to an arbitrary
  829. location within an existing hive.
  830. Caller must have SeRestorePrivilege privilege.
  831. If the flag REG_REFRESH_HIVE is set (must be only flag) then the
  832. the Hive will be restored to its state as of the last flush.
  833. The hive must be marked NOLAZY_FLUSH, and the caller must have
  834. TCB privilege, and the handle must point to the root of the hive.
  835. If the refresh fails, the hive will be corrupt, and the system
  836. will bugcheck. Notifies are flushed. The hive file will be resized,
  837. the log will not. If there is any volatile space in the hive
  838. being refreshed, STATUS_UNSUCCESSFUL will be returned. (It's much
  839. too obscure a failure to warrant a new error code.)
  840. If the flag REG_FORCE_RESTORE is set, the restore operation is done
  841. even if the KeyHandle has open subkeys by other applications
  842. Arguments:
  843. KeyHandle - refers to the Key in the registry which is to be the
  844. root of the new tree read from the disk. This key
  845. will be replaced.
  846. FileHandle - refers to file to restore from, must have read access.
  847. Flags - If REG_WHOLE_HIVE_VOLATILE is set, then the copy will
  848. exist only in memory, and disappear when the machine
  849. is rebooted. No hive file will be created on disk.
  850. Normally, a hive file will be created on disk.
  851. Return Value:
  852. NTSTATUS - values TBS.
  853. --*/
  854. {
  855. return NtRestoreKey(
  856. KeyHandle,
  857. FileHandle,
  858. Flags
  859. );
  860. }
  861. NTSTATUS
  862. Wow64NtSaveKey(
  863. IN HANDLE KeyHandle,
  864. IN HANDLE FileHandle
  865. )
  866. /*++
  867. Routine Description:
  868. A subtree of the active registry may be written to a file in a
  869. format suitable for use with NtRestoreKey. All of the data in the
  870. subtree, including such things as security descriptors will be written
  871. out.
  872. Caller must have SeBackupPrivilege privilege.
  873. Arguments:
  874. KeyHandle - refers to the Key in the registry which is the
  875. root of the tree to be written to disk. The specified
  876. node will be included in the data written out.
  877. FileHandle - a file handle with write access to the target file
  878. of interest.
  879. Return Value:
  880. NTSTATUS - values TBS
  881. --*/
  882. {
  883. return NtSaveKey(
  884. KeyHandle,
  885. FileHandle
  886. );
  887. }
  888. NTSTATUS
  889. Wow64NtSaveMergedKeys(
  890. IN HANDLE HighPrecedenceKeyHandle,
  891. IN HANDLE LowPrecedenceKeyHandle,
  892. IN HANDLE FileHandle
  893. )
  894. /*++
  895. Routine Description:
  896. Two subtrees of the registry can be merged. The resulting subtree may
  897. be written to a file in a format suitable for use with NtRestoreKey.
  898. All of the data in the subtree, including such things as security
  899. descriptors will be written out.
  900. Caller must have SeBackupPrivilege privilege.
  901. Arguments:
  902. HighPrecedenceKeyHandle - refers to the key in the registry which is the
  903. root of the HighPrecedence tree. I.e., when a key is present in
  904. both trees headded by the two keys, the key underneath HighPrecedence
  905. tree will always prevail. The specified
  906. node will be included in the data written out.
  907. LowPrecedenceKeyHandle - referrs to the key in the registry which is the
  908. root of the "second choice" tree. Keys from this trees get saved
  909. when there is no equivalent key in the tree headded by HighPrecedenceKey
  910. FileHandle - a file handle with write access to the target file
  911. of interest.
  912. Return Value:
  913. NTSTATUS - values TBS
  914. --*/
  915. {
  916. return NtSaveMergedKeys(
  917. HighPrecedenceKeyHandle,
  918. LowPrecedenceKeyHandle,
  919. FileHandle
  920. );
  921. }
  922. NTSTATUS
  923. Wow64NtSetValueKey(
  924. IN HANDLE KeyHandle,
  925. IN PUNICODE_STRING ValueName,
  926. IN ULONG TitleIndex OPTIONAL,
  927. IN ULONG Type,
  928. IN PVOID Data,
  929. IN ULONG DataSize
  930. )
  931. /*++
  932. Routine Description:
  933. A value entry may be created or replaced with NtSetValueKey.
  934. If a value entry with a Value ID (i.e. name) matching the
  935. one specified by ValueName exists, it is deleted and replaced
  936. with the one specified. If no such value entry exists, a new
  937. one is created. NULL is a legal Value ID. While Value IDs must
  938. be unique within any given key, the same Value ID may appear
  939. in many different keys.
  940. Arguments:
  941. KeyHandle - Handle of the key whose for which a value entry is
  942. to be set. Must be opened for KEY_SET_VALUE access.
  943. ValueName - The unique (relative to the containing key) name
  944. of the value entry. May be NULL.
  945. TitleIndex - Supplies the title index for ValueName. The title
  946. index specifies the index of the localized alias for the ValueName.
  947. Type - The integer type number of the value entry.
  948. Data - Pointer to buffer with actual data for the value entry.
  949. DataSize - Size of Data buffer.
  950. Return Value:
  951. NTSTATUS - Result code from call, among the following:
  952. <TBS>
  953. --*/
  954. {
  955. WCHAR ThunkData[_MAX_PATH];
  956. PWCHAR pCorrectData = (PWCHAR)Data;
  957. ULONG CorrectDataSize = DataSize;
  958. NTSTATUS St = STATUS_SUCCESS;
  959. //
  960. // thunk %ProgramFiles% ==> %ProgramFiles(x86)%
  961. // %commonprogramfiles% ==> %commonprogramfiles(x86)%
  962. //
  963. try {
  964. if ((DataSize > 0) &&
  965. (DataSize < ( _MAX_PATH*sizeof (WCHAR) - 10) &&
  966. ((Type == REG_SZ) || (Type == REG_EXPAND_SZ) )) ) { //(x86)==>10 byte
  967. PWCHAR p;
  968. PWCHAR t;
  969. //
  970. // do the thunking here.
  971. //
  972. memcpy ( (PBYTE ) &ThunkData[0], (PBYTE)Data, DataSize);
  973. ThunkData [DataSize/sizeof (WCHAR) ] = UNICODE_NULL; // make sure NULL terminated
  974. if ( (p = wcsstr (ThunkData, L"%ProgramFiles%" )) != NULL ){
  975. p +=13; //skip at the end of %ProgramFiles
  976. } else if ( (p = wcsstr (ThunkData, L"%commonprogramfiles%")) != NULL ){
  977. p +=19; //skip at the end of %commonprogramfiles
  978. }
  979. if (p) {
  980. t = pCorrectData + (p - ThunkData);
  981. wcscpy(p, L"(x86)"); //(x86)
  982. wcscat(p, t); //copy rest of the string
  983. pCorrectData = ThunkData;
  984. CorrectDataSize += sizeof (L"(x86)");
  985. } else if ( (p=wcsistr (Data, L"\\System32\\")) != NULL) {
  986. if (IsOnReflectionByHandle ( KeyHandle ) ) {
  987. wcsncpy (p, L"\\SysWow64\\",10);
  988. }
  989. }
  990. }
  991. } except (EXCEPTION_EXECUTE_HANDLER) {
  992. St = GetExceptionCode ();
  993. }
  994. //
  995. // Check if the operation should proceed. The key might be on access denied list.
  996. //
  997. if (NT_SUCCESS (St)) {
  998. St = NtSetValueKey(
  999. KeyHandle,
  1000. ValueName,
  1001. TitleIndex ,
  1002. Type,
  1003. (PVOID)pCorrectData,
  1004. CorrectDataSize
  1005. );
  1006. if (NT_SUCCESS(St)) {
  1007. Wow64RegSetKeyDirty (KeyHandle ); // Need some clean/sync up on exit
  1008. }
  1009. }
  1010. return St;
  1011. }
  1012. NTSTATUS
  1013. Wow64NtLoadKey(
  1014. IN POBJECT_ATTRIBUTES TargetKey,
  1015. IN POBJECT_ATTRIBUTES SourceFile
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. A hive (file in the format created by NtSaveKey) may be linked
  1020. into the active registry with this call. UNLIKE NtRestoreKey,
  1021. the file specified to NtLoadKey will become the actual backing
  1022. store of part of the registry (that is, it will NOT be copied.)
  1023. The file may have an associated .log file.
  1024. If the hive file is marked as needing a .log file, and one is
  1025. not present, the call will fail.
  1026. The name specified by SourceFile must be such that ".log" can
  1027. be appended to it to generate the name of the log file. Thus,
  1028. on FAT file systems, the hive file may not have an extension.
  1029. Caller must have SeRestorePrivilege privilege.
  1030. This call is used by logon to make the user's profile available
  1031. in the registry. It is not intended for use doing backup,
  1032. restore, etc. Use NtRestoreKey for that.
  1033. Arguments:
  1034. TargetKey - specifies the path to a key to link the hive to.
  1035. path must be of the form "\registry\user\<username>"
  1036. SourceFile - specifies a file. while file could be remote,
  1037. that is strongly discouraged.
  1038. Return Value:
  1039. NTSTATUS - values TBS.
  1040. --*/
  1041. {
  1042. return NtLoadKey(TargetKey, SourceFile);
  1043. }
  1044. NTSTATUS
  1045. Wow64NtLoadKey2(
  1046. IN POBJECT_ATTRIBUTES TargetKey,
  1047. IN POBJECT_ATTRIBUTES SourceFile,
  1048. IN ULONG Flags
  1049. )
  1050. /*++
  1051. Routine Description:
  1052. A hive (file in the format created by NtSaveKey) may be linked
  1053. into the active registry with this call. UNLIKE NtRestoreKey,
  1054. the file specified to NtLoadKey will become the actual backing
  1055. store of part of the registry (that is, it will NOT be copied.)
  1056. The file may have an associated .log file.
  1057. If the hive file is marked as needing a .log file, and one is
  1058. not present, the call will fail.
  1059. The name specified by SourceFile must be such that ".log" can
  1060. be appended to it to generate the name of the log file. Thus,
  1061. on FAT file systems, the hive file may not have an extension.
  1062. Caller must have SeRestorePrivilege privilege.
  1063. This call is used by logon to make the user's profile available
  1064. in the registry. It is not intended for use doing backup,
  1065. restore, etc. Use NtRestoreKey for that.
  1066. Arguments:
  1067. TargetKey - specifies the path to a key to link the hive to.
  1068. path must be of the form "\registry\user\<username>"
  1069. SourceFile - specifies a file. while file could be remote,
  1070. that is strongly discouraged.
  1071. Flags - specifies any flags that should be used for the load operation.
  1072. The only valid flag is REG_NO_LAZY_FLUSH.
  1073. Return Value:
  1074. NTSTATUS - values TBS.
  1075. --*/
  1076. {
  1077. return NtLoadKey2(
  1078. TargetKey,
  1079. SourceFile,
  1080. Flags
  1081. );
  1082. }
  1083. NTSTATUS
  1084. Wow64NtUnloadKey(
  1085. IN POBJECT_ATTRIBUTES TargetKey
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Drop a subtree (hive) out of the registry.
  1090. Will fail if applied to anything other than the root of a hive.
  1091. Cannot be applied to core system hives (HARDWARE, SYSTEM, etc.)
  1092. Can be applied to user hives loaded via NtRestoreKey or NtLoadKey.
  1093. If there are handles open to the hive being dropped, this call
  1094. will fail. Terminate relevent processes so that handles are
  1095. closed.
  1096. This call will flush the hive being dropped.
  1097. Caller must have SeRestorePrivilege privilege.
  1098. Arguments:
  1099. TargetKey - specifies the path to a key to link the hive to.
  1100. path must be of the form "\registry\user\<username>"
  1101. Return Value:
  1102. NTSTATUS - values TBS.
  1103. --*/
  1104. {
  1105. return NtUnloadKey(
  1106. TargetKey
  1107. );
  1108. }
  1109. NTSTATUS
  1110. Wow64NtSetInformationKey(
  1111. IN HANDLE KeyHandle,
  1112. IN KEY_SET_INFORMATION_CLASS KeySetInformationClass,
  1113. IN PVOID KeySetInformation,
  1114. IN ULONG KeySetInformationLength
  1115. )
  1116. {
  1117. return NtSetInformationKey(
  1118. KeyHandle,
  1119. KeySetInformationClass,
  1120. KeySetInformation,
  1121. KeySetInformationLength
  1122. );
  1123. }
  1124. NTSTATUS
  1125. Wow64NtReplaceKey(
  1126. IN POBJECT_ATTRIBUTES NewFile,
  1127. IN HANDLE TargetHandle,
  1128. IN POBJECT_ATTRIBUTES OldFile
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. A hive file may be "replaced" under a running system, such
  1133. that the new file will be the one actually used at next
  1134. boot, with this call.
  1135. This routine will:
  1136. Open newfile, and verify that it is a valid Hive file.
  1137. Rename the Hive file backing TargetHandle to OldFile.
  1138. All handles will remain open, and the system will continue
  1139. to use the file until rebooted.
  1140. Rename newfile to match the name of the hive file
  1141. backing TargetHandle.
  1142. .log and .alt files are ignored
  1143. The system must be rebooted for any useful effect to be seen.
  1144. Caller must have SeRestorePrivilege.
  1145. Arguments:
  1146. NewFile - specifies the new file to use. must not be just
  1147. a handle, since NtReplaceKey will insist on
  1148. opening the file for exclusive access (which it
  1149. will hold until the system is rebooted.)
  1150. TargetHandle - handle to a registry hive root
  1151. OldFile - name of file to apply to current hive, which will
  1152. become old hive
  1153. Return Value:
  1154. NTSTATUS - values TBS.
  1155. --*/
  1156. {
  1157. return NtReplaceKey(
  1158. NewFile,
  1159. TargetHandle,
  1160. OldFile
  1161. );
  1162. }
  1163. NTSTATUS
  1164. Wow64NtQueryMultipleValueKey(
  1165. IN HANDLE KeyHandle,
  1166. IN PKEY_VALUE_ENTRY ValueEntries,
  1167. IN ULONG EntryCount,
  1168. OUT PVOID ValueBuffer,
  1169. IN OUT PULONG BufferLength,
  1170. OUT OPTIONAL PULONG RequiredBufferLength
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. Multiple values of any key may be queried atomically with
  1175. this api.
  1176. Arguments:
  1177. KeyHandle - Supplies the key to be queried.
  1178. ValueNames - Supplies an array of value names to be queried
  1179. ValueEntries - Returns an array of KEY_VALUE_ENTRY structures, one for each value.
  1180. EntryCount - Supplies the number of entries in the ValueNames and ValueEntries arrays
  1181. ValueBuffer - Returns the value data for each value.
  1182. BufferLength - Supplies the length of the ValueBuffer array in bytes.
  1183. Returns the length of the ValueBuffer array that was filled in.
  1184. RequiredBufferLength - if present, Returns the length in bytes of the ValueBuffer
  1185. array required to return all the values of this key.
  1186. Return Value:
  1187. NTSTATUS
  1188. --*/
  1189. {
  1190. return NtQueryMultipleValueKey( KeyHandle,
  1191. ValueEntries,
  1192. EntryCount,
  1193. ValueBuffer,
  1194. BufferLength,
  1195. RequiredBufferLength
  1196. );
  1197. }
  1198. NTSTATUS
  1199. Wow64NtQueryOpenSubKeys(
  1200. IN POBJECT_ATTRIBUTES TargetKey,
  1201. OUT PULONG HandleCount
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Dumps all the subkeys of the target key that are kept open by some other
  1206. process; Returns the number of open subkeys
  1207. Arguments:
  1208. TargetKey - specifies the path to a key to link the hive to.
  1209. path must be of the form "\registry\user\<username>"
  1210. Return Value:
  1211. NTSTATUS - values TBS.
  1212. --*/
  1213. {
  1214. return NtQueryOpenSubKeys( TargetKey, HandleCount );
  1215. }
  1216. NTSTATUS
  1217. Wow64NtSetSecurityObject (
  1218. IN HANDLE Handle,
  1219. IN SECURITY_INFORMATION SecurityInformation,
  1220. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. This routine is used to invoke an object's security routine. It
  1225. is used to set the object's security state.
  1226. Arguments:
  1227. Handle - Supplies the handle for the object being modified
  1228. SecurityInformation - Indicates the type of information we are
  1229. interested in setting. e.g., owner, group, dacl, or sacl.
  1230. SecurityDescriptor - Supplies the security descriptor for the
  1231. object being modified.
  1232. Return Value:
  1233. An appropriate NTSTATUS value
  1234. --*/
  1235. {
  1236. //
  1237. // Check if the handle points to a particular key, then if the API succeed
  1238. // Reflect that.
  1239. //
  1240. NTSTATUS St;
  1241. NTSTATUS Status;
  1242. POBJECT_TYPE_INFORMATION pTypeInfo;
  1243. CHAR Buffer[1024];
  1244. pTypeInfo = (POBJECT_TYPE_INFORMATION) Buffer;
  1245. Status = NtQueryObject(Handle,
  1246. ObjectTypeInformation,
  1247. pTypeInfo,
  1248. sizeof (Buffer),
  1249. NULL
  1250. );
  1251. St = NtSetSecurityObject (
  1252. Handle,
  1253. SecurityInformation,
  1254. SecurityDescriptor
  1255. );
  1256. //
  1257. // If NT_SUCCESS (St) && the handle point on to a registry Key set the handle for reflection.
  1258. //
  1259. if (NT_SUCCESS (St) && NT_SUCCESS (Status)){
  1260. if ( _wcsnicmp ( pTypeInfo->TypeName.Buffer, L"Key", 3) == 0)
  1261. Wow64RegSetKeyDirty (Handle); // Need some clean/sync up on exit
  1262. }
  1263. return St;
  1264. }