Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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