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.

2757 lines
63 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. regmisc.c
  5. Abstract:
  6. This module implement Handle redirection for registry redirection.
  7. Author:
  8. ATM Shafiqul Khalid (askhalid) 16-June-2000
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #include <ntregapi.h>
  17. #define _WOW64REFLECTOR_
  18. #include "regremap.h"
  19. #include "wow64reg.h"
  20. #include "wow64reg\reflectr.h"
  21. #ifdef _WOW64DLLAPI_
  22. #include "wow64.h"
  23. #else
  24. #define ERRORLOG 1 //this one is completely dummy
  25. #define LOGPRINT(x)
  26. #define WOWASSERT(p)
  27. #endif //_WOW64DLLAPI_
  28. #define REFLECTOR_ENABLE_KEY L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\WOW64\\Reflector Setup"
  29. #define REFLECTOR_DISABLE_KEY L"\\Registry\\Machine\\System\\Setup"
  30. #define REFLECTOR_DISABLE_KEY_WOW64 L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\WOW64"
  31. BOOL
  32. HandleRunOnce (
  33. WCHAR *SrcNode
  34. );
  35. BOOL
  36. ReflectClassGuid (
  37. PWCHAR SrcName,
  38. DWORD dwDirection
  39. );
  40. VOID
  41. InitRegistry ();
  42. BOOL
  43. SyncGuidKey (
  44. HANDLE hSrc,
  45. HANDLE hDest,
  46. DWORD dwDirection,
  47. DWORD __bNewlyCreated
  48. );
  49. BOOL
  50. Wow64ReflectSecurity (
  51. HKEY SrcKey,
  52. HKEY DestKey
  53. );
  54. //
  55. //IsOnReflectionList: has hardcoded \\registry\\user\\<sid>_Classes.
  56. //
  57. DWORD ReflectListLen[18] ={0};
  58. WCHAR ReflectList[18][128]={
  59. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes"}, // alias to the classes root on the user hives
  60. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Classes"}, // alias to the classes root on the user hives
  61. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node"}, // alias to the classes root on the user hives
  62. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"}, // Runonce Key
  63. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"}, // Runonce Key
  64. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx"}, // Runonce Key
  65. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\COM3"}, // COM+ Key
  66. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\COM3"}, // COM+ Key
  67. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Ole"}, // OLE Key
  68. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Ole"}, // OLE Key
  69. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\EventSystem"}, // EventSystem
  70. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\EventSystem"}, // EventSystem
  71. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\RPC"}, // RPC
  72. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\RPC"}, // RPC
  73. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\TEST"}, // Test Node
  74. { L"\\REGISTRY\\MACHINE\\SOFTWARE\\TEST"}, // Test Node
  75. { L""}
  76. };
  77. typedef struct {
  78. HANDLE hBase; // handle to the original object
  79. HANDLE hRemap; // handle to the remapped object
  80. DWORD Status; // will have different attribute set.
  81. DWORD dwCount; // Handle count- according to dragos, we can ignore because multiple open get different handle.
  82. DWORD Attribute; //attribute to hold Key attribute
  83. } WOW64_HANDLE;
  84. #define TABLE_SEGMENT_MAX 500
  85. #define SEGMENT_SIZE 256
  86. #define DIRECTION_32_TO_64 10
  87. #define DIRECTION_64_TO_32 11
  88. //
  89. // Flag while copying value Key.
  90. //
  91. #define DEFAULT_FLAG 0x00000000
  92. #define DELETE_SRC_VALUEKEY 0x00000010
  93. #define DONT_DELETE_DEST_VALUEKEY 0x00000020
  94. #define PATCH_VALUE_KEY_NAME 0x00000040
  95. #define SYNC_VALUE_IF_REFLECTED_KEYS 0x00000080
  96. #define DONT_SYNC_IF_DLL_SURROGATE 0x00000100
  97. #define WOW64_HANDLE_DIRTY 0x00000001 // some update operation was done using this handle
  98. #define WOW64_HANDLE_INUSE 0x00000002 // Tag this handle block not free
  99. #define HashValue (x) ((((x)>>24) + ((x)>>16) + (x)>>8 + (x)) % SEGMENT_SIZE )
  100. #define MyNtClose(hRemap) if (hRemap != NULL) { NtClose (hRemap); hRemap = NULL;}
  101. RTL_CRITICAL_SECTION HandleTable;
  102. //
  103. // BUGBUG: This module implement simplifiled version of handle redirection using linear list.
  104. // This must have to be implemented by a hash table if possible.
  105. //
  106. PVOID List[TABLE_SEGMENT_MAX];
  107. WOW64_HANDLE HandleList[SEGMENT_SIZE]; //hopefully this will be good enough for open key handle. It can always allocate dynamically.
  108. BOOL bTableInitialized=FALSE;
  109. BOOL bReflectorStatusOn = FALSE;
  110. LogMsg (
  111. HANDLE hKey,
  112. PWCHAR Msg
  113. )
  114. {
  115. WCHAR Name[WOW64_MAX_PATH];
  116. DWORD Len = WOW64_MAX_PATH;
  117. HandleToKeyName (hKey, Name, &Len);
  118. DbgPrint ("\nMsg:%S Key:%S",Msg, Name );
  119. }
  120. PVOID
  121. RegRemapAlloc (
  122. DWORD dwSize
  123. )
  124. /*++
  125. Routine Description:
  126. Allocate memory.
  127. Arguments:
  128. dwSize - size of memory to allocate.
  129. Return Value:
  130. return appropriate buffer.
  131. --*/
  132. {
  133. PVOID pBuffer;
  134. //
  135. // For performance reason you might allocate big chunk and then reuse.
  136. //
  137. pBuffer = RtlAllocateHeap (
  138. RtlProcessHeap(),
  139. 0,
  140. dwSize);
  141. return pBuffer;
  142. }
  143. VOID
  144. RegRemapFree (
  145. PVOID pBuffer
  146. )
  147. /*++
  148. Routine Description:
  149. Free allocated mery.
  150. Arguments:
  151. dwSize - size of memory to allocate.
  152. Return Value:
  153. None.
  154. --*/
  155. {
  156. //
  157. // For performance reason you might allocate big chunk and then reuse.
  158. //
  159. if ( pBuffer == NULL)
  160. return;
  161. RtlFreeHeap (
  162. RtlProcessHeap(),
  163. 0,
  164. pBuffer
  165. );
  166. return;
  167. }
  168. BOOL
  169. InitHandleTable ( )
  170. /*++
  171. Routine Description:
  172. Initialize the table with appropriate allocation and value if its not initialized yet.
  173. Arguments:
  174. None.
  175. Return Value:
  176. TRUE if the function succeed.
  177. FALSE otherwise.
  178. <TBD> this might allocate more memory and free up later.
  179. --*/
  180. {
  181. HKEY hWowSetupKey;
  182. HKEY hKey;
  183. OBJECT_ATTRIBUTES Obja;
  184. UNICODE_STRING KeyName;
  185. UNICODE_STRING ValueName;
  186. NTSTATUS Status;
  187. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL;
  188. BYTE Buff[sizeof (KEY_VALUE_PARTIAL_INFORMATION)+10];
  189. if ( bTableInitialized == TRUE )
  190. return TRUE; // already initialized
  191. memset (List, 0, sizeof (List));
  192. memset (HandleList, 0, sizeof (HandleList));
  193. List [0]= HandleList;
  194. bTableInitialized = TRUE;
  195. RtlInitUnicodeString (&KeyName, REFLECTOR_DISABLE_KEY);
  196. InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
  197. Status = NtOpenKey (&hKey, KEY_READ, &Obja);
  198. if (NT_SUCCESS(Status)) {
  199. DWORD Res;
  200. DWORD Len = sizeof (Buff);
  201. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)Buff;
  202. RtlInitUnicodeString (&ValueName, L"SystemSetupInProgress");
  203. Status = NtQueryValueKey(
  204. hKey,
  205. &ValueName,
  206. KeyValuePartialInformation,
  207. KeyValueInformation,
  208. Len,
  209. &Len
  210. );
  211. NtClose (hKey); // reflection should be disable because setup is on its way.
  212. if (NT_SUCCESS(Status)) {
  213. if ( *(LONG *)KeyValueInformation->Data != 0)
  214. return FALSE; //system setup is in progress no reflection
  215. } else return FALSE;
  216. } else return FALSE;
  217. bReflectorStatusOn = TRUE; //Now reflector is on.
  218. #ifdef DBG
  219. //
  220. // Check if the systemwide flag is turned off.
  221. //
  222. RtlInitUnicodeString (&KeyName, REFLECTOR_DISABLE_KEY_WOW64);
  223. InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
  224. Status = NtOpenKey (&hKey, KEY_READ, &Obja);
  225. if (NT_SUCCESS(Status)) {
  226. DWORD Res;
  227. DWORD Len = sizeof (Buff);
  228. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)Buff;
  229. RtlInitUnicodeString (&ValueName, L"DisableReflector");
  230. Status = NtQueryValueKey(
  231. hKey,
  232. &ValueName,
  233. KeyValuePartialInformation,
  234. KeyValueInformation,
  235. Len,
  236. &Len
  237. );
  238. NtClose (hKey); // reflection should be disable because setup is on its way.
  239. if (NT_SUCCESS(Status)) {
  240. if ( *(LONG *)KeyValueInformation->Data != 0)
  241. bReflectorStatusOn = FALSE; //Now reflector is on.
  242. }
  243. }
  244. if (!bReflectorStatusOn)
  245. return FALSE;
  246. #endif //DBG
  247. //
  248. // Initialize Internal ISN node table to remap keys.
  249. //
  250. Status = RtlInitializeCriticalSection( &HandleTable );
  251. if (!NT_SUCCESS (Status))
  252. return FALSE;
  253. return TRUE;
  254. }
  255. WOW64_HANDLE *
  256. GetFreeHandleBlock (
  257. HANDLE hKey
  258. )
  259. /*++
  260. Routine Description:
  261. Return a free block from the handle table.
  262. Arguments:
  263. hKey - Handle to the key that will be inserted into the table.
  264. Return Value:
  265. Return a free block on the table.
  266. --*/
  267. {
  268. WOW64_HANDLE *pList;
  269. DWORD i,k;
  270. RtlEnterCriticalSection(&HandleTable);
  271. for (i=0;i<TABLE_SEGMENT_MAX && List[i] != NULL;i++) {
  272. pList = (WOW64_HANDLE *)List[i];
  273. for (k=0;k<SEGMENT_SIZE;k++)
  274. if (pList[k].hBase == NULL && (!(WOW64_HANDLE_INUSE & pList[k].Status )) ) {
  275. //
  276. // Mark the entry in use
  277. //
  278. pList[k].Status = WOW64_HANDLE_INUSE;
  279. RtlLeaveCriticalSection(&HandleTable);
  280. return &pList[k];
  281. }
  282. }
  283. RtlLeaveCriticalSection(&HandleTable);
  284. return NULL;
  285. }
  286. WOW64_HANDLE *
  287. GetHandleBlock (
  288. HANDLE hKey
  289. )
  290. /*++
  291. Routine Description:
  292. Return a the block having information associated with the given handle.
  293. Arguments:
  294. hKey - Handle to the key that need to be investigated.
  295. Return Value:
  296. Return a the block that has the handle.
  297. --*/
  298. {
  299. WOW64_HANDLE *pList;
  300. DWORD i,k;
  301. for (i=0;i<TABLE_SEGMENT_MAX, List[i] != NULL;i++) {
  302. pList = (WOW64_HANDLE *)List[i];
  303. for (k=0;k<SEGMENT_SIZE;k++)
  304. if (pList[k].hBase == hKey)
  305. return &pList[k];
  306. }
  307. return NULL;
  308. }
  309. HANDLE
  310. GetWow64Handle (
  311. HANDLE hKey
  312. )
  313. /*++
  314. Routine Description:
  315. Return a handle to the remapped key if any.
  316. Arguments:
  317. hKey - Handle to the key that need ramapped information.
  318. Return Value:
  319. Handle to the remapped key.
  320. NULL if no remapped key is there.
  321. --*/
  322. {
  323. WOW64_HANDLE *pHandleBlock = GetHandleBlock (hKey);
  324. if ( pHandleBlock == NULL )
  325. return NULL;
  326. return pHandleBlock->hRemap;
  327. }
  328. BOOL
  329. IsWow64Handle (
  330. HANDLE hKey
  331. )
  332. /*++
  333. Routine Description:
  334. Check if the handle has been tagged to watch while closing.
  335. Arguments:
  336. hKey - Handle to the key that need to be checked.
  337. Return Value:
  338. TRUE if the handle is on the TABLE.
  339. FALSE otherwise.
  340. --*/
  341. {
  342. return GetHandleBlock (hKey) != NULL;
  343. }
  344. WOW64_HANDLE *
  345. InsertWow64Handle (
  346. HANDLE hKeyBase,
  347. HANDLE hKeyRemap
  348. )
  349. /*++
  350. Routine Description:
  351. Allocate some resources so that some manipulation can be done in case of
  352. Key changes.
  353. Arguments:
  354. hKey - Handle to the base key that need to be marked.
  355. Return Value:
  356. Valid block that refer to the handle.
  357. --*/
  358. {
  359. WCHAR SrcNode[WOW64_MAX_PATH];
  360. DWORD dwLen = WOW64_MAX_PATH;
  361. WOW64_HANDLE *pHandleBlock = NULL;
  362. pHandleBlock = GetHandleBlock (hKeyBase);
  363. if (hKeyBase == NULL || hKeyRemap == NULL)
  364. return NULL;
  365. if ( pHandleBlock == NULL ) { // new handle
  366. //
  367. // Get the path name and if the key is on the reflection list add it.
  368. //
  369. if (!HandleToKeyName ( hKeyBase, SrcNode, &dwLen ))
  370. return NULL;
  371. //
  372. // Make sure The name is on the List otherwise forget.
  373. //
  374. if ( !IsOnReflectionList (SrcNode))
  375. return NULL;
  376. pHandleBlock = GetFreeHandleBlock (hKeyBase);
  377. }
  378. if ( pHandleBlock == NULL)
  379. return NULL;
  380. pHandleBlock->hRemap = hKeyRemap;
  381. pHandleBlock->hBase = hKeyBase;
  382. return pHandleBlock;
  383. }
  384. BOOL
  385. Wow64RegSetKeyDirty (
  386. HANDLE hKey
  387. )
  388. /*++
  389. Routine Description:
  390. Mark the handle dirty, i.e., some value has been changed associated to this Key.
  391. Arguments:
  392. hKey - Handle to the base key that need to be marked.
  393. Return Value:
  394. TRUE if the key is on the list of reflection.
  395. FALSE otherwise.
  396. --*/
  397. {
  398. WOW64_HANDLE *pHandleBlock;
  399. hKey = (HANDLE)((SIZE_T)hKey & ~3); //ignore the last 2 bits
  400. InitHandleTable (); //initialize if its already not initialized.
  401. if (!bReflectorStatusOn)
  402. return TRUE; //reflector isn't enable yet.
  403. if (( pHandleBlock = InsertWow64Handle (hKey, hKey)) == NULL)
  404. return FALSE;
  405. pHandleBlock->Status |= WOW64_HANDLE_DIRTY;
  406. return TRUE;
  407. }
  408. VOID
  409. CloseWow64Handle (
  410. WOW64_HANDLE *pHandleBlock
  411. )
  412. {
  413. RtlEnterCriticalSection(&HandleTable);
  414. pHandleBlock->hBase = NULL;
  415. pHandleBlock->hRemap = NULL;
  416. pHandleBlock->Status = 0;
  417. pHandleBlock->Attribute = 0;
  418. RtlLeaveCriticalSection(&HandleTable);
  419. }
  420. BOOL
  421. Wow64RegCloseKey (
  422. HANDLE hKey
  423. )
  424. /*++
  425. Routine Description:
  426. Remove entry associated with the handle.
  427. Arguments:
  428. hKey - Handle to the key that is being closed.
  429. Return Value:
  430. TRUE if function succeed.
  431. FALSE otherwise.
  432. --*/
  433. {
  434. WOW64_HANDLE *pHandleBlock;
  435. hKey = (HANDLE)((SIZE_T)hKey & ~3); //ignore the last 2 bits
  436. if (!bReflectorStatusOn)
  437. return TRUE; //reflector isn't enable yet.
  438. if ((pHandleBlock = GetHandleBlock (hKey)) == NULL )
  439. return FALSE;
  440. if (pHandleBlock->Status & WOW64_HANDLE_DIRTY) // if the handle is dirty sync the node
  441. NtSyncNode ( hKey, NULL, FALSE ); //BUGBUG
  442. if ( pHandleBlock->hRemap!= hKey )
  443. MyNtClose ( pHandleBlock->hRemap ); // if Same then just allocating block
  444. CloseWow64Handle ( pHandleBlock );
  445. //
  446. // Call sync APi. to synchronize the registry reflection
  447. //
  448. return TRUE;
  449. }
  450. void
  451. CleanupReflector (
  452. DWORD dwFlag
  453. )
  454. /*++
  455. Routine Description:
  456. This routine is called while apps is shutting down. This will give reflector a chance to
  457. reflect any leftover handle than need reflection.
  458. This can be called from multiple places, like NtTerminateProcess, Advapi32 dll
  459. detach or shutdown routine.
  460. Arguments:
  461. dwFlag - for future use to track from where this call came from.
  462. Return Value:
  463. None.
  464. --*/
  465. {
  466. WOW64_HANDLE *pList;
  467. DWORD i,k;
  468. for (i=0;i<TABLE_SEGMENT_MAX, List[i] != NULL;i++) {
  469. pList = (WOW64_HANDLE *)List[i];
  470. for (k=0;k<SEGMENT_SIZE;k++)
  471. if ((pList[k].hBase != NULL) && (pList[k].Status & WOW64_HANDLE_DIRTY) )
  472. Wow64RegCloseKey(pList[k].hBase);
  473. }
  474. }
  475. NTSTATUS
  476. Wow64NtClose(
  477. IN HANDLE Handle
  478. )
  479. /*++
  480. Routine Description:
  481. Intercept NtClose Call.
  482. Arguments:
  483. Handle - Handle to the object that is being closed.
  484. Return Value:
  485. return valid NTSTATUS
  486. --*/
  487. {
  488. Wow64RegCloseKey ( Handle );
  489. return NtClose ( Handle );
  490. }
  491. BOOL
  492. IsOnReflectionList (
  493. PWCHAR Path
  494. )
  495. /*++
  496. Routine Description:
  497. Check if the given path is on the list of reflection.
  498. Arguments:
  499. Path - Path to the key that need to be chacked for reflection.
  500. Return Value:
  501. TRUE if the key is on the list of reflection.
  502. FALSE otherwise.
  503. --*/
  504. {
  505. DWORD i =0;
  506. //
  507. // Check exception to the list, non reflectable like uninstaller/TypeLib etc
  508. //
  509. //
  510. // _Classes \Registry\user\sid_Classes is reflected by default.
  511. //
  512. //if ( wcslen (Path) >= 69) //sizeof \Registry\user\sid_Classes
  513. //if ( wcsncmp (Path+61, L"_Classes", 8) == 0 ) //69 is the size of user classes sid and 61 is for sanity check
  514. if ( wcsistr (Path, L"_Classes"))
  515. return TRUE;
  516. if (ReflectListLen[0]==0) {
  517. i=0;
  518. while (ReflectList[i][0] != UNICODE_NULL ) {
  519. ReflectListLen[i] = wcslen (ReflectList[i]);
  520. i++;
  521. }
  522. }
  523. i=0;
  524. while (ReflectList[i][0] != UNICODE_NULL ) {
  525. if ( _wcsnicmp (ReflectList[i], Path, ReflectListLen[i]) == 0)
  526. return TRUE;
  527. i++;
  528. }
  529. return FALSE;
  530. }
  531. BOOL
  532. UpdateKeyTag (
  533. HKEY hBase,
  534. DWORD dwAttribute
  535. )
  536. /*++
  537. Routine Description:
  538. Update a particular Key tag, like written by 32bit apps or its a copy by reflector.
  539. Arguments:
  540. hBase - handle to a key to operate.
  541. dwAttribute - tag value its can be
  542. 0x01 written by 32bit apps.
  543. 0x02 created by reflector.
  544. Return Value:
  545. TRUE if the function succeed.
  546. FALSE otherwise.
  547. --*/
  548. {
  549. //
  550. // the flag can't be >0x0f i.e., last 4 bits
  551. //
  552. KEY_USER_FLAGS_INFORMATION sFlag;
  553. NTSTATUS st;
  554. sFlag.UserFlags = dwAttribute;
  555. st = NtSetInformationKey(
  556. hBase,
  557. KeyUserFlagsInformation,
  558. &sFlag,
  559. sizeof( KEY_USER_FLAGS_INFORMATION)
  560. );
  561. if (!NT_SUCCESS (st))
  562. return FALSE;
  563. return TRUE;
  564. }
  565. BOOL
  566. QueryKeyTag (
  567. HKEY hBase,
  568. DWORD *dwAttribute
  569. )
  570. /*++
  571. Routine Description:
  572. Read Key tag, like written by 32bit apps or its a copy by reflector.
  573. Arguments:
  574. hBase - handle to a key to operate.
  575. dwAttribute - receive the TAG
  576. 0x01 written by 32bit apps.
  577. 0x02 created by reflector.
  578. Return Value:
  579. TRUE if the function succeed.
  580. FALSE otherwise.
  581. --*/
  582. {
  583. DWORD ResLen;
  584. KEY_USER_FLAGS_INFORMATION sFlag;
  585. NTSTATUS st;
  586. if ( dwAttribute == NULL )
  587. return FALSE;
  588. if ( hBase == NULL )
  589. return FALSE;
  590. *dwAttribute =0;
  591. st = NtQueryKey(
  592. hBase,
  593. KeyFlagsInformation,
  594. (PVOID)&sFlag,
  595. sizeof(KEY_FLAGS_INFORMATION),
  596. &ResLen);
  597. if (!NT_SUCCESS (st))
  598. return FALSE;
  599. *dwAttribute = sFlag.UserFlags;
  600. return TRUE;
  601. }
  602. BOOL
  603. SyncValue (
  604. HANDLE hBase,
  605. HANDLE hRemap,
  606. DWORD dwDirection,
  607. DWORD dwFlag
  608. )
  609. /*++
  610. Routine Description:
  611. Synchronize a two node with value Key. Delete from the RemapKey, and copy from Base
  612. Arguments:
  613. hBase - Handle to the src key.
  614. hRemap - Handle to the remap key.
  615. dwDirection - SyncDitection
  616. DIRECTION_32_TO_64 - 32bit is the source of information
  617. DIRECTION_64_TO_32 - 32bit is the source of information
  618. dwFlag - determine the behavior of the operation.
  619. DELETE_SRC_VALUEKEY delete source value key after coping on the dest.
  620. DONT_DELETE_DEST_VALUEKEY don't delete dest before copying from src.
  621. DEFAULT_FLAG - this means the default operation.
  622. SYNC_VALUE_IF_REFLECTED_KEYS - if either one is reflected key then sync.
  623. Return Value:
  624. TRUE if the function succeed.
  625. FALSE otherwise.
  626. --*/
  627. {
  628. HANDLE hTimeStampKey;
  629. NTSTATUS st= STATUS_SUCCESS;
  630. DWORD Index=0;
  631. DWORD ResultLength;
  632. DWORD LastKnownSize = 0;
  633. UNICODE_STRING UnicodeValueName;
  634. PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
  635. BYTE Buff [sizeof(KEY_VALUE_FULL_INFORMATION) + 2048];
  636. WCHAR TmpChar;
  637. ULONG Length = sizeof(KEY_VALUE_FULL_INFORMATION) + 2048;
  638. KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buff;
  639. if ( SYNC_VALUE_IF_REFLECTED_KEYS & dwFlag) {
  640. DWORD Attrib1 =0;
  641. DWORD Attrib2 =0;
  642. QueryKeyTag (hBase, &Attrib1);
  643. QueryKeyTag (hRemap, &Attrib2);
  644. //
  645. // if atleast one is a reflected Key then sync value
  646. //
  647. if (!( (Attrib1 & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) ||
  648. (Attrib2 & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) ) ) // reflector touched this Key
  649. return TRUE;
  650. }
  651. for (Index=0;;Index++) {
  652. st = NtEnumerateValueKey(
  653. hRemap,
  654. Index,
  655. KeyValueFullInformation,
  656. KeyValueInformation,
  657. Length,
  658. &ResultLength
  659. );
  660. if (!NT_SUCCESS(st))
  661. break;
  662. KeyValueInformation->Name[KeyValueInformation->NameLength/2] = UNICODE_NULL;
  663. RtlInitUnicodeString( &UnicodeValueName, KeyValueInformation->Name );
  664. if ( !(DONT_DELETE_DEST_VALUEKEY & dwFlag))
  665. if ( NtDeleteValueKey(
  666. hRemap,
  667. &UnicodeValueName
  668. ) == STATUS_SUCCESS ) Index--;
  669. }
  670. //
  671. // Copy all key from the Base. For each copy patch value if applicable
  672. //
  673. for (Index=0, st= STATUS_SUCCESS;;Index++) {
  674. st = NtEnumerateValueKey(
  675. hBase,
  676. Index,
  677. KeyValueFullInformation,
  678. KeyValueInformation,
  679. Length,
  680. &ResultLength
  681. );
  682. if (st == STATUS_BUFFER_OVERFLOW ) {
  683. //Allocate more Buffer BUGBUG name shouldn't that big
  684. DbgPrint ("\nWow64: Will ignore any Key value larger than 2048 byte");
  685. }
  686. if (!NT_SUCCESS (st))
  687. break;
  688. TmpChar = KeyValueInformation->Name[KeyValueInformation->NameLength/2];
  689. KeyValueInformation->Name[KeyValueInformation->NameLength/2] = UNICODE_NULL;
  690. RtlInitUnicodeString( &UnicodeValueName, KeyValueInformation->Name );
  691. //
  692. // Check if you need to filter the Value DllSurrogate is such one.
  693. //
  694. if (dwFlag & DONT_SYNC_IF_DLL_SURROGATE) {
  695. if (_wcsnicmp (KeyValueInformation->Name, L"DllSurrogate",12 )==0 && KeyValueInformation->DataLength <=2) // size of UNICODE_NULL
  696. continue;
  697. }
  698. if ( (DELETE_SRC_VALUEKEY & dwFlag)) //delete from source in case of runonce
  699. if ( NtDeleteValueKey(
  700. hBase,
  701. &UnicodeValueName
  702. ) == STATUS_SUCCESS ) Index--;
  703. if ( (PATCH_VALUE_KEY_NAME & dwFlag) && (DIRECTION_32_TO_64 == dwDirection)) {
  704. wcscat (KeyValueInformation->Name, L"_x86");
  705. RtlInitUnicodeString( &UnicodeValueName, KeyValueInformation->Name );
  706. }
  707. KeyValueInformation->Name[KeyValueInformation->NameLength/2] = TmpChar;
  708. NtSetValueKey(
  709. hRemap,
  710. &UnicodeValueName,
  711. KeyValueInformation->TitleIndex,
  712. KeyValueInformation->Type,
  713. (PBYTE)(KeyValueInformation)+KeyValueInformation->DataOffset,
  714. KeyValueInformation->DataLength
  715. );
  716. }
  717. //
  718. // Now reflect the security attribute
  719. //
  720. Wow64ReflectSecurity (hBase, hRemap );
  721. return TRUE;
  722. }
  723. BOOL
  724. ReflectDllSurrogateKey (
  725. PWCHAR SrcNode
  726. )
  727. /*++
  728. Routine Description:
  729. Determine if the DllSurrogateKey under AppID shoule be reflected.
  730. //By default this should always be reflected. Except when the key is empty.
  731. Arguments:
  732. SrcNode - Name of the node to be synced.
  733. Return Value:
  734. TRUE if the key Should be reflected.
  735. FALSE otherwise.
  736. --*/
  737. {
  738. BYTE KeyBuffer[512];
  739. DWORD KeyBufferSize = sizeof (KeyBuffer);
  740. DWORD ResultLength;
  741. UNICODE_STRING ValueName;
  742. NTSTATUS Status;
  743. PWCHAR pStr;
  744. HKEY hKey;
  745. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL;
  746. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyBuffer;
  747. RtlInitUnicodeString (&ValueName, L"");
  748. //
  749. // Apply special rule of empty AppID key for dll surrogate.
  750. //
  751. if ( ( pStr = wcsistr (SrcNode, L"\\DllSurrogate") ) == NULL)
  752. return TRUE;
  753. if ( *(pStr+13) != UNICODE_NULL) {
  754. return TRUE;
  755. }
  756. //
  757. // Consider only value in that key
  758. //
  759. //
  760. // if value key isn't empty reflect, i.e., return FALSE.
  761. //
  762. hKey = OpenNode (SrcNode);
  763. *(LONG *)KeyValueInformation->Data = 0;
  764. Status = NtQueryValueKey(
  765. hKey,
  766. &ValueName,
  767. KeyValuePartialInformation,
  768. KeyValueInformation,
  769. KeyBufferSize,
  770. &ResultLength);
  771. if (NULL != hKey)
  772. NtClose (hKey); // reflection should be disable because setup is on its way.
  773. if ( *(LONG *)KeyValueInformation->Data == 0)
  774. return FALSE;
  775. return TRUE;
  776. }
  777. BOOL
  778. ReflectInprocHandler32KeyByHandle (
  779. HKEY hKey
  780. )
  781. /*++
  782. Routine Description:
  783. Determine if the ReflectInprocHandler32Key under CLSID shoule be reflected.
  784. //By default this should always be reflected. Except when the key is empty.
  785. Arguments:
  786. SrcNode - Name of the node to be synced.
  787. Return Value:
  788. TRUE if the key Should be reflected.
  789. FALSE otherwise.
  790. --*/
  791. {
  792. BYTE KeyBuffer[512];
  793. DWORD KeyBufferSize = sizeof (KeyBuffer);
  794. DWORD ResultLength;
  795. UNICODE_STRING ValueName;
  796. NTSTATUS Status;
  797. PWCHAR pStr;
  798. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL;
  799. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyBuffer;
  800. RtlInitUnicodeString (&ValueName, L""); //default value Key
  801. //
  802. // if value key isn't empty reflect, i.e., return FALSE.
  803. //
  804. //return FALSE; //never reflect
  805. *(LONG *)KeyValueInformation->Data = 0;
  806. Status = NtQueryValueKey(
  807. hKey,
  808. &ValueName,
  809. KeyValuePartialInformation,
  810. KeyValueInformation,
  811. KeyBufferSize,
  812. &ResultLength
  813. );
  814. pStr = (PWCHAR)KeyValueInformation->Data;
  815. if ( NT_SUCCESS(Status) && pStr != NULL) { //Need to check type
  816. if ( 0 == _wcsnicmp (pStr, L"ole32.dll", 9))
  817. return TRUE;
  818. if ( 0 == _wcsnicmp (pStr, L"oleaut32.dll", 12))
  819. return TRUE;
  820. }
  821. return FALSE;
  822. }
  823. BOOL
  824. ReflectInprocHandler32KeyByName (
  825. PWCHAR SrcNode
  826. )
  827. /*++
  828. Routine Description:
  829. Determine if the ReflectInprocHandler32Key under CLSID shoule be reflected.
  830. //By default this should always be reflected. Except when the key is empty.
  831. Arguments:
  832. SrcNode - Name of the node to be synced.
  833. Return Value:
  834. TRUE if the key Should be reflected.
  835. FALSE otherwise.
  836. --*/
  837. {
  838. HKEY hKey;
  839. BOOL bRet = FALSE;
  840. hKey = OpenNode (SrcNode);
  841. if ( NULL != hKey ) {
  842. bRet = ReflectInprocHandler32KeyByHandle (hKey);
  843. NtClose (hKey);
  844. }
  845. return bRet;
  846. }
  847. BOOL
  848. TaggedKeyForDelete (
  849. PWCHAR SrcNode
  850. )
  851. /*++
  852. Routine Description:
  853. Check if the Tagged deletion and noclobber rule should be applicable on this key.
  854. Arguments:
  855. SrcNode - Name of the node to be checked.
  856. Return Value:
  857. TRUE if the rule is applicable.
  858. FALSE otherwise.
  859. --*/
  860. {
  861. if ( wcsistr (SrcNode, L"Classes\\CLSID\\{") != NULL )
  862. return TRUE;
  863. if ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\CLSID\\{") != NULL )
  864. return TRUE;
  865. if ( ( wcsistr (SrcNode, L"Classes\\AppID\\{") != NULL ) ||
  866. ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\AppID\\{") != NULL ) )
  867. return TRUE;
  868. return FALSE;
  869. }
  870. BOOL
  871. IsExemptReflection (
  872. PWCHAR SrcNode
  873. )
  874. /*++
  875. Routine Description:
  876. Check if the is is on the exempt list from reflection.
  877. Arguments:
  878. SrcNode - Name of the node to be synced that need to be checked.
  879. Return Value:
  880. TRUE if the key is on the exempt list.
  881. FALSE otherwise.
  882. --*/
  883. {
  884. //
  885. // Use a static list.
  886. //
  887. if ( wcsistr (SrcNode, L"Classes\\Installer") != NULL )
  888. return TRUE;
  889. if ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\Installer") != NULL )
  890. return TRUE;
  891. return FALSE;
  892. }
  893. BOOL
  894. IsSpecialNode (
  895. PWCHAR SrcNode,
  896. BOOL *Flag,
  897. DWORD dwDirection,
  898. DWORD *pdwKeyType
  899. )
  900. /*++
  901. Routine Description:
  902. Check if the node need different treatment.
  903. Arguments:
  904. SrcNode - Name of the node to be synced.
  905. Flag - If this fall in the special node category this flag is set TRUE.
  906. dwDirection - SyncDitection
  907. DIRECTION_32_TO_64 - 32bit is the source of information
  908. DIRECTION_64_TO_32 - 32bit is the source of information
  909. Return Value:
  910. TRUE if the function succeed.
  911. FALSE otherwise.
  912. --*/
  913. {
  914. *Flag = FALSE;
  915. if ( wcsistr (SrcNode, L"Classes\\CLSID\\{") != NULL ) { //guid start with {
  916. *Flag = TRUE;
  917. ReflectClassGuid ( SrcNode, dwDirection);
  918. }
  919. if ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\CLSID\\{") != NULL ) {
  920. *Flag = TRUE;
  921. ReflectClassGuid ( SrcNode, dwDirection);
  922. }
  923. //
  924. // Always merge file association BUGBUG: See how bad it is.
  925. // Must handle special case runonce
  926. //
  927. if ( _wcsnicmp (SrcNode, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",75 ) == 0 ) { //75 is the size of the string
  928. *Flag = TRUE;
  929. //
  930. // HandleRunOnce (SrcNode);
  931. //
  932. }
  933. if ( wcsistr (SrcNode, L"Classes\\Installer") != NULL )
  934. *Flag = TRUE;
  935. if ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\Installer") != NULL )
  936. *Flag = TRUE;
  937. //if ( wcsistr (SrcNode, L"\\Classes\\Interface") != NULL )
  938. // *Flag = TRUE;
  939. //if ( wcsistr (SrcNode, L"\\Classes\\Wow6432Node\\Interface") != NULL )
  940. // *Flag = TRUE;
  941. //if (_wcsnicmp (SrcNode, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\TypeLib", sizeof (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\TypeLib")/2 -1)==0)
  942. // *Flag = TRUE;
  943. //if (_wcsnicmp (SrcNode, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\TypeLib", sizeof (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\TypeLib")/2 -1)==0)
  944. // *Flag = TRUE;
  945. if ( ( wcsistr (SrcNode, L"Classes\\AppID\\{") != NULL ) ||
  946. ( wcsistr (SrcNode, L"Classes\\Wow6432Node\\AppID\\{") != NULL ) ) {
  947. *pdwKeyType = DONT_SYNC_IF_DLL_SURROGATE;
  948. }
  949. return *Flag;
  950. }
  951. BOOL
  952. NtSyncNode (
  953. HANDLE hBase,
  954. PWCHAR AbsPath,
  955. BOOL bFlag
  956. )
  957. /*++
  958. Routine Description:
  959. Synchronize a tree based while closing a Key that was dirty.
  960. Arguments:
  961. hBase - Handle to the open Key.
  962. AbsPath - The original path application has created a key.
  963. bFlag - specify the sync property.
  964. Return Value:
  965. TRUE if the function succeed.
  966. FALSE otherwise.
  967. --*/
  968. {
  969. WCHAR DestNode[WOW64_MAX_PATH];
  970. WCHAR SrcNode[WOW64_MAX_PATH];
  971. BOOL bSpecialNode = FALSE;
  972. DWORD dwLen = WOW64_MAX_PATH;
  973. HKEY hRemap;
  974. HKEY hBaseNew;
  975. BOOL bRet;
  976. DWORD dwDirection;
  977. DWORD dwKeyType =0;
  978. //
  979. // If handle is null try to open the key on the otherside of the registry and pull that in.
  980. //
  981. if ( hBase != NULL ) {
  982. if (!HandleToKeyName ( hBase, SrcNode, &dwLen ))
  983. return FALSE;
  984. } else wcscpy (SrcNode, AbsPath);
  985. if (wcsistr (SrcNode, L"Wow6432Node") != NULL ) {
  986. dwDirection = DIRECTION_32_TO_64;
  987. Map32bitTo64bitKeyName ( SrcNode, DestNode );
  988. } else {
  989. dwDirection = DIRECTION_64_TO_32;
  990. Map64bitTo32bitKeyName ( SrcNode, DestNode );
  991. }
  992. //
  993. // check if both are the same
  994. //
  995. if (_wcsicmp ( SrcNode, DestNode ) == 0)
  996. return TRUE; //source and destination is the same
  997. //DbgPrint ("\nSyncing Node %S", SrcNode );
  998. if (! (bFlag & SKIP_SPECIAL_CASE ))
  999. if (IsSpecialNode ( SrcNode, &bSpecialNode, dwDirection, &dwKeyType )) //special rule is applicable here.
  1000. return TRUE;
  1001. hRemap = OpenNode (DestNode);
  1002. hBaseNew = OpenNode (SrcNode); // Open source in case user didn't open it with query priviledge.
  1003. if ( hRemap == NULL && (!( bFlag & DONT_CREATE_DEST_KEY)) ) { //check if you should create this node
  1004. //
  1005. // Always create unless GUID or .abc, then you need to do some additional check.
  1006. //
  1007. if ( CreateNode (DestNode)) {
  1008. hRemap = OpenNode (DestNode);
  1009. UpdateKeyTag ( hRemap, TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE);
  1010. }
  1011. }
  1012. //
  1013. // SyncValue only, delete all the value from destination and recopy.
  1014. // Generated Key will be reflected by create key.
  1015. //
  1016. if ( hBaseNew!= NULL && hRemap != NULL )
  1017. bRet = SyncValue (hBaseNew, hRemap, dwDirection, DEFAULT_FLAG | dwKeyType );
  1018. MyNtClose (hRemap); // Close the handle
  1019. MyNtClose (hBaseNew); // Close the NewHandle
  1020. return bRet;
  1021. //
  1022. // Check for existamce?
  1023. //
  1024. }
  1025. LONGLONG
  1026. CmpKeyTimeStamp (
  1027. HKEY hSrc,
  1028. HKEY hDest
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. Compare Key time stamp.
  1033. Arguments:
  1034. hSrc - handle to the src Key.
  1035. hDest - Handle to the dest Key.
  1036. Return Value:
  1037. 0 - if timestamp of hSrc == timestamp of hDest
  1038. >0 - if timestamp of hSrc > timestamp of hDest
  1039. <0 - if timestamp of hSrc < timestamp of hDest
  1040. FALSE otherwise.
  1041. --*/
  1042. {
  1043. NTSTATUS st= STATUS_SUCCESS;
  1044. DWORD Index=0, ResultLength;
  1045. LONGLONG TimeSrc=0;
  1046. LONGLONG TimeDest=0;
  1047. PKEY_BASIC_INFORMATION KeyInformation = NULL;
  1048. BYTE Buff [sizeof(KEY_BASIC_INFORMATION) + 256];
  1049. ULONG Length = sizeof(KEY_BASIC_INFORMATION) + 256;
  1050. KeyInformation = (PKEY_BASIC_INFORMATION)Buff;
  1051. st = NtQueryKey(
  1052. hSrc,
  1053. KeyBasicInformation,
  1054. KeyInformation,
  1055. Length,
  1056. &ResultLength
  1057. );
  1058. if(NT_SUCCESS (st))
  1059. TimeSrc = *(LONGLONG *)&KeyInformation->LastWriteTime;
  1060. st = NtQueryKey(
  1061. hDest,
  1062. KeyBasicInformation,
  1063. KeyInformation,
  1064. Length,
  1065. &ResultLength
  1066. );
  1067. if(NT_SUCCESS (st))
  1068. TimeDest = *(LONGLONG *)&KeyInformation->LastWriteTime;
  1069. if ( TimeDest == 0 || TimeSrc == 0)
  1070. return 0;
  1071. return TimeSrc - TimeDest;
  1072. }
  1073. BOOL
  1074. IsPresentLocalServerAppID (
  1075. PWCHAR KeyName,
  1076. PWCHAR pCLSID,
  1077. PWCHAR DestNode
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. Check if a GUID has localserver32 or AppID than should have been
  1082. reflected on the other side.
  1083. Arguments:
  1084. KeyName - Name of the key.
  1085. pCLDID - pointer to the end of CLSID
  1086. DestNode - Destination CLSID
  1087. Return Value:
  1088. TRUE if LocalSrever or AppID is there.
  1089. FALSE otherwise.
  1090. --*/
  1091. {
  1092. HKEY hKeyTemp = NULL;
  1093. DWORD Len = wcslen (DestNode);
  1094. PWCHAR pDest = DestNode+Len;
  1095. DWORD AttribSrc = 0;
  1096. DWORD AttribDest = TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE; //if key doesn't exist
  1097. HKEY hDest = NULL;
  1098. BYTE KeyBuffer[512];
  1099. DWORD KeyBufferSize = sizeof (KeyBuffer);
  1100. DWORD ResultLength;
  1101. UNICODE_STRING ValueName;
  1102. NTSTATUS Status;
  1103. HKEY hKey;
  1104. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL;
  1105. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyBuffer;
  1106. RtlInitUnicodeString (&ValueName, L"APPID");
  1107. wcscpy (pCLSID-1, L"\\LocalServer32");
  1108. hKeyTemp = OpenNode (KeyName);
  1109. if (hKeyTemp == NULL ) {
  1110. wcscpy (pCLSID-1, L"\\AppID");
  1111. hKeyTemp = OpenNode (KeyName);
  1112. if (hKeyTemp == NULL ) {
  1113. //
  1114. // Check APPID value key associated with the GUID.
  1115. //
  1116. *(pCLSID-1)= UNICODE_NULL;
  1117. hKeyTemp = OpenNode (KeyName);
  1118. if (hKeyTemp != NULL ) { // query for APPID
  1119. Status = NtQueryValueKey(
  1120. hKeyTemp,
  1121. &ValueName,
  1122. KeyValuePartialInformation,
  1123. KeyValueInformation,
  1124. KeyBufferSize,
  1125. &ResultLength);
  1126. if (!NT_SUCCESS (Status)) {
  1127. MyNtClose(hKeyTemp);
  1128. return FALSE;
  1129. }
  1130. *pDest = UNICODE_NULL;
  1131. hDest = OpenNode (DestNode);
  1132. }
  1133. }
  1134. wcscpy (pDest, L"\\AppID");
  1135. hDest = OpenNode (DestNode);
  1136. *pDest = UNICODE_NULL;
  1137. }else {
  1138. wcscpy (pDest, L"\\LocalServer32");
  1139. hDest = OpenNode (DestNode);
  1140. *pDest = UNICODE_NULL;
  1141. }
  1142. QueryKeyTag (hKeyTemp, &AttribSrc);
  1143. QueryKeyTag (hDest, &AttribDest);
  1144. MyNtClose (hDest);
  1145. MyNtClose (hKeyTemp);
  1146. //
  1147. // if atleast one is a reflected Key then sync value
  1148. //
  1149. if ( (AttribSrc & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) ||
  1150. (AttribDest & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) ) // reflector touched this Key
  1151. return TRUE;
  1152. return FALSE; //Yepp ID is present and the guid can be reflected
  1153. }
  1154. BOOL
  1155. ReflectClassGuid (
  1156. PWCHAR SrcName,
  1157. DWORD dwDirection
  1158. )
  1159. /*++
  1160. Routine Description:
  1161. Synchronize a two node with value Key. Delete from the RemapKey, and copy from Base
  1162. Arguments:
  1163. SrcName - Name of the key on CLSID path.
  1164. dwDirection - SyncDitection
  1165. DIRECTION_32_TO_64 - 32bit is the source of information
  1166. DIRECTION_64_TO_32 - 32bit is the source of information
  1167. Return Value:
  1168. TRUE if the function succeed.
  1169. FALSE otherwise.
  1170. --*/
  1171. {
  1172. PWCHAR pCLSID;
  1173. DWORD dwLen;
  1174. WCHAR KeyName[256]; //You don't need this big Key for CLSID
  1175. WCHAR DestNode[256];
  1176. HANDLE hKeyTemp;
  1177. HANDLE hSrc;
  1178. HANDLE hDest;
  1179. BOOL bNewlyCreated = FALSE;
  1180. //
  1181. // If Localserver is present for that key, sync from the CLSID.
  1182. //
  1183. pCLSID = wcsistr (SrcName, L"\\CLSID\\{");
  1184. if ( pCLSID == NULL )
  1185. return TRUE;
  1186. wcscpy (KeyName, SrcName );
  1187. pCLSID = &KeyName[(DWORD)(pCLSID - SrcName)];
  1188. pCLSID +=7; // point start of guid {
  1189. // Sanity Check and will be good enough????
  1190. if ( pCLSID[9] != L'-' || pCLSID[14] != L'-' || pCLSID[19] != L'-' ||
  1191. pCLSID[24] != L'-' || pCLSID[37] != L'}' )
  1192. return FALSE;
  1193. //DbgPrint ("\nTrying to sync GUID %S", SrcName);
  1194. //
  1195. // Initially sync the Key first in case time stamp is same because of resolution.
  1196. // Cey Creation will be done while syncing Key from GUID
  1197. //
  1198. pCLSID +=39;
  1199. if ( *(pCLSID-1) != UNICODE_NULL ) { //check if following is applicable.
  1200. if ( _wcsnicmp (pCLSID, L"InprocServer32", 14) == 0 ) //Skip Inproc server
  1201. return TRUE;
  1202. if ( _wcsnicmp (pCLSID, L"InprocHandler32", 15) == 0 ) {//Check InprocHandler
  1203. if (!ReflectInprocHandler32KeyByName (KeyName))
  1204. return TRUE;
  1205. }
  1206. }
  1207. //
  1208. // Get other path.
  1209. //
  1210. *(pCLSID-1)= UNICODE_NULL; // Make path only to the GUID
  1211. if ( dwDirection == DIRECTION_32_TO_64 )
  1212. Map32bitTo64bitKeyName ( KeyName, DestNode ); //get 64bit side //BUGBUG: you can optimize this
  1213. else if ( dwDirection == DIRECTION_64_TO_32 )
  1214. Map64bitTo32bitKeyName ( KeyName, DestNode ); //get 32bit side
  1215. //
  1216. // If the other hive has InProcHandler ignore this reflection rule
  1217. // After Beta1 or apply by Tag
  1218. //
  1219. if ( !IsPresentLocalServerAppID (KeyName, pCLSID, DestNode) )
  1220. return TRUE;
  1221. //
  1222. // Now time to reflect everything except InprocServer32
  1223. //
  1224. pCLSID--;
  1225. pCLSID[0]= UNICODE_NULL; // Make path only to the GUID
  1226. hSrc = OpenNode (KeyName);
  1227. if (hSrc == NULL )
  1228. return TRUE;
  1229. hDest = OpenNode (DestNode);
  1230. if ( hDest == NULL ) {
  1231. CreateNode (DestNode);
  1232. hDest = OpenNode (DestNode);
  1233. if (hDest != NULL) {
  1234. UpdateKeyTag ( hDest, TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE);
  1235. bNewlyCreated = TRUE;
  1236. SyncValue ( hSrc, hDest, dwDirection, 0);
  1237. }
  1238. }
  1239. if (hDest != NULL && hSrc != NULL) {
  1240. //
  1241. // Sync Value on current Node
  1242. //
  1243. //if ( !bNewlyCreated ) {
  1244. //
  1245. // if destination is a copy then update this.
  1246. //
  1247. DWORD Attrib1=0;
  1248. DWORD Attrib2=0;
  1249. HKEY hSrcKey1;
  1250. HKEY hDestKey1;
  1251. if ( dwDirection == DIRECTION_32_TO_64 )
  1252. Map32bitTo64bitKeyName ( SrcName, DestNode ); //get 64bit side //BUGBUG: you can optimize this
  1253. else if ( dwDirection == DIRECTION_64_TO_32 )
  1254. Map64bitTo32bitKeyName ( SrcName, DestNode ); //get 32bit side
  1255. hSrcKey1 = OpenNode (SrcName);
  1256. hDestKey1 = OpenNode (DestNode);
  1257. if ( hSrcKey1 != NULL && hDestKey1 != NULL ) //if dest isn't reflected key should you merge?
  1258. //
  1259. // 64bit Local Server might get priority
  1260. //
  1261. SyncValue ( hSrcKey1, hDestKey1, dwDirection, SYNC_VALUE_IF_REFLECTED_KEYS);
  1262. MyNtClose ( hSrcKey1 );
  1263. MyNtClose ( hDestKey1 );
  1264. //}
  1265. SyncGuidKey (hSrc, hDest, dwDirection, FALSE );
  1266. }
  1267. MyNtClose (hDest);
  1268. MyNtClose (hSrc);
  1269. return TRUE;
  1270. }
  1271. BOOL
  1272. SyncGuidKey (
  1273. HANDLE hSrc,
  1274. HANDLE hDest,
  1275. DWORD dwDirection,
  1276. DWORD __bNewlyCreated
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. Synchronize a two CLSID Node.
  1281. Arguments:
  1282. hSrc - Handle to Source Class GUID.
  1283. hDest - Handle to dest Class GUID.
  1284. dwDirection - SyncDitection
  1285. DIRECTION_32_TO_64 - 32bit is the source of information
  1286. DIRECTION_64_TO_32 - 32bit is the source of information
  1287. __bNewlyCreated - if the destination is just created.
  1288. Return Value:
  1289. TRUE if the function succeed.
  1290. FALSE otherwise.
  1291. --*/
  1292. {
  1293. //
  1294. // Enumerate every key under src and recursively copy that except InProcServer32
  1295. //
  1296. HANDLE hSrcNew;
  1297. HANDLE hDestNew;
  1298. OBJECT_ATTRIBUTES Obja;
  1299. NTSTATUS st= STATUS_SUCCESS;
  1300. DWORD Index=0;
  1301. LONGLONG TimeDiff;
  1302. BOOL bNewlyCreated = FALSE;
  1303. DWORD ResultLength;
  1304. UNICODE_STRING UnicodeKeyName;
  1305. PKEY_NODE_INFORMATION KeyInformation = NULL;
  1306. BYTE Buff [sizeof(KEY_NODE_INFORMATION) + 256];
  1307. DWORD Length = sizeof (Buff);
  1308. KeyInformation = (PKEY_NODE_INFORMATION)Buff;
  1309. //
  1310. // Sync Value first.
  1311. //
  1312. //TimeDiff = CmpKeyTimeStamp ( hSrc, hDest );
  1313. //if (TimeDiff > 0 || __bNewlyCreated ) { //for newnly created key always merge.
  1314. if (__bNewlyCreated ) { //for newnly created key always merge.
  1315. SyncValue ( hSrc, hDest, dwDirection, DEFAULT_FLAG);
  1316. //LogMsg (hSrc, L"Copy Guid Keys..");
  1317. }
  1318. //
  1319. // Enumerate all key from the hRemap and delete.
  1320. //
  1321. for (Index=0;;Index++) {
  1322. st = NtEnumerateKey(
  1323. hSrc,
  1324. Index,
  1325. KeyNodeInformation,
  1326. KeyInformation,
  1327. Length,
  1328. &ResultLength
  1329. );
  1330. if (!NT_SUCCESS(st))
  1331. break;
  1332. KeyInformation->Name[KeyInformation->NameLength/2] = UNICODE_NULL;
  1333. RtlInitUnicodeString( &UnicodeKeyName, KeyInformation->Name );
  1334. if (_wcsnicmp (KeyInformation->Name, L"InprocServer32", 14) == 0 ) //Skip Inproc server
  1335. continue;
  1336. InitializeObjectAttributes (&Obja, &UnicodeKeyName, OBJ_CASE_INSENSITIVE, hSrc, NULL );
  1337. //
  1338. // Open source key on the Source Side;
  1339. //
  1340. st = NtOpenKey (&hSrcNew, KEY_ALL_ACCESS, &Obja);
  1341. if (!NT_SUCCESS(st))
  1342. continue;
  1343. if (_wcsnicmp (KeyInformation->Name, L"InprocHandler32", 15) == 0 ) {//Check InprocHandler
  1344. if (!ReflectInprocHandler32KeyByHandle (hSrcNew)) {
  1345. NtClose (hSrcNew);
  1346. continue;
  1347. }
  1348. }
  1349. //
  1350. // Create or open the key on the dest side.
  1351. //
  1352. InitializeObjectAttributes (&Obja, &UnicodeKeyName, OBJ_CASE_INSENSITIVE, hDest, NULL );
  1353. bNewlyCreated = FALSE;
  1354. st = NtOpenKey (&hDestNew, KEY_ALL_ACCESS, &Obja);
  1355. if (!NT_SUCCESS(st)) {
  1356. //
  1357. // Try to create the key here
  1358. //
  1359. st = NtCreateKey(
  1360. &hDestNew,
  1361. KEY_ALL_ACCESS,
  1362. &Obja,
  1363. 0,
  1364. NULL ,
  1365. REG_OPTION_NON_VOLATILE,
  1366. NULL
  1367. );
  1368. if (!NT_SUCCESS(st)) {
  1369. NtClose (hSrcNew);
  1370. continue;
  1371. }
  1372. bNewlyCreated = TRUE;
  1373. UpdateKeyTag ( hDestNew, TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE );
  1374. }
  1375. //
  1376. // Sync only when Key is created.
  1377. //
  1378. SyncGuidKey ( hSrcNew, hDestNew, dwDirection, bNewlyCreated );
  1379. NtClose (hSrcNew);
  1380. NtClose (hDestNew);
  1381. }
  1382. return TRUE;
  1383. }
  1384. BOOL
  1385. SyncKeysOnBoot ( )
  1386. /*++
  1387. Routine Description:
  1388. Sync Certain Keys on Boot.
  1389. We don't have any particular list or way to figure it out what need to be synced but this
  1390. can be extended as request comes.
  1391. Arguments:
  1392. None.
  1393. Return Value:
  1394. TRUE on success.
  1395. FALSE otherwise.
  1396. --*/
  1397. {
  1398. //
  1399. // Sync some setup information here.
  1400. //
  1401. HKEY hSrc;
  1402. HKEY hDest;
  1403. BOOL bRet = FALSE;
  1404. if ( (hSrc = OpenNode (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion")) == NULL)
  1405. return FALSE;
  1406. if ( (hDest = OpenNode (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion")) == NULL) {
  1407. NtClose (hSrc);
  1408. return FALSE;
  1409. }
  1410. bRet = SyncValue ( hSrc, hDest, DIRECTION_64_TO_32, DONT_DELETE_DEST_VALUEKEY );
  1411. NtClose (hSrc);
  1412. NtClose (hDest);
  1413. return bRet;
  1414. }
  1415. BOOL
  1416. Wow64SyncCLSID ()
  1417. /*++
  1418. Routine Description:
  1419. Synchronize CLSID on the machine hive.
  1420. Algorithm:
  1421. 1. Enumerate all guid on 64bit side, if the guid has the local
  1422. server and the other side don't have the guid, sync this.
  1423. 2. Apply the same rule for 32bit side as well.
  1424. 3. This is only applicable for machine hives only.
  1425. 4. This function will run at the end of setup once to sync some guid.
  1426. Arguments:
  1427. None.
  1428. Return Value:
  1429. TRUE if the function succeed.
  1430. FALSE otherwise.
  1431. --*/
  1432. {
  1433. //
  1434. // Enumerate every key under src and recursively copy that except InProcServer32
  1435. //
  1436. HANDLE hSrc;
  1437. HANDLE hSrcTemp;
  1438. HANDLE hSrcNew;
  1439. HANDLE hDestNew;
  1440. OBJECT_ATTRIBUTES Obja;
  1441. WCHAR Path [256];
  1442. NTSTATUS st= STATUS_SUCCESS;
  1443. DWORD Index=0;
  1444. DWORD ResultLength;
  1445. UNICODE_STRING UnicodeKeyName;
  1446. PKEY_NODE_INFORMATION KeyInformation = NULL;
  1447. BYTE Buff [sizeof(KEY_NODE_INFORMATION) + 256];
  1448. DWORD Length = sizeof (Buff);
  1449. DWORD dwDirection = DIRECTION_64_TO_32;
  1450. KeyInformation = (PKEY_NODE_INFORMATION)Buff;
  1451. for (;;) {
  1452. if ( dwDirection == DIRECTION_64_TO_32 )
  1453. hSrc = OpenNode (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID");
  1454. else hSrc = OpenNode (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\CLSID");
  1455. //
  1456. // Enumerate all key from the hRemap and delete.
  1457. //
  1458. for (Index=0;;Index++) {
  1459. st = NtEnumerateKey(
  1460. hSrc,
  1461. Index,
  1462. KeyNodeInformation,
  1463. KeyInformation,
  1464. Length,
  1465. &ResultLength
  1466. );
  1467. if (!NT_SUCCESS(st))
  1468. break;
  1469. KeyInformation->Name[KeyInformation->NameLength/2] = UNICODE_NULL;
  1470. wcscpy (Path, KeyInformation->Name);
  1471. wcscat ( Path,L"\\LocalServer32");
  1472. RtlInitUnicodeString( &UnicodeKeyName, Path );
  1473. InitializeObjectAttributes (&Obja, &UnicodeKeyName, OBJ_CASE_INSENSITIVE, hSrc, NULL );
  1474. //
  1475. // Open source key on the Source Side;
  1476. //
  1477. st = NtOpenKey (&hSrcTemp, KEY_READ, &Obja);
  1478. if (!NT_SUCCESS(st)) { // Local Server Key doesn't exist
  1479. wcscpy (Path, KeyInformation->Name);
  1480. wcscat ( Path,L"\\AppID");
  1481. RtlInitUnicodeString( &UnicodeKeyName, Path );
  1482. InitializeObjectAttributes (&Obja, &UnicodeKeyName, OBJ_CASE_INSENSITIVE, hSrc, NULL );
  1483. st = NtOpenKey (&hSrcTemp, KEY_READ, &Obja);
  1484. if (!NT_SUCCESS(st)) // AppID Key doesn't exist
  1485. continue;
  1486. else NtClose (hSrcTemp);
  1487. } else NtClose (hSrcTemp);
  1488. //
  1489. // Check if the guid exists on the other side, if so continue.
  1490. //
  1491. if ( dwDirection == DIRECTION_64_TO_32 )
  1492. wcscpy (Path,L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\CLSID\\");
  1493. else
  1494. wcscpy (Path,L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\");
  1495. wcscat (Path,KeyInformation->Name );
  1496. hSrcTemp = OpenNode (Path);
  1497. if (hSrcTemp != NULL ) {
  1498. NtClose (hSrcTemp );
  1499. continue;
  1500. }
  1501. //
  1502. // Create or open the key on the dest side.
  1503. //
  1504. if ( !CreateNode (Path))
  1505. continue;
  1506. if ( (hDestNew = OpenNode (Path))==NULL)
  1507. continue;
  1508. UpdateKeyTag ( hDestNew, TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE ); //Mark the key as reflected.
  1509. RtlInitUnicodeString( &UnicodeKeyName, KeyInformation->Name );
  1510. InitializeObjectAttributes (&Obja, &UnicodeKeyName, OBJ_CASE_INSENSITIVE, hSrc, NULL );
  1511. st = NtOpenKey (&hSrcNew, KEY_ALL_ACCESS, &Obja);
  1512. if (!NT_SUCCESS(st)) {
  1513. NtClose (hDestNew);
  1514. continue;
  1515. }
  1516. SyncGuidKey ( hSrcNew, hDestNew, dwDirection, 1);
  1517. NtClose (hSrcNew);
  1518. NtClose (hDestNew);
  1519. } //for-loop enumeration all guids
  1520. NtClose ( hSrc );
  1521. if (DIRECTION_32_TO_64 == dwDirection)
  1522. break;
  1523. if (dwDirection == DIRECTION_64_TO_32 )
  1524. dwDirection = DIRECTION_32_TO_64;
  1525. } //for loop for direction
  1526. SyncKeysOnBoot (); //sync some special value keys
  1527. return TRUE;
  1528. }
  1529. VOID
  1530. PatchPathOnValueKey (
  1531. ULONG DataSize,
  1532. ULONG Type,
  1533. WCHAR *Data,
  1534. WCHAR *RetDataBuff,
  1535. ULONG *pCorrectDataSize
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. Patch the value key while writing on the 32bit side.
  1540. Arguments:
  1541. DataSize - Size of data in byte in the buffer.
  1542. Type - registry value type.
  1543. Data - data buffer.
  1544. RetDataBuffer - will contain the patched value.
  1545. pCorrectDataSide - Will have the updated size.
  1546. Return Value:
  1547. TRUE if the function succeed.
  1548. FALSE otherwise.
  1549. --*/
  1550. {
  1551. WCHAR ThunkData[256];
  1552. PWCHAR pCorrectData = (PWCHAR)Data;
  1553. *pCorrectDataSize = DataSize;
  1554. //
  1555. // thunk %ProgramFiles% ==> %ProgramFiles(x86)%
  1556. // %commonprogramfiles% ==> %commonprogramfiles(x86)%
  1557. //
  1558. if (DataSize < ( sizeof (ThunkData) - 10) && (Type == REG_SZ || Type == REG_EXPAND_SZ ) ) { //(x86)==>10 byte
  1559. //
  1560. // do the thunking here.
  1561. //
  1562. PWCHAR p;
  1563. PWCHAR t;
  1564. memcpy ( (PBYTE ) &ThunkData[0], (PBYTE)Data, DataSize);
  1565. ThunkData [DataSize/sizeof (WCHAR) ] = UNICODE_NULL; // make sure NULL terminated
  1566. if ( (p = wcsistr (ThunkData, L"%ProgramFiles%" )) != NULL ){
  1567. p +=13; //skip at the end of %ProgramFiles
  1568. } else if ( (p = wcsistr (ThunkData, L"%commonprogramfiles%")) != NULL ){
  1569. p +=19; //skip at the end of %commonprogramfiles
  1570. }
  1571. if (p) {
  1572. t = pCorrectData + (p - ThunkData);
  1573. wcscpy(p, L"(x86)"); //(x86)
  1574. wcscat(p, t); //copy rest of the string
  1575. pCorrectData = ThunkData;
  1576. *pCorrectDataSize += sizeof (L"(x86)");
  1577. }
  1578. } //if if (DataSize < ( _MAX_PATH
  1579. if ( pCorrectData == ThunkData )
  1580. memcpy ( RetDataBuff, pCorrectData, *pCorrectDataSize );
  1581. }
  1582. BOOL
  1583. Wow64RegDeleteKey (
  1584. HKEY hBase,
  1585. WCHAR *SubKey
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Delete mirror Key.
  1590. Arguments:
  1591. hBase - handle to the base key.
  1592. SubKey - Name of the subkey to be deleted.
  1593. Return Value:
  1594. TRUE if the key is on the list of reflection.
  1595. FALSE otherwise.
  1596. --*/
  1597. {
  1598. //
  1599. // 1. Get the complete path to base.
  1600. // 2. Get Check if the key exist on the reflection list.
  1601. // 3. Delete the mirror.
  1602. //
  1603. WCHAR SrcNode[WOW64_MAX_PATH];
  1604. WCHAR KeyName[WOW64_MAX_PATH];
  1605. PWCHAR pCLSID;
  1606. BOOL bSpecialNode = FALSE;
  1607. DWORD dwLen = WOW64_MAX_PATH;
  1608. HKEY hRemap;
  1609. DWORD dwDirection;
  1610. NTSTATUS St;
  1611. DWORD AttributeMirrorKey;
  1612. InitHandleTable (); //initialize if its already not initialized.
  1613. if (!bReflectorStatusOn)
  1614. return TRUE; //reflector isn't enable yet.
  1615. if ( hBase == NULL)
  1616. wcscpy ( SrcNode, SubKey);
  1617. else if (!HandleToKeyName ( hBase, SrcNode, &dwLen ))
  1618. return FALSE;
  1619. if (SubKey != NULL && hBase != NULL) { // wow64 will call with null subkey
  1620. if (*SubKey != L'\\')
  1621. wcscat (SrcNode, L"\\");
  1622. wcscat (SrcNode, SubKey );
  1623. }
  1624. //
  1625. // If it's guid then dest mustnot have InprocServer.
  1626. //
  1627. /*
  1628. pCLSID = wcsistr (SrcNode, L"\\CLSID\\{");
  1629. if ( pCLSID != NULL ) {
  1630. HKEY hKeyTemp;
  1631. wcscpy (KeyName, SrcNode );
  1632. pCLSID = &KeyName[(DWORD)(pCLSID - SrcNode)];
  1633. pCLSID +=7; // point start of guid {
  1634. // Sanity Check and will be good enough????
  1635. if (!( pCLSID[9] != L'-' || pCLSID[14] != L'-' || pCLSID[19] != L'-' ||
  1636. pCLSID[24] != L'-' || pCLSID[37] != L'}' ) ) {
  1637. //DbgPrint ("\nTrying to sync GUID %S", SrcName);
  1638. pCLSID +=38;
  1639. wcscpy (pCLSID, L"\\InprocServer32");
  1640. hKeyTemp = OpenNode (KeyName);
  1641. if (hKeyTemp != NULL ) {
  1642. MyNtClose (hKeyTemp);
  1643. return TRUE; // Shouldn't detele InprocSrver32
  1644. }
  1645. wcscpy (pCLSID, L"\\InprocHandler32");
  1646. hKeyTemp = OpenNode (KeyName);
  1647. if (hKeyTemp != NULL ) {
  1648. MyNtClose (hKeyTemp);
  1649. return TRUE; // Shouldn't delete InprocHandler
  1650. }
  1651. } // if initial guid check succeed
  1652. } // if \CLSID\{ is there
  1653. */
  1654. //
  1655. // The other Key has already been deleted. You can delete this or wait.
  1656. //
  1657. if ( TaggedKeyForDelete (SrcNode) ) {
  1658. DWORD Attrib1 = 0;
  1659. QueryKeyTag (hBase, &Attrib1);
  1660. //*** finetune the rule remove key only with reflected tag.
  1661. //if (!( (Attrib1 & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) ||
  1662. // (AttributeMirrorKey & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE) )) // reflector touched this Key
  1663. // return TRUE; // One key must have reflected tag to be deleted.
  1664. if (!(Attrib1 & TAG_KEY_ATTRIBUTE_REFLECTOR_WRITE))
  1665. return TRUE; // the isn't tagged as reflected.
  1666. }
  1667. //
  1668. // Delete the key here
  1669. //
  1670. St = NtDeleteKey( hBase );
  1671. return TRUE;
  1672. //
  1673. // Check for existamce?
  1674. //
  1675. }
  1676. BOOL
  1677. Wow64ReflectSecurity (
  1678. HKEY SrcKey,
  1679. HKEY DestKey
  1680. )
  1681. /*++
  1682. Routine Description:
  1683. Copy security attribute from SrcKey to DestKey.
  1684. Arguments:
  1685. SrcKey - Handle to a key..
  1686. DestKey - handle to the destination key.
  1687. Return Value:
  1688. TRUE if operation succeeded.
  1689. FALSE otherwise.
  1690. --*/
  1691. {
  1692. NTSTATUS Status;
  1693. PSECURITY_DESCRIPTOR SD;
  1694. BYTE Buffer[2048]; // reflector only manages general purpose keys and will have smaller ACL
  1695. LONG Ret, Len;
  1696. LONG BufferLen = sizeof (Buffer);
  1697. DWORD Count = 0;
  1698. SD = (PSECURITY_DESCRIPTOR)Buffer;
  1699. Len = BufferLen;
  1700. Status = NtQuerySecurityObject(
  1701. SrcKey,
  1702. DACL_SECURITY_INFORMATION,
  1703. SD,
  1704. Len,
  1705. &Len
  1706. );
  1707. if ( NT_SUCCESS (Status ))
  1708. Status = NtSetSecurityObject(
  1709. DestKey,
  1710. DACL_SECURITY_INFORMATION,
  1711. SD
  1712. );
  1713. Len = BufferLen;
  1714. Status = NtQuerySecurityObject(
  1715. SrcKey,
  1716. GROUP_SECURITY_INFORMATION,
  1717. SD,
  1718. Len,
  1719. &Len
  1720. );
  1721. if ( NT_SUCCESS (Status ))
  1722. Status = NtSetSecurityObject(
  1723. DestKey,
  1724. GROUP_SECURITY_INFORMATION,
  1725. SD
  1726. );
  1727. Len = BufferLen;
  1728. Status = NtQuerySecurityObject(
  1729. SrcKey,
  1730. OWNER_SECURITY_INFORMATION,
  1731. SD,
  1732. Len,
  1733. &Len
  1734. );
  1735. if ( NT_SUCCESS (Status ))
  1736. Status = NtSetSecurityObject(
  1737. DestKey,
  1738. OWNER_SECURITY_INFORMATION,
  1739. SD
  1740. );
  1741. Len = BufferLen;
  1742. Status = NtQuerySecurityObject(
  1743. SrcKey,
  1744. SACL_SECURITY_INFORMATION,
  1745. SD,
  1746. Len,
  1747. &Len
  1748. );
  1749. if ( NT_SUCCESS (Status ))
  1750. Status = NtSetSecurityObject(
  1751. DestKey,
  1752. SACL_SECURITY_INFORMATION,
  1753. SD
  1754. );
  1755. return TRUE;
  1756. }
  1757. BOOL
  1758. IsOnReflectionByHandle (
  1759. HKEY KeyHandle
  1760. )
  1761. /*++
  1762. Routine Description:
  1763. Check if the key specified by a handle sit on the list of keys of reflection.
  1764. Arguments:
  1765. KeyHandle - Handle to a key..
  1766. Return Value:
  1767. TRUE if the key sit on the the list of reflection.
  1768. FALSE otherwise.
  1769. --*/
  1770. {
  1771. WCHAR SrcNode[WOW64_MAX_PATH];
  1772. DWORD dwLen = WOW64_MAX_PATH;
  1773. InitHandleTable (); //initialize if its already not initialized.
  1774. if (!bReflectorStatusOn)
  1775. return FALSE; //reflector isn't enable yet.
  1776. if ( KeyHandle == NULL)
  1777. return FALSE;
  1778. else if (!HandleToKeyName ( KeyHandle, SrcNode, &dwLen ))
  1779. return FALSE;
  1780. return IsOnReflectionList (SrcNode);
  1781. }
  1782. HKEY
  1783. Wow64OpenRemappedKeyOnReflection (
  1784. HKEY SrcKey
  1785. )
  1786. /*++
  1787. Routine Description:
  1788. Called from advapi to get an handle to remapped key that is on reflection list.
  1789. Arguments:
  1790. SrcKey - Handle to a key..
  1791. Return Value:
  1792. Valid handle to the reflected key.
  1793. NULL if the function fails.
  1794. --*/
  1795. {
  1796. PWCHAR DestNode;
  1797. PWCHAR SrcNode;
  1798. BOOL bSpecialNode = FALSE;
  1799. DWORD dwLen = WOW64_MAX_PATH;
  1800. HKEY hRemap;
  1801. NTSTATUS St;
  1802. DestNode = RegRemapAlloc (WOW64_MAX_PATH);
  1803. SrcNode = RegRemapAlloc (WOW64_MAX_PATH);
  1804. if ( NULL == DestNode || NULL == SrcNode ) {
  1805. RegRemapFree ( DestNode );
  1806. RegRemapFree ( SrcNode );
  1807. return NULL;
  1808. }
  1809. InitHandleTable (); //initialize if its already not initialized.
  1810. if (!bReflectorStatusOn) {
  1811. RegRemapFree ( DestNode );
  1812. RegRemapFree ( SrcNode );
  1813. return NULL; //reflector isn't enable yet.
  1814. }
  1815. if ( SrcKey == NULL) {
  1816. RegRemapFree ( DestNode );
  1817. RegRemapFree ( SrcNode );
  1818. return NULL;
  1819. }
  1820. else if (!HandleToKeyName ( SrcKey, SrcNode, &dwLen )) {
  1821. RegRemapFree ( DestNode );
  1822. RegRemapFree ( SrcNode );
  1823. return NULL;
  1824. }
  1825. if ( !IsOnReflectionList (SrcNode)) {
  1826. RegRemapFree ( DestNode );
  1827. RegRemapFree ( SrcNode );
  1828. return NULL;
  1829. }
  1830. if (wcsistr (SrcNode, L"Wow6432Node") != NULL ) {
  1831. Map32bitTo64bitKeyName ( SrcNode, DestNode );
  1832. } else {
  1833. Map64bitTo32bitKeyName ( SrcNode, DestNode );
  1834. }
  1835. //
  1836. // check if both are the same
  1837. //
  1838. if (_wcsicmp ( SrcNode, DestNode ) == 0) {
  1839. RegRemapFree ( DestNode );
  1840. RegRemapFree ( SrcNode );
  1841. return NULL; //source and destination is the same
  1842. }
  1843. //
  1844. // Must check the special case, Like Installer/file association....
  1845. //
  1846. if ( IsExemptReflection ( SrcNode )) {
  1847. RegRemapFree ( DestNode );
  1848. RegRemapFree ( SrcNode );
  1849. return NULL;
  1850. }
  1851. if ( (hRemap = OpenNode (DestNode) ) == NULL ){
  1852. RegRemapFree ( DestNode );
  1853. RegRemapFree ( SrcNode );
  1854. return NULL;
  1855. }
  1856. RegRemapFree ( DestNode );
  1857. RegRemapFree ( SrcNode );
  1858. return hRemap;
  1859. }
  1860. void
  1861. InitializeWow64OnBoot(
  1862. DWORD dwFlag
  1863. )
  1864. /*++
  1865. Routine Description:
  1866. Called from advapi to get an handle to remapped key that is on reflection list.
  1867. Arguments:
  1868. dwFlag - define the point where this function were invoked.
  1869. 1- means were invoked from csr service
  1870. 2- means this were invoked by setup.
  1871. Return Value:
  1872. None.
  1873. --*/
  1874. {
  1875. DWORD Ret;
  1876. HKEY Key;
  1877. NTSTATUS st;
  1878. OBJECT_ATTRIBUTES Obja;
  1879. UNICODE_STRING KeyName;
  1880. RtlInitUnicodeString (&KeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Classes");
  1881. InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
  1882. st = NtOpenKey (&Key, KEY_ALL_ACCESS, &Obja);
  1883. if (NT_SUCCESS(st)) {
  1884. st = NtDeleteKey (Key);
  1885. NtClose (Key);
  1886. }
  1887. RtlInitUnicodeString (&KeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Classes");
  1888. InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
  1889. st = NtCreateKey(
  1890. &Key,
  1891. KEY_ALL_ACCESS | KEY_CREATE_LINK,
  1892. &Obja,
  1893. 0,
  1894. NULL ,
  1895. REG_OPTION_NON_VOLATILE | REG_OPTION_OPEN_LINK | REG_OPTION_CREATE_LINK, // special options flag
  1896. NULL
  1897. );
  1898. if (NT_SUCCESS(st)) {
  1899. RtlInitUnicodeString (&KeyName, L"SymbolicLinkValue");
  1900. st = NtSetValueKey(
  1901. Key,
  1902. &KeyName,
  1903. 0 ,
  1904. REG_LINK,
  1905. (PBYTE)WOW64_32BIT_MACHINE_CLASSES_ROOT,
  1906. (DWORD ) (wcslen (WOW64_32BIT_MACHINE_CLASSES_ROOT) * sizeof (WCHAR))
  1907. );
  1908. NtClose(Key);
  1909. if ( !NT_SUCCESS(st) ) {
  1910. #if DBG
  1911. DbgPrint ( "Wow64-InitializeWow64OnBoot: Couldn't create symbolic link%S\n", WOW64_32BIT_MACHINE_CLASSES_ROOT);
  1912. #endif
  1913. return;
  1914. }
  1915. }
  1916. return;
  1917. }
  1918. #ifdef _ADVAPI32_
  1919. WINADVAPI
  1920. LONG
  1921. APIENTRY
  1922. Wow64Win32ApiEntry (
  1923. DWORD dwFuncNumber,
  1924. DWORD dwFlag,
  1925. DWORD dwRes
  1926. )
  1927. /*++
  1928. Routine Description:
  1929. This is a generic API exported through adavpi32.dll. Just changing the function number
  1930. More functionality can be added in the future if needed.
  1931. Arguments:
  1932. dwFuncNumber - desired function number. 1 means enable/disable reflection.
  1933. dwFlag - set properties of the function entry. if Function number is 1 flag might be one of them.
  1934. WOW64_REFLECTOR_ENABLE - enable reflection.
  1935. WOW64_REFLECTOR_ENABLE - Disable reflection.
  1936. dwRes - for future uses. set to 0.
  1937. Return Value:
  1938. None.
  1939. --*/
  1940. {
  1941. if (dwFuncNumber == 1) {
  1942. if (dwFlag & WOW64_REFLECTOR_ENABLE )
  1943. bReflectorStatusOn = TRUE;
  1944. else if (dwFlag & WOW64_REFLECTOR_DISABLE )
  1945. bReflectorStatusOn = FALSE;
  1946. }
  1947. return 0;
  1948. }
  1949. #endif