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.

2200 lines
53 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. This module will do the necessary things to setup initial registry for the redirection
  7. purpose.
  8. //
  9. // Test case scenario
  10. // 1. Open a ISN node and list content
  11. // 2. Create a ISN node do 1.
  12. // 3. Open a non ISN node and list
  13. // 4. Create a non ISN node and list content
  14. //
  15. Outstanding issue:
  16. reflector: If Key has been created on one side, we can reflect that on the other side.
  17. Deletion: Without any additional attribute it's impossible to track.
  18. Author:
  19. ATM Shafiqul Khalid (askhalid) 18-Nov-1999
  20. Revision History:
  21. --*/
  22. #include <windows.h>
  23. #include <windef.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "wow64reg.h"
  27. #include <assert.h>
  28. #include "reflectr.h"
  29. VOID
  30. DbgPrint(
  31. PCHAR FormatString,
  32. ...
  33. );
  34. #define REFLECTOR_ENABLE_KEY L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\WOW64\\Reflector Setup"
  35. ISN_NODE_TYPE ReflectorTableStatic[ISN_NODE_MAX_NUM]={
  36. { { L"REFLECT1"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes"},0 }, // alias to the classes root on the user hives
  37. //{ { L"REFLECT2"}, {L"\\REGISTRY\\USER\\*\\Software\\Classes"},0 }, // the first '*' is the user's SID
  38. { { L"REFLECT3"}, {L"\\REGISTRY\\USER\\*_Classes"},0 }, // alias to the classes root on the user hives
  39. { { L"REFLECT4"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"},0 }, // Runonce Key
  40. { { L"REFLECT5"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"},0 }, // Runonce Key
  41. { { L"REFLECT6"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx"},0 }, // Runonce Key
  42. { { L"REFLECT7"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\COM3"},0 }, // COM+ Key
  43. { { L"REFLECT8"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\COM3"},0 }, // COM+ Key
  44. { { L"REFLECT9"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Ole"},0 }, // OLE Key
  45. { { L"REFLECT10"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Ole"},0 }, // OLE Key
  46. { { L"REFLECT11"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\EventSystem"},0 }, // EventSystem
  47. { { L"REFLECT12"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\EventSystem"},0 }, // EventSystem
  48. { { L"REFLECT13"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\RPC"},0 }, // RPC
  49. { { L"REFLECT14"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\RPC"},0 }, // RPC
  50. { { L"REFLECT15"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\UnInstall"},0 }, // UnInstall Key
  51. { { L"REFLECT16"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UnInstall"},0 }, // UnInstall Key
  52. //{ { L"REFLECT15"}, {L"\\REGISTRY\\MACHINE\\SYSTEM\\TEST"},0 },
  53. { {L""}, {L""} }
  54. };
  55. ISN_NODE_TYPE RedirectorTableStatic[ISN_NODE_MAX_NUM]={
  56. //{ { L"REDIRECT1"}, {L"\\REGISTRY\\MACHINE\\SYSTEM\\TEST"},0 },
  57. { { L"REDIRECT2"}, {L"\\REGISTRY\\USER\\*\\Software\\Classes"},0 }, // the first '*' is the user's SID
  58. { { L"REDIRECT3"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes"},0 }, // CLS ROOT
  59. { { L"REDIRECT4"}, {L"\\REGISTRY\\MACHINE\\SOFTWARE"},0 }, // CLS ROOT
  60. { { L"REDIRECT5"}, {L"\\REGISTRY\\USER\\*_Classes"},0 }, // alias to the classes root on the user hives
  61. { {L""}, {L""} }
  62. };
  63. ISN_NODE_TYPE *ReflectorTable = &ReflectorTableStatic[0]; // dynamically we can allocate later on.
  64. ISN_NODE_TYPE *RedirectorTable = &RedirectorTableStatic[0]; // dynamically we can allocate later on.
  65. ISN_NODE_TYPE TempIsnNode;
  66. BOOL bInitialCopy = FALSE;
  67. VOID
  68. SetInitialCopy ()
  69. {
  70. bInitialCopy = TRUE;
  71. }
  72. BOOL
  73. ReflectSecurity (
  74. HKEY SrcKey,
  75. HKEY DestKey
  76. )
  77. /*++
  78. Routine Description:
  79. Copy security attribute from SrcKey to DestKey.
  80. Arguments:
  81. SrcKey - Handle to a key..
  82. DestKey - handle to the destination key.
  83. Return Value:
  84. TRUE if operation succeeded.
  85. FALSE otherwise.
  86. --*/
  87. {
  88. PSECURITY_DESCRIPTOR SD;
  89. BYTE Buffer[2048]; // reflector only manages general purpose keys and will have smaller ACL
  90. LONG Ret, Len;
  91. LONG BufferLen = sizeof (Buffer);
  92. DWORD Count = 0;
  93. SD = (PSECURITY_DESCRIPTOR)Buffer;
  94. Len = BufferLen;
  95. Ret = RegGetKeySecurity( SrcKey, DACL_SECURITY_INFORMATION, SD, &Len);
  96. if (Ret == ERROR_INSUFFICIENT_BUFFER ) {
  97. SD = VirtualAlloc( NULL, Len, MEM_COMMIT, PAGE_READWRITE );
  98. if (SD != NULL) {
  99. BufferLen = Len;
  100. Ret = RegGetKeySecurity( SrcKey, DACL_SECURITY_INFORMATION, SD, &Len);
  101. } else SD = (PSECURITY_DESCRIPTOR)Buffer;
  102. }
  103. if (ERROR_SUCCESS == Ret )
  104. Ret = RegSetKeySecurity ( DestKey, DACL_SECURITY_INFORMATION, SD );
  105. Count +=Ret;
  106. Len = BufferLen;
  107. Ret = RegGetKeySecurity( SrcKey, GROUP_SECURITY_INFORMATION, SD, &Len);
  108. if (Ret == ERROR_INSUFFICIENT_BUFFER ) {
  109. if (SD != Buffer)
  110. VirtualFree (SD, 0,MEM_RELEASE);
  111. SD = VirtualAlloc( NULL, Len, MEM_COMMIT, PAGE_READWRITE );
  112. if (SD != NULL) {
  113. BufferLen = Len;
  114. Ret = RegGetKeySecurity( SrcKey, DACL_SECURITY_INFORMATION, SD, &Len);
  115. } else SD = (PSECURITY_DESCRIPTOR)Buffer;
  116. }
  117. if (ERROR_SUCCESS == Ret )
  118. Ret = RegSetKeySecurity ( DestKey, GROUP_SECURITY_INFORMATION, SD );
  119. Count +=Ret;
  120. Len = BufferLen;
  121. Ret = RegGetKeySecurity( SrcKey, OWNER_SECURITY_INFORMATION, SD, &Len);
  122. if (Ret == ERROR_INSUFFICIENT_BUFFER ) {
  123. if (SD != Buffer)
  124. VirtualFree (SD, 0,MEM_RELEASE);
  125. SD = VirtualAlloc( NULL, Len, MEM_COMMIT, PAGE_READWRITE );
  126. if (SD != NULL) {
  127. BufferLen = Len;
  128. Ret = RegGetKeySecurity( SrcKey, DACL_SECURITY_INFORMATION, SD, &Len);
  129. } else SD = (PSECURITY_DESCRIPTOR)Buffer;
  130. }
  131. if (ERROR_SUCCESS == Ret )
  132. Ret = RegSetKeySecurity ( DestKey, OWNER_SECURITY_INFORMATION, SD );
  133. Count +=Ret;
  134. Len = BufferLen;
  135. Ret = RegGetKeySecurity( SrcKey, SACL_SECURITY_INFORMATION, SD, &Len);
  136. if (Ret == ERROR_INSUFFICIENT_BUFFER ) {
  137. if (SD != Buffer)
  138. VirtualFree (SD, 0,MEM_RELEASE);
  139. SD = VirtualAlloc( NULL, Len, MEM_COMMIT, PAGE_READWRITE );
  140. if (SD != NULL) {
  141. BufferLen = Len;
  142. Ret = RegGetKeySecurity( SrcKey, DACL_SECURITY_INFORMATION, SD, &Len);
  143. } else SD = (PSECURITY_DESCRIPTOR)Buffer;
  144. }
  145. if (ERROR_SUCCESS == Ret )
  146. Ret = RegSetKeySecurity ( DestKey, SACL_SECURITY_INFORMATION, SD );
  147. Count +=Ret;
  148. if (SD != Buffer)
  149. VirtualFree (SD, 0,MEM_RELEASE);
  150. if (Count != 0) {
  151. return FALSE;
  152. }
  153. return TRUE;
  154. }
  155. BOOL
  156. GetDefaultValue (
  157. HKEY SrcKey,
  158. WCHAR *pBuff,
  159. DWORD *Len
  160. )
  161. /*++
  162. Routine Description:
  163. retrieve the default value.
  164. Arguments:
  165. SrcKey - Handle to a key default value need to be retrieved.
  166. pBuff - receiving the default value.
  167. Len - size of the buffer.
  168. Return Value:
  169. TRUE if it can retrieve the value,
  170. FALSE otherwise.
  171. --*/
  172. {
  173. DWORD Ret;
  174. Ret = RegQueryValueEx(
  175. SrcKey, // handle to key to query
  176. NULL,
  177. NULL,
  178. NULL,
  179. (PBYTE) &pBuff[0],
  180. Len);
  181. if (Ret != ERROR_SUCCESS )
  182. return FALSE;
  183. return TRUE;
  184. }
  185. BOOL
  186. NonMergeableValueCLSID (
  187. HKEY SrcKey,
  188. HKEY DestKey
  189. )
  190. /*++
  191. Routine Description:
  192. determine if a key related to an association should be merged.
  193. Rule: if the association refer to a CLSID that has InprocServer don't merge that.
  194. .doc default attrib will have another key x, and x's default attribute might have
  195. CLSID. Now that clsID need to have either LocalServer or need to be present on the
  196. other side.
  197. Arguments:
  198. SrcKey - Handle to a key that need to be checked.
  199. DestKey - handle to the destination key that will receive the update.
  200. Return Value:
  201. TRUE if we shouldn't merge value.
  202. FALSE otherwise. //catter will merge value.
  203. --*/
  204. {
  205. WCHAR Name[_MAX_PATH];
  206. WCHAR Buff[_MAX_PATH];
  207. WCHAR *pStr;
  208. DWORD dwBuffLen = 256;
  209. HKEY hClsID;
  210. DWORD dwCount;
  211. DWORD Ret;
  212. DWORD dwFlag = 0;
  213. BOOL bCLSIDPresent = TRUE;
  214. //
  215. // get name to the key.
  216. // get default value
  217. // open the key under SrcKey
  218. // try CLSID if exist
  219. // open the CLSID and check for localserver
  220. // Merge the key
  221. // try classid on dest.
  222. //
  223. dwBuffLen = sizeof (Name ) / sizeof (Name[0]);
  224. if (!HandleToKeyName ( SrcKey, Name, &dwBuffLen ))
  225. return TRUE; // ignore merging at this point, fardown the association.
  226. pStr = wcsstr (Name, L"\\."); // consider only association like .doc
  227. //
  228. // don't fall in the association category
  229. //
  230. if (pStr == NULL)
  231. return FALSE; // value key should be merged
  232. if (wcschr (pStr+1, L'\\') !=NULL )
  233. return FALSE; // value key should be merged
  234. //
  235. // get the default string
  236. //
  237. if ( !GetDefaultValue (SrcKey, Buff, &dwBuffLen) )
  238. return TRUE; // failed don't merge, check for insufficient buffer.
  239. wcscat (Buff, L"\\CLSID");
  240. //
  241. // Check which side you are checking, if src is 32bit you need to pass 32bit flag
  242. //
  243. dwBuffLen = sizeof (Name ) / sizeof (Name[0]);
  244. if (!HandleToKeyName ( SrcKey, Name, &dwBuffLen )) //get the name
  245. return TRUE;
  246. if (!Is64bitNode (Name) )
  247. dwFlag = KEY_WOW64_32KEY;
  248. Ret = RegOpenKeyEx(
  249. HKEY_CLASSES_ROOT,
  250. Buff,
  251. 0,//OpenOption,
  252. KEY_ALL_ACCESS | dwFlag,
  253. &hClsID
  254. );
  255. if ( Ret != ERROR_SUCCESS ) {
  256. if (Ret == ERROR_FILE_NOT_FOUND )
  257. return FALSE; // key doesn't exist
  258. //
  259. // Try to find out if this assumption is true.
  260. // no CLSID you can merge because it doesn't associate any CLSID
  261. //
  262. return TRUE; //key might be bad or access denied.
  263. }
  264. dwBuffLen = sizeof (Buff ) / sizeof (Buff[0]);
  265. if ( !GetDefaultValue (hClsID, Buff, &dwBuffLen ) ) {
  266. RegCloseKey (hClsID);
  267. return TRUE; // failed don't merge, couldn't get the CLSID
  268. }
  269. RegCloseKey (hClsID);
  270. //
  271. // check if the CLSID has localserver
  272. //
  273. wcscpy (Name, L"CLSID\\");
  274. wcscat (Name, Buff );
  275. Ret = RegOpenKeyEx(
  276. HKEY_CLASSES_ROOT,
  277. Name,
  278. 0,//OpenOption,
  279. KEY_ALL_ACCESS | dwFlag,
  280. &hClsID
  281. );
  282. if ( Ret != ERROR_SUCCESS )
  283. bCLSIDPresent = FALSE; //clsid on source doesn't exist and hence no local server, i.e., no handler
  284. else {
  285. dwBuffLen = sizeof (Name ) / sizeof (Name[0]);
  286. if (!HandleToKeyName ( hClsID, Name, &dwBuffLen )) //get the name
  287. return TRUE;
  288. }
  289. if ( bCLSIDPresent ) {
  290. dwCount =0;
  291. MarkNonMergeableKey ( Buff, hClsID, &dwCount );
  292. RegCloseKey (hClsID);
  293. if (dwCount != 0)
  294. return FALSE;
  295. bCLSIDPresent = FALSE; // must be an InProc
  296. }
  297. //
  298. // Now chek of local server, there might be some case where
  299. // on the source there is one local server that don't exist on the dest,
  300. // but in the future, that will get copied over.
  301. //
  302. //
  303. //
  304. // Get mirror Name
  305. //
  306. GetMirrorName (Name, Buff);
  307. if ( (hClsID = OpenNode (Buff)) != NULL ) {
  308. RegCloseKey (hClsID);
  309. return FALSE; // mirror side has the handler CLSID
  310. }
  311. return TRUE; // no don't merge value associated with the src key.
  312. }
  313. BOOL
  314. GetKeyTime (
  315. HKEY SrcKey,
  316. ULONGLONG *Time
  317. )
  318. /*++
  319. Routine Description:
  320. Get last update time associated with a key.
  321. Arguments:
  322. SrcKey - handle to the key.
  323. Return Value:
  324. TRUE if function succeed, FALSE otherwise.
  325. --*/
  326. {
  327. DWORD Ret;
  328. FILETIME ftLastWriteTime;
  329. Ret = RegQueryInfoKey(
  330. SrcKey, // handle to key to query
  331. NULL, // address of buffer for class string
  332. NULL, // address of size of class string buffer
  333. NULL, // reserved
  334. NULL, // address of buffer for number of
  335. // subkeys
  336. NULL, // address of buffer for longest subkey
  337. // name length
  338. NULL, // address of buffer for longest class
  339. // string length
  340. NULL, // address of buffer for number of value
  341. // entries
  342. NULL, // address of buffer for longest
  343. // value name length
  344. NULL, // address of buffer for longest value
  345. // data length
  346. NULL,
  347. // address of buffer for security
  348. // descriptor length
  349. &ftLastWriteTime // address of buffer for last write
  350. // time
  351. );
  352. if ( Ret == ERROR_SUCCESS ) {
  353. *Time = *(ULONGLONG *)&ftLastWriteTime; //copy the value
  354. return TRUE;
  355. }
  356. return FALSE;
  357. }
  358. VOID
  359. UpdateTable (
  360. ISN_NODE_TYPE *Table,
  361. ISN_NODE_TYPE *TempIsnNode
  362. )
  363. {
  364. DWORD dwCount=0;
  365. BOOL Found = FALSE;
  366. if ( !wcslen (TempIsnNode->NodeName) || !wcslen (TempIsnNode->NodeValue) )
  367. return;
  368. for ( dwCount=0;wcslen (Table[dwCount].NodeValue);dwCount++) {
  369. if (wcscmp (Table[dwCount].NodeValue, TempIsnNode->NodeValue) == 0 ) {
  370. Table[dwCount].Flag=1; //already in the registry
  371. Found = TRUE;
  372. }
  373. }
  374. if (!Found) {
  375. //update the table with the node
  376. if ( dwCount >= ISN_NODE_MAX_NUM ) {
  377. Wow64RegDbgPrint ( ("\nSorry! The table is full returning..............."));
  378. return;
  379. }
  380. Table[dwCount].Flag=1;
  381. wcscpy (Table[dwCount].NodeName, TempIsnNode->NodeName);
  382. wcscpy (Table[dwCount].NodeValue, TempIsnNode->NodeValue);
  383. Table[dwCount+1].NodeName[0] = UNICODE_NULL;
  384. Table[dwCount+1].NodeValue[0] = UNICODE_NULL;
  385. }
  386. }
  387. BOOL
  388. IsGUIDStrUnderCLSID (
  389. LPCWSTR Key
  390. )
  391. /*++
  392. Routine Description:
  393. pIsGuid examines the string specified by Key and determines if it
  394. is the correct length and has dashes at the correct locations.
  395. Arguments:
  396. Key - The string that may or may not be a GUID
  397. Return Value:
  398. TRUE if Key is a GUID (and only a GUID), or FALSE if not.
  399. --*/
  400. {
  401. int i;
  402. PWCHAR p;
  403. if ( (wcslen (Key) != 38) || (*Key != L'{' )) {
  404. return FALSE;
  405. }
  406. for (i = 0, p = (PWCHAR)(Key+1) ; i<36 ; p++, i++) {
  407. if (*p == L'-') {
  408. if (i != 8 && i != 13 && i != 18 && i != 23) {
  409. return FALSE;
  410. }
  411. } else if (i == 8 || i == 13 || i == 18 || i == 23) {
  412. return FALSE;
  413. } else if (!iswxdigit( *p )) //ifnot alphaneumeric
  414. return FALSE;
  415. }
  416. if ( *p != L'}')
  417. return FALSE;
  418. return TRUE;
  419. }
  420. BOOL
  421. CreateWow6432ValueKey (
  422. HKEY DestKey,
  423. WOW6432_VALUEKEY_TYPE ValueType
  424. )
  425. /*++
  426. Routine Description:
  427. Create a Wow6432ValueKey under the node.
  428. Arguments:
  429. DestKey - Handle to the dest Key.
  430. Return Value:
  431. TRUE if the function succeed.
  432. FALSE otherwise.
  433. --*/
  434. {
  435. WOW6432_VALUEKEY Value;
  436. ULONGLONG temp;
  437. SYSTEMTIME sSystemTime;
  438. FILETIME sFileTime;
  439. Value.ValueType = ValueType;
  440. Value.Reserve = 0;
  441. GetSystemTime (&sSystemTime);
  442. if ( SystemTimeToFileTime( &sSystemTime, &sFileTime) ==0 )
  443. return FALSE;
  444. Value.TimeStamp = *(ULONGLONG *)&sFileTime;
  445. Value.TimeStamp += (1000*10000*VALUE_KEY_UPDATE_TIME_DIFF); //100 nano sec interval
  446. if ( RegSetValueEx(
  447. DestKey,
  448. (LPCWSTR )WOW6432_VALUE_KEY_NAME,
  449. 0,
  450. REG_BINARY,
  451. (const PBYTE)&Value,
  452. sizeof (WOW6432_VALUEKEY)
  453. ) != ERROR_SUCCESS ) {
  454. Wow64RegDbgPrint ( ("\nSorry! couldn't create wow6432valueKey "));
  455. return FALSE;
  456. }
  457. if (! GetKeyTime (DestKey, &temp))
  458. return FALSE;
  459. if (Value.TimeStamp < temp || Value.TimeStamp > (temp+(1000*10000*VALUE_KEY_UPDATE_TIME_DIFF)) )
  460. Wow64RegDbgPrint ( ("\nError in the time Stamp!!!!"));
  461. return TRUE;
  462. }
  463. BOOL
  464. GetWow6432ValueKey (
  465. HKEY hKey,
  466. WOW6432_VALUEKEY *pValue
  467. )
  468. /*++
  469. Routine Description:
  470. If the specified Key have the Wow6432Value key return the structure.
  471. Arguments:
  472. hKey - Handle to the Key to search the value key.
  473. pValue - Receive the structure.
  474. Return Value:
  475. TRUE if the value can be quaried and exist.
  476. FALSE otherwise.
  477. --*/
  478. {
  479. DWORD Type;
  480. DWORD Len = sizeof (WOW6432_VALUEKEY);
  481. DWORD Ret;
  482. memset ( pValue, 0, sizeof (WOW6432_VALUEKEY)); // zeroing buffer
  483. if ( (Ret=RegQueryValueEx(
  484. hKey, // handle to key to query
  485. (LPCWSTR )WOW6432_VALUE_KEY_NAME, // address of name of value to query
  486. 0, // reserved
  487. &Type, // address of buffer for value type
  488. (PBYTE)pValue, // address of data buffer
  489. &Len // address of data buffer size
  490. )) == ERROR_SUCCESS )
  491. return TRUE;
  492. return FALSE;
  493. }
  494. BOOL
  495. MarkSingleNonMergeableKey (
  496. HKEY hParent,
  497. LPCWSTR KeyName
  498. )
  499. /*++
  500. Routine Description:
  501. Mark a key non mergeable.
  502. Arguments:
  503. KeyName - Name of the key to mark.
  504. hParent - Handle to the parent.
  505. Return Value:
  506. TRUE if the function succeed.
  507. FALSE otherwise.
  508. --*/
  509. {
  510. HKEY hKey;
  511. DWORD Ret;
  512. WOW6432_VALUEKEY Value;
  513. if ( RegOpenKey (hParent, KeyName, &hKey ) != ERROR_SUCCESS )
  514. return FALSE;
  515. GetWow6432ValueKey ( hKey, &Value ); //todo check return value
  516. if ( Value.ValueType != None ) {
  517. RegCloseKey (hKey );
  518. return FALSE; // already marked with some other type
  519. }
  520. Ret = CreateWow6432ValueKey ( hKey, NonMergeable);
  521. RegCloseKey (hKey );
  522. return Ret;
  523. }
  524. BOOL
  525. MarkNonMergeableKey (
  526. LPCWSTR KeyName,
  527. HKEY hKey,
  528. DWORD *pMergeableSubkey
  529. )
  530. /*++
  531. Routine Description:
  532. Check all the key under hKey if they qualify to be non mergeable.
  533. If so mark them non mergeable.
  534. Arguments:
  535. KeyName - Name of the Key. Normally all following rules is for guid type parent.
  536. If parent qualify, complete path name can be extracted to compare againest grammer.
  537. hKey - Handle to a open Key.
  538. pMergeableSubkey - caller receive total number of mergeable subkey.
  539. Return Value:
  540. TRUE if the function succeed.
  541. FALSE otherwise.
  542. // pMergeableSubkey==0 and return TRUE means there is nothing to reflect.
  543. --*/
  544. {
  545. //
  546. // 1. Inproc server is always non mergeable
  547. // 2. If there is no local server everything is nonmergeable
  548. // 3. If there is both LocalServer32 and InprocServer32 skip Inprocserver
  549. // 4. InprocHandler32 ??
  550. // 5. Typelib check if the GUID point to a right content that can be copied.
  551. //
  552. //
  553. // check if the name is guid
  554. //
  555. DWORD LocalServer = 0;
  556. DWORD InprocServer32 = 0;
  557. ISN_NODE_TYPE Node;
  558. DWORD dwIndex;
  559. DWORD Ret;
  560. WCHAR FullKeyName[_MAX_PATH];
  561. DWORD dwLen = _MAX_PATH;
  562. //
  563. // Check if the Key Fall under Classes\CLSID or \\Classes\\Wow6432Node\\CLSID
  564. //
  565. if ( !IsGUIDStrUnderCLSID ( KeyName ) )
  566. return TRUE; //No action is required
  567. if ( !HandleToKeyName ( hKey, FullKeyName, &dwLen )) {
  568. *pMergeableSubkey = 0;
  569. return TRUE; // FALSE
  570. }
  571. dwLen = wcslen (FullKeyName);
  572. if (dwLen <=39)
  573. return TRUE;
  574. dwLen-=39; //skip the GUID because the handle point to guid
  575. if (!(_wcsnicmp ( FullKeyName+dwLen-14, L"\\Classes\\CLSID", 14) ==0 ||
  576. _wcsnicmp ( FullKeyName+dwLen-26, L"\\Classes\\Wow6432Node\\CLSID", 26) ==0 ||
  577. _wcsnicmp ( FullKeyName+dwLen-6, L"\\CLSID", 6) ==0)
  578. )
  579. return TRUE;
  580. //don't reflect Key with name InProcServer32 or inprochandler
  581. if ( _wcsicmp (KeyName, (LPCWSTR)L"InprocServer32")==0 || _wcsicmp (KeyName, (LPCWSTR) L"InprocHandler32")==0) {
  582. *pMergeableSubkey = 0;
  583. return TRUE;
  584. }
  585. //Mark the inprocserver
  586. //Mark InprocHandler
  587. //if no localserver mark all
  588. //Enumerate all the Keys
  589. *pMergeableSubkey = 0;
  590. dwIndex = 0;
  591. LocalServer =0;
  592. for (;;) {
  593. DWORD Len = sizeof (Node.NodeValue)/sizeof (WCHAR);
  594. Ret = RegEnumKey(
  595. hKey,
  596. dwIndex,
  597. Node.NodeValue,
  598. Len
  599. );
  600. if (Ret != ERROR_SUCCESS)
  601. break;
  602. dwIndex++;
  603. if ( !wcscmp (Node.NodeValue, (LPCWSTR )NODE_NAME_32BIT) )
  604. continue;
  605. if ( !_wcsicmp (Node.NodeValue, (LPCWSTR)L"InprocServer32") || !_wcsicmp (Node.NodeValue, (LPCWSTR) L"InprocHandler32")) {
  606. MarkSingleNonMergeableKey ( hKey, Node.NodeValue );
  607. InprocServer32 = 1;
  608. } else if ( !_wcsicmp ((LPCWSTR)Node.NodeValue, (LPCWSTR)L"LocalServer32")) {
  609. LocalServer=1;
  610. (*pMergeableSubkey)++;
  611. }
  612. else (*pMergeableSubkey)++;
  613. }
  614. // if Ret != NomoreKey then you are in trouble
  615. //
  616. // you might try 2nd pass to evaluate rest of the key
  617. //
  618. if ( LocalServer == 0 )
  619. *pMergeableSubkey = 0; //there might be some copy key to merge
  620. return TRUE;
  621. }
  622. BOOL
  623. ChangedInValueKey(
  624. HKEY DestKey,
  625. PWCHAR pValueName,
  626. PBYTE pBuff,
  627. DWORD BuffLen
  628. )
  629. /*++
  630. Routine Description:
  631. This routine check for a particular value key and return if that
  632. need to be copied into the destination key.
  633. Arguments:
  634. DestKey - Handle to the dest Key.
  635. pValueName - Name of the value key need to be checked into DestKey
  636. pBuff - buffer that contain the value.
  637. BuffLen - length of the buffer
  638. Return Value:
  639. TRUE if destination need to be updated.
  640. FALSE otherwise.
  641. --*/
  642. {
  643. BYTE TempBuff[256];
  644. DWORD Ret;
  645. DWORD Type;
  646. DWORD TempBuffLen = 256;
  647. Ret =RegQueryValueEx(
  648. DestKey,
  649. pValueName,
  650. 0,
  651. &Type,
  652. TempBuff,
  653. &TempBuffLen
  654. );
  655. if ( (Ret != ERROR_SUCCESS ) || (BuffLen != TempBuffLen ) )
  656. return TRUE;
  657. if (memcmp (TempBuff, pBuff, BuffLen) != 0)
  658. return TRUE;
  659. return FALSE;
  660. }
  661. BOOL
  662. MergeK1K2Value (
  663. HKEY SrcKey,
  664. HKEY DestKey,
  665. DWORD dwFlag
  666. )
  667. /*++
  668. Routine Description:
  669. Copy value key from the node pointed by SrcKey to the DestKey skipping the special wow6432 node.
  670. Arguments:
  671. SrcKey - Source Key Node.
  672. DestKey - Handle to the dest Key.
  673. dwFlag - option flag to merge value key.
  674. Return Value:
  675. TRUE if the function succeed.
  676. FALSE otherwise.
  677. --*/
  678. {
  679. ISN_NODE_TYPE Node;
  680. DWORD dwIndex =0;
  681. DWORD Ret;
  682. WOW6432_VALUEKEY ValueSrc;
  683. WOW6432_VALUEKEY ValueDest;
  684. ULONGLONG TimeSrc;
  685. ULONGLONG TimeDest;
  686. DWORD CreateWowValueKey = FALSE;
  687. //
  688. // CopyValue
  689. //
  690. //
  691. // find the wow6432valuekey and interpret the case if value keys need to be copied.
  692. // Compare the same wow6432node from both Key.
  693. //
  694. GetWow6432ValueKey ( SrcKey, &ValueSrc);
  695. GetWow6432ValueKey ( DestKey, &ValueDest);
  696. if ( !GetKeyTime ( SrcKey, &TimeSrc) || ! GetKeyTime ( DestKey, &TimeDest) ) {
  697. Wow64RegDbgPrint ( ("\nSorry! Couldn't get time stamp"));
  698. return FALSE;
  699. }
  700. if (!( dwFlag & DESTINATION_NEWLY_CREATED )) { //timestamp is always higher for newly created key by reflector
  701. //
  702. // check which one is new
  703. //
  704. if ( ValueDest.TimeStamp ==0 || ValueSrc.TimeStamp ==0 ) {
  705. //check only Key time stamp
  706. if ( TimeSrc < TimeDest ) return TRUE;
  707. } else if ( ValueSrc.TimeStamp > TimeSrc || //nothing has been changed on src
  708. ( TimeDest > TimeSrc ) //dest has newer valid stamp
  709. )
  710. return TRUE; //nothing has been changed since last scan
  711. }
  712. if ( NonMergeableValueCLSID ( SrcKey, DestKey))
  713. return TRUE;
  714. //
  715. // Reflect security attributes
  716. //
  717. ReflectSecurity (SrcKey, DestKey);
  718. for (;;) {
  719. DWORD Type;
  720. DWORD Len1 = sizeof(Node.NodeName);
  721. DWORD Len2 = sizeof(Node.NodeValue);
  722. Ret = RegEnumValue(
  723. SrcKey,
  724. dwIndex,
  725. Node.NodeName,
  726. &Len1,
  727. 0,
  728. &Type,
  729. (PBYTE)&Node.NodeValue[0],
  730. &Len2
  731. );
  732. if ( Ret != ERROR_SUCCESS)
  733. break;
  734. dwIndex++;
  735. //
  736. // skip the value if its wow6432 value key. Advapi will filter the key in the long run
  737. //
  738. if ( !wcscmp (Node.NodeName, (LPCWSTR )WOW6432_VALUE_KEY_NAME) )
  739. continue;
  740. //
  741. // check first if any changes in the value key
  742. //
  743. if (!ChangedInValueKey(
  744. DestKey,
  745. Node.NodeName,
  746. (PBYTE)&Node.NodeValue[0],
  747. Len2
  748. ) )
  749. continue;
  750. if (dwFlag & PATCH_PATHNAME )
  751. PatchPathName ( Node.NodeValue );
  752. Ret = RegSetValueEx(
  753. DestKey,
  754. Node.NodeName,
  755. 0,
  756. Type,
  757. (PBYTE)&Node.NodeValue[0],
  758. Len2
  759. );
  760. if ( Ret != ERROR_SUCCESS ) {
  761. Wow64RegDbgPrint ( ("\nSorry! couldn't set Key value"));
  762. } else {
  763. CreateWowValueKey = TRUE; //need to update the wow64keys.
  764. if (dwFlag & DELETE_VALUEKEY ) {
  765. //delete the value key from the sources
  766. RegDeleteValue (SrcKey, Node.NodeName);
  767. dwIndex = 0; // start the loop again
  768. }
  769. }
  770. }
  771. if ( dwIndex == 0 ) // for an empty key you need to write the value
  772. CreateWowValueKey = TRUE;
  773. if ( ( CreateWowValueKey) && (!(NOT_MARK_DESTINATION & dwFlag ) ) ) {
  774. if ( !CreateWow6432ValueKey ( DestKey, Copy) )
  775. Wow64RegDbgPrint ( ("\nSorry! Couldn't create wow6432ValueKey..."));
  776. }
  777. //
  778. // set attribute on the parent side that key has been reflected
  779. //
  780. if ( CreateWowValueKey && !(NOT_MARK_SOURCE & dwFlag) )
  781. if ( !CreateWow6432ValueKey ( SrcKey, Reflected ) ) {
  782. Wow64RegDbgPrint ( ("\nSorry! couldn't create wow6432ValueKey on the source."));
  783. return FALSE;
  784. }
  785. return TRUE;
  786. }
  787. BOOL
  788. SpecialReflectableKey (
  789. HKEY SrcKey,
  790. HKEY DestKey
  791. )
  792. /*++
  793. Routine Description:
  794. This will determine if a certain key shouldn't be scanned for possible reflection.
  795. Arguments:
  796. SrcKey - Source Key Node.
  797. DestKey - Handle to destination key.
  798. Return Value:
  799. TRUE if the key shouldn't be scanned.
  800. FALSE otherwise.
  801. --*/
  802. {
  803. WCHAR Node[_MAX_PATH];
  804. DWORD dwLen = _MAX_PATH;
  805. if ( !HandleToKeyName ( SrcKey, Node, &dwLen ))
  806. return TRUE; // on error betrter skip the key
  807. //
  808. // Check if its a TypeLib
  809. //
  810. //
  811. // Hard coded no reflection for \Installer Key.
  812. //
  813. if (_wcsnicmp (Node, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\Installer", sizeof (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\Installer")/sizeof (WCHAR) )==0)
  814. return TRUE;
  815. if (_wcsnicmp (Node, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Installer", sizeof (L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\Installer")/sizeof (WCHAR) )==0)
  816. return TRUE;
  817. if (_wcsicmp (Node, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\TypeLib")==0) {
  818. //ProcessTypeLib (SrcKey, DestKey, TRUE);
  819. return TRUE;
  820. }
  821. if (_wcsicmp (Node, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\Wow6432Node\\TypeLib")==0) {
  822. //ProcessTypeLib (SrcKey, DestKey, FALSE);
  823. return TRUE;
  824. }
  825. return FALSE;
  826. }
  827. void
  828. MergeK1K2 (
  829. HKEY SrcKey,
  830. HKEY DestKey,
  831. DWORD OptionFlag
  832. )
  833. /*++
  834. Routine Description:
  835. Copy contect from the node pointed by SrcKey to the DestKey skipping the special wow6432 node.
  836. Cases:
  837. 1. Reflect everything from K1 to K2: done
  838. 2. Reflect everything from K2 to K1: <TBD>
  839. 3. Delete everything from K1 which was a copy from K1 and doesn't exist over there <TBD>
  840. 4. Delete everything from K2 which was a copy from K2 and doesn't exist over there <TBD>
  841. Arguments:
  842. SrcKey - Source Key Node.
  843. DestKey - Handle to the dest Key.
  844. OptionFlag - determine behavior of the reflection
  845. Return Value:
  846. None.
  847. --*/
  848. {
  849. WCHAR Node[_MAX_PATH];
  850. DWORD dwIndex =0;
  851. DWORD Ret;
  852. DWORD dwNewOptionFlag = 0;
  853. HKEY Key11;
  854. HKEY Key21;
  855. //
  856. // Copy Values first
  857. //
  858. if ( SpecialReflectableKey (SrcKey, DestKey) )
  859. return;
  860. if ( GetReflectorThreadStatus () == PrepareToStop )
  861. return; // thread going to stop soon
  862. if ( ! (OptionFlag & DELETE_FLAG ) )
  863. MergeK1K2Value ( SrcKey,DestKey, OptionFlag );
  864. //
  865. // Copy subKeys
  866. //
  867. dwIndex = 0;
  868. for (;;) {
  869. DWORD ToMergeSubKey =1;
  870. BOOL MirrorKeyExist = FALSE;
  871. WOW6432_VALUEKEY ValueSrc;
  872. DWORD Len = sizeof (Node)/sizeof (Node[0]);
  873. Ret = RegEnumKey(
  874. SrcKey,
  875. dwIndex,
  876. Node,
  877. Len
  878. );
  879. if (Ret != ERROR_SUCCESS)
  880. break;
  881. dwIndex++;
  882. if ( !wcscmp (Node, (LPCWSTR )NODE_NAME_32BIT) )
  883. continue;
  884. Ret = RegOpenKeyEx(SrcKey, Node, 0, KEY_ALL_ACCESS, &Key11);
  885. if (Ret != ERROR_SUCCESS) {
  886. continue;
  887. }
  888. if (!MarkNonMergeableKey (Node, Key11, &ToMergeSubKey ) ) {
  889. RegCloseKey (Key11);
  890. continue;
  891. }
  892. if ( ToMergeSubKey == 0 ){
  893. RegCloseKey (Key11);
  894. continue;
  895. } // no subkey to merge
  896. GetWow6432ValueKey ( Key11, &ValueSrc);
  897. if ( ValueSrc.ValueType == NonMergeable ) {
  898. RegCloseKey (Key11);
  899. continue;
  900. }
  901. //
  902. // Tryto open first if fail then create
  903. //
  904. if ((Ret = RegOpenKeyEx(DestKey, Node, 0, KEY_ALL_ACCESS, &Key21))
  905. == ERROR_SUCCESS)
  906. MirrorKeyExist = TRUE;
  907. //
  908. // Check if the mirror key is a original Key
  909. //
  910. if ( MirrorKeyExist ) {
  911. WOW6432_VALUEKEY ValueDest;
  912. GetWow6432ValueKey ( Key21, &ValueDest);
  913. if ( ( ValueDest.ValueType == None && ValueDest.TimeStamp!=0 ) ||
  914. ( ValueDest.ValueType == NonMergeable ) )
  915. { //doesn't make any sense to merge down.
  916. printf ("\nClosing here...");
  917. RegCloseKey (Key11);
  918. RegCloseKey (Key21);
  919. continue;
  920. }
  921. }
  922. //
  923. // check the deletion case: if the dest isn't empty
  924. //
  925. if (!MirrorKeyExist) { //The key doesn't exist on the other side
  926. //
  927. // See if the src key is a copy
  928. //
  929. //
  930. // if its a copy you shouldn't try to create the key
  931. // Rather you might delete the Key
  932. //
  933. if ( ValueSrc.ValueType == Copy || ValueSrc.ValueType == Reflected ) {
  934. RegCloseKey (Key11);
  935. //
  936. // Delete the subKey
  937. //
  938. if ( DeleteKey( SrcKey, Node, 1) == ERROR_SUCCESS) {
  939. dwIndex--; //you needn't to increase index otherwise skip
  940. //Wow64RegDbgPrint ( ("\nDeleting copied Key: %S",Node.NodeValue));
  941. } else
  942. Wow64RegDbgPrint ( ("\nCouldn't delete Key: %S, Error:%d",Node, Ret));
  943. continue;
  944. } else {
  945. //
  946. // if it has already been reflected do you need to create
  947. // Mark the Key as copied Key
  948. //
  949. if ( ValueSrc.ValueType == None || ValueSrc.ValueType == Reflected) { //todo make sure reflected key should be there
  950. if ( (Ret = RegCreateKey(DestKey, Node, &Key21) ) != ERROR_SUCCESS)
  951. Wow64RegDbgPrint ( ("\nCouldn't create Key: %S, Error:%d",Node, Ret));
  952. else {
  953. MirrorKeyExist = TRUE; //just created the mirror key
  954. dwNewOptionFlag = DESTINATION_NEWLY_CREATED;
  955. }
  956. }
  957. }
  958. }
  959. if (!MirrorKeyExist) {
  960. RegCloseKey (Key11);
  961. continue;
  962. }
  963. MergeK1K2 ( Key11, Key21, OptionFlag | dwNewOptionFlag );
  964. RegCloseKey (Key11);
  965. RegCloseKey (Key21);
  966. }
  967. }
  968. BOOL
  969. MergeKeySrcDest(
  970. PWCHAR Src,
  971. PWCHAR Dest
  972. )
  973. /*++
  974. Routine Description:
  975. Copy contect from the src node to the dest node.
  976. Arguments:
  977. Src - Name of the src Node.
  978. Dest - Name of the dest Node.
  979. Return Value:
  980. TRUE if the function succeed.
  981. FALSE otherwise.
  982. --*/
  983. {
  984. BOOL Ret = TRUE;
  985. HKEY Key1;
  986. HKEY Key2;
  987. Key1 = OpenNode (Src);
  988. if (Key1==NULL )
  989. return FALSE;
  990. Key2 = OpenNode (Dest );
  991. if (Key2==NULL ) {
  992. RegCloseKey (Key1);
  993. return FALSE;
  994. }
  995. MergeK1K2 (Key1, Key2, 0); //you need to return right value
  996. RegCloseKey (Key1);
  997. RegCloseKey (Key2);
  998. //
  999. // if its a delete and Key2 is empty should you delete that?
  1000. //
  1001. return Ret;
  1002. }
  1003. BOOL
  1004. SyncNode (
  1005. PWCHAR NodeName
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. Sync registry from a given point.
  1010. Arguments:
  1011. NodeName - Name of the registry from where the node need to be synced.
  1012. Return Value:
  1013. TRUE if the function succeed.
  1014. FALSE otherwise.
  1015. --*/
  1016. {
  1017. WCHAR DestNode[_MAX_PATH];
  1018. BOOL b64bitSide=TRUE;
  1019. BOOL Ret = TRUE;
  1020. DestNode[0] = UNICODE_NULL;
  1021. //
  1022. // must check the value if that exist
  1023. //
  1024. if ( Is64bitNode ( NodeName )) {
  1025. Map64bitTo32bitKeyName ( NodeName, DestNode );
  1026. } else {
  1027. b64bitSide = FALSE;
  1028. Map32bitTo64bitKeyName ( NodeName, DestNode );
  1029. }
  1030. //
  1031. // if both name are same you can return immediately.
  1032. //
  1033. Wow64RegDbgPrint ( ("\nvalidating nodes in SyncNode :%S==>\n\t\t\t%S", NodeName, DestNode));
  1034. if (!wcscmp ( NodeName, DestNode ) )
  1035. return TRUE; // nothing to do same thing
  1036. Ret = MergeKeySrcDest( NodeName, DestNode ); //merge both way??
  1037. return Ret & MergeKeySrcDest( DestNode, NodeName );
  1038. }
  1039. BOOL
  1040. MergeContent (
  1041. PWCHAR Chield,
  1042. DWORD FlagDelete,
  1043. DWORD dwMergeMode
  1044. )
  1045. /*++
  1046. Routine Description:
  1047. Copy contect from the parent node to chield node. Parent node would be just immediate
  1048. parent.
  1049. Arguments:
  1050. Clield - Name of the chield with complete path to copy.
  1051. FlagDelete - if this flag is set the its delete operation for all those reflected Keys.
  1052. dwMergeMode - 0 means the destination node would be 32bit side
  1053. 1 means the destination node would be 64bit side
  1054. Return Value:
  1055. TRUE if the function succeed.
  1056. FALSE otherwise.
  1057. --*/
  1058. {
  1059. ISN_NODE_TYPE Parent;
  1060. PWCHAR p;
  1061. HKEY Key1;
  1062. HKEY Key2;
  1063. p = wcsstr (Chield, (LPCWSTR)NODE_NAME_32BIT);
  1064. if ( p != NULL ) {
  1065. wcsncpy (Parent.NodeValue, Chield, p-Chield-1);
  1066. Parent.NodeValue[p-Chield-1] = UNICODE_NULL;
  1067. } else return FALSE;
  1068. Key1 = OpenNode (Parent.NodeValue);
  1069. if (Key1==NULL )
  1070. return FALSE;
  1071. Key2 = OpenNode (Chield );
  1072. if (Key2==NULL ) {
  1073. RegCloseKey (Key1);
  1074. return FALSE;
  1075. }
  1076. if ( dwMergeMode == 0 ) // 64bit side to 32bit side
  1077. MergeK1K2 (Key1, Key2, 0 );
  1078. else if ( dwMergeMode == 1) // 32bit to 64bit side
  1079. MergeK1K2 (Key2, Key1, 0 );
  1080. RegCloseKey (Key1);
  1081. RegCloseKey (Key2);
  1082. return TRUE;
  1083. }
  1084. BOOL
  1085. ValidateNode (
  1086. PWCHAR Parent,
  1087. PWCHAR SubNodeName,
  1088. DWORD Mode, //one means validate all node under parent and using subnode
  1089. DWORD FlagDelete,
  1090. DWORD dwMergeMode
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. Validate node. if node exist skip if doesn't then create the node and then return.
  1095. Arguments:
  1096. Parent - Name of the parent.
  1097. SubNodeName - Name of the node under parent that need to be validated.
  1098. Mode - 0 means Subnode is under the parent.
  1099. 1 means there were wild card and the subnode is under all key under parent.
  1100. FlagDelete - if this flag is set then the content need to be deleted.
  1101. dwMergeMode - 0 means the destination node would be 32bit side
  1102. 1 means the destination node would be 64bit side
  1103. Return Value:
  1104. TRUE if the function succeed.
  1105. FALSE otherwise.
  1106. --*/
  1107. {
  1108. PWCHAR SplitLoc;
  1109. DWORD Ret;
  1110. WCHAR KeyName[256]; //this is just single node name
  1111. WCHAR TempIsnNode2[MAX_PATH];
  1112. if (SubNodeName == NULL) {
  1113. //then its only with the parent
  1114. CheckAndCreateNode (Parent);
  1115. //
  1116. // you can try to copy here
  1117. //
  1118. return MergeContent ( Parent, FlagDelete, dwMergeMode);
  1119. }
  1120. if (SubNodeName[0] == UNICODE_NULL)
  1121. return TRUE;
  1122. if ( Mode == 1) {
  1123. HKEY Key = OpenNode (Parent);
  1124. //
  1125. // loop through all the subkey under parent
  1126. //
  1127. DWORD dwIndex =0;
  1128. for (;;) {
  1129. DWORD Len = sizeof ( KeyName)/sizeof (WCHAR);
  1130. Ret = RegEnumKey(
  1131. Key,
  1132. dwIndex,
  1133. KeyName,
  1134. Len
  1135. );
  1136. if (Ret != ERROR_SUCCESS)
  1137. break;
  1138. if (Parent[0] != UNICODE_NULL) {
  1139. wcscpy ( TempIsnNode2, Parent);
  1140. wcscat (TempIsnNode2, (LPCWSTR )L"\\");
  1141. wcscat (TempIsnNode2, KeyName);
  1142. } else wcscpy (TempIsnNode2, KeyName);
  1143. ValidateNode (TempIsnNode2, SubNodeName, 0, FlagDelete, dwMergeMode);
  1144. dwIndex++;
  1145. }
  1146. if (ERROR_NO_MORE_ITEMS != Ret)
  1147. return FALSE;
  1148. RegCloseKey (Key);
  1149. return TRUE;
  1150. }
  1151. //
  1152. // No wild card here
  1153. //
  1154. if ( ( SplitLoc = wcschr (SubNodeName, L'*') ) == NULL ) {
  1155. if (Parent[0] != UNICODE_NULL) {
  1156. wcscpy ( TempIsnNode2, Parent);
  1157. wcscat (TempIsnNode2, (LPCWSTR )L"\\");
  1158. wcscat (TempIsnNode2, SubNodeName);
  1159. } else
  1160. wcscpy (TempIsnNode2, SubNodeName);
  1161. return ValidateNode (TempIsnNode2, NULL, 0, FlagDelete, dwMergeMode);
  1162. }
  1163. assert ( *(SplitLoc-1) == L'\\');
  1164. *(SplitLoc-1) = UNICODE_NULL;
  1165. SplitLoc++;
  1166. if (*SplitLoc == L'\\')
  1167. SplitLoc++;
  1168. if (Parent[0] != UNICODE_NULL) {
  1169. wcscat (Parent, (LPCWSTR )L"\\");
  1170. wcscat (Parent, SubNodeName);
  1171. } else
  1172. wcscpy (Parent, SubNodeName);
  1173. return ValidateNode (Parent, SplitLoc, 1, FlagDelete, dwMergeMode); //mode 1 means loop within all
  1174. //for any wildcard split the string
  1175. }
  1176. BOOL
  1177. Is64bitNode (
  1178. WCHAR *pName
  1179. )
  1180. /*++
  1181. Routine Description:
  1182. Check if the given name is 64bit.
  1183. Arguments:
  1184. pName - Name of the Key.
  1185. Return Value:
  1186. TRUE if the name is 64bit.
  1187. FALSE otherwise.
  1188. --*/
  1189. {
  1190. PWCHAR pTemp;
  1191. WCHAR Buff[_MAX_PATH];
  1192. WCHAR WowNodeName[1+sizeof (NODE_NAME_32BIT)];
  1193. wcscpy (WowNodeName, NODE_NAME_32BIT);
  1194. _wcsupr (WowNodeName);
  1195. wcscpy (Buff, pName );
  1196. _wcsupr (Buff);
  1197. if ( ( pTemp = wcsstr (Buff, WowNodeName) ) == NULL )
  1198. return TRUE;
  1199. if ( *(pTemp-1) != L'\\' ) // check that wow64 is not in the middle of name
  1200. return TRUE;
  1201. return FALSE;
  1202. }
  1203. BOOL
  1204. GetMirrorName (
  1205. PWCHAR Name,
  1206. PWCHAR MirrorName
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. Return the Mirror name of the Key, ie., if the input is 64 bit it
  1211. will try to get 32bit name and vice versa.
  1212. Arguments:
  1213. Name - name of the key.
  1214. MirrorName - receive the mirror key name.
  1215. Return Value:
  1216. TRUE if the function succeed.
  1217. FALSE otherwise.
  1218. --*/
  1219. {
  1220. if ( Is64bitNode ( Name) )
  1221. Map64bitTo32bitKeyName ( Name, MirrorName );
  1222. else
  1223. Map32bitTo64bitKeyName ( Name, MirrorName );
  1224. return TRUE;
  1225. }
  1226. BOOL
  1227. CreateIsnNodeSingle(
  1228. DWORD dwIndex
  1229. )
  1230. /*++
  1231. Routine Description:
  1232. This function basically start merging from the root of a given key.
  1233. Arguments:
  1234. dwIndex - index to the reflector table.
  1235. Return Value:
  1236. TRUE if the function succeed.
  1237. FALSE otherwise.
  1238. --*/
  1239. {
  1240. ISN_NODE_TYPE IsnNode;
  1241. BOOL b64bitSide=TRUE;
  1242. Wow64RegDbgPrint ( ("\nvalidating nodes %S", ReflectorTable[dwIndex].NodeValue));
  1243. //DbgPrint ("\nvalidating nodes %S", ReflectorTable[dwIndex].NodeValue);
  1244. if (_wcsnicmp (
  1245. ReflectorTable[dwIndex].NodeValue,
  1246. (LPCWSTR )WOW64_RUNONCE_SUBSTR,
  1247. wcslen ((LPCWSTR )WOW64_RUNONCE_SUBSTR) ) == 0 ) {
  1248. return HandleRunonce ( ReflectorTable[dwIndex].NodeValue );
  1249. }
  1250. if ( !wcschr (ReflectorTable[dwIndex].NodeValue, L'*') ) // no wildcard
  1251. return SyncNode ( ReflectorTable[dwIndex].NodeValue );
  1252. //
  1253. // Check for runonce Key
  1254. //
  1255. wcscpy (TempIsnNode.NodeValue, ReflectorTable[dwIndex].NodeValue);
  1256. wcscat (TempIsnNode.NodeValue, (LPCWSTR )L"\\");
  1257. wcscat (TempIsnNode.NodeValue, (LPCWSTR )NODE_NAME_32BIT);
  1258. Wow64RegDbgPrint ( ("\nCopying Key %S==>%S", IsnNode.NodeValue, TempIsnNode.NodeValue));
  1259. ValidateNode (
  1260. IsnNode.NodeValue,
  1261. TempIsnNode.NodeValue,
  1262. 0,
  1263. 0, // last 0 means creation
  1264. 0 // Merge 64bit side to 32bit side
  1265. );
  1266. ValidateNode (
  1267. IsnNode.NodeValue,
  1268. TempIsnNode.NodeValue,
  1269. 0,
  1270. 0, // last 0 means creation
  1271. 1
  1272. );
  1273. return TRUE;
  1274. }
  1275. BOOL
  1276. CreateIsnNode()
  1277. /*++
  1278. Routine Description:
  1279. This function basically start merging using all entry in the reflector table.
  1280. Arguments:
  1281. None.
  1282. Return Value:
  1283. TRUE if the function succeed.
  1284. FALSE otherwise.
  1285. --*/
  1286. {
  1287. ISN_NODE_TYPE IsnNode;
  1288. DWORD dwIndex;
  1289. for ( dwIndex=0;wcslen (RedirectorTable[dwIndex].NodeValue);dwIndex++) {
  1290. IsnNode.NodeValue[0] = UNICODE_NULL;
  1291. wcscpy (TempIsnNode.NodeValue, RedirectorTable[dwIndex].NodeValue);
  1292. wcscat (TempIsnNode.NodeValue, (LPCWSTR )L"\\");
  1293. wcscat (TempIsnNode.NodeValue, (LPCWSTR )NODE_NAME_32BIT);
  1294. Wow64RegDbgPrint ( ("\nCopying Key %S==>%S", IsnNode.NodeValue, TempIsnNode.NodeValue));
  1295. ValidateNode (
  1296. IsnNode.NodeValue,
  1297. TempIsnNode.NodeValue,
  1298. 0,
  1299. 0, // last 0 means creation
  1300. 0 // Merge 64bit side to 32bit side
  1301. );
  1302. ValidateNode (
  1303. IsnNode.NodeValue,
  1304. TempIsnNode.NodeValue,
  1305. 0,
  1306. 0, // last 0 means creation
  1307. 1 // Merge 32bit side to 64bit side
  1308. );
  1309. }
  1310. return TRUE;
  1311. }
  1312. BOOL
  1313. AllocateTable (
  1314. HKEY Key,
  1315. ISN_NODE_TYPE **Table
  1316. )
  1317. /*++
  1318. Routine Description:
  1319. This function will dynamically allocate memory for the reflector thread.
  1320. Currently its implemented as a static table with around 30 entry.
  1321. Arguments:
  1322. Key - entry in the registry that will have the initial table information.
  1323. Table - Table that will point at the new location.
  1324. Return Value:
  1325. TRUE if the function succeed.
  1326. FALSE otherwise.
  1327. --*/
  1328. {
  1329. //
  1330. // determine the number of subkey and that would determine the size
  1331. //
  1332. return TRUE;
  1333. }
  1334. BOOL
  1335. InitializeIsnTable ()
  1336. /*++
  1337. Routine Description:
  1338. Initialize the NodeTable. It merge the value from the registry as well as
  1339. hardcoded value
  1340. Arguments:
  1341. None.
  1342. Return Value:
  1343. TRUE if the function succeed.
  1344. FALSE otherwise.
  1345. --*/
  1346. {
  1347. HKEY Key;
  1348. HKEY Key1;
  1349. LONG Ret;
  1350. DWORD dwIndex=0;
  1351. Ret = RegOpenKeyEx(
  1352. HKEY_LOCAL_MACHINE,
  1353. (LPCWSTR ) WOW64_REGISTRY_SETUP_KEY_NAME_REL,
  1354. 0,
  1355. KEY_ALL_ACCESS,
  1356. &Key
  1357. );
  1358. if (Ret != ERROR_SUCCESS) {
  1359. Ret = RegOpenKeyEx(
  1360. HKEY_LOCAL_MACHINE,
  1361. (LPCWSTR )L"SOFTWARE\\Microsoft",
  1362. 0,
  1363. KEY_ALL_ACCESS,
  1364. &Key
  1365. );
  1366. if (Ret != ERROR_SUCCESS )
  1367. return FALSE;
  1368. if ((Ret = RegOpenKeyEx (Key, (LPCWSTR )L"WOW64\\ISN Nodes", 0, KEY_ALL_ACCESS, &Key1)) != ERROR_SUCCESS )
  1369. if ((Ret = RegCreateKey (Key, (LPCWSTR )L"WOW64\\ISN Nodes", &Key1)) != ERROR_SUCCESS) {
  1370. RegCloseKey (Key);
  1371. return FALSE;
  1372. }
  1373. RegCloseKey (Key);
  1374. Key=Key1;
  1375. }
  1376. //if (!AllocateTable (Key, &RedirectorTable ) )
  1377. // return FALSE;
  1378. //
  1379. // Now Key point to the right location
  1380. //
  1381. RedirectorTable[0].NodeName[0]=UNICODE_NULL; //initialize the table with empty
  1382. RedirectorTable[0].NodeValue[0]=UNICODE_NULL;
  1383. for (;;) {
  1384. DWORD Type, Len1 = sizeof ( TempIsnNode.NodeName );
  1385. DWORD Len2 = sizeof ( TempIsnNode.NodeValue );
  1386. Ret = RegEnumValue(
  1387. Key,
  1388. dwIndex,
  1389. TempIsnNode.NodeName,
  1390. &Len1,
  1391. 0,
  1392. &Type,
  1393. (PBYTE)&TempIsnNode.NodeValue[0],
  1394. &Len2
  1395. );
  1396. //see if its in the table
  1397. if ( Ret != ERROR_SUCCESS)
  1398. break;
  1399. dwIndex++;
  1400. if (Type != REG_SZ )
  1401. continue;
  1402. UpdateTable (RedirectorTable, &TempIsnNode);
  1403. }
  1404. RegCloseKey (Key);
  1405. return TRUE;
  1406. }
  1407. BOOL
  1408. InitializeIsnTableReflector ()
  1409. /*++
  1410. Routine Description:
  1411. Initialize the NodeTable for the reflector. It merge the value from the registry as
  1412. well as hardcoded value
  1413. Arguments:
  1414. Mode - Operation mode
  1415. 0 - default, it update the table and rewrite the table in the registry.
  1416. 1 - means only update the table, don't overwrite in the registry.
  1417. Return Value:
  1418. TRUE if the function succeed.
  1419. FALSE otherwise.
  1420. --*/
  1421. {
  1422. HKEY Key;
  1423. HKEY Key1;
  1424. LONG Ret;
  1425. DWORD dwIndex=0;
  1426. Ret = RegOpenKeyEx(
  1427. HKEY_LOCAL_MACHINE,
  1428. (LPCWSTR ) WOW64_REGISTRY_SETUP_REFLECTOR_KEY,
  1429. 0,
  1430. KEY_ALL_ACCESS,
  1431. &Key
  1432. );
  1433. if (Ret != ERROR_SUCCESS ) {
  1434. Wow64RegDbgPrint ( ("\nSorry!! couldn't open key list at %S", WOW64_REGISTRY_SETUP_REFLECTOR_KEY));
  1435. return FALSE;
  1436. }
  1437. //
  1438. // Now Key point to the right location
  1439. //
  1440. //if (!AllocateTable (Key, &ReflectorTable ) )
  1441. // return FALSE;
  1442. ReflectorTable[0].NodeName[0]=UNICODE_NULL; //initialize the table with empty
  1443. ReflectorTable[0].NodeValue[0]=UNICODE_NULL;
  1444. for (;;) {
  1445. DWORD Type, Len1 = sizeof ( TempIsnNode.NodeName );
  1446. DWORD Len2 = sizeof ( TempIsnNode.NodeValue );
  1447. Ret = RegEnumValue(
  1448. Key,
  1449. dwIndex,
  1450. TempIsnNode.NodeName,
  1451. &Len1,
  1452. 0,
  1453. &Type,
  1454. (PBYTE)&TempIsnNode.NodeValue[0],
  1455. &Len2
  1456. );
  1457. //see if its in the table
  1458. if ( Ret != ERROR_SUCCESS)
  1459. break;
  1460. dwIndex++;
  1461. if (Type != REG_SZ )
  1462. continue;
  1463. UpdateTable (ReflectorTable, &TempIsnNode);
  1464. }
  1465. return TRUE;
  1466. }
  1467. BOOL
  1468. StartReflector ()
  1469. /*++
  1470. Routine Description:
  1471. Start the reflector thread.
  1472. Arguments:
  1473. None.
  1474. Return Value:
  1475. TRUE if the function succeed.
  1476. FALSE otherwise.
  1477. --*/
  1478. {
  1479. HKEY hWowSetupKey;
  1480. WCHAR RefEnableKey[256]; // only a defined key
  1481. if ((hWowSetupKey = OpenNode (REFLECTOR_ENABLE_KEY))!=NULL) {
  1482. RegCloseKey ( hWowSetupKey );
  1483. return FALSE; //reflector couldn't be register because it's disabled now, because of reflection code in advapi.
  1484. }
  1485. //
  1486. // Sync all CLDids
  1487. //
  1488. Wow64SyncCLSID();
  1489. //
  1490. // Now disable the reflector forcefully
  1491. //
  1492. wcscpy (RefEnableKey, REFLECTOR_ENABLE_KEY);
  1493. if (CreateNode (RefEnableKey))
  1494. return FALSE; //reflector couldn't be register because it's disabled now, because of reflection code in advapi.
  1495. //
  1496. // This will be called at the end of GUI mode setup and runonce key can be processed here.
  1497. //
  1498. //return FALSE; // eventully reflector service will go away.
  1499. return RegisterReflector ();
  1500. }
  1501. BOOL
  1502. StopReflector ()
  1503. /*++
  1504. Routine Description:
  1505. Stop the reflector thread.
  1506. Arguments:
  1507. None.
  1508. Return Value:
  1509. TRUE if the function succeed.
  1510. FALSE otherwise.
  1511. --*/
  1512. {
  1513. return UnRegisterReflector ();
  1514. }
  1515. BOOL
  1516. PatchPathName (
  1517. PWCHAR pName
  1518. )
  1519. /*++
  1520. Routine Description:
  1521. Patch pathname so that it point to the right location.
  1522. The value might have multiple system32.
  1523. Arguments:
  1524. pName - name to the path.
  1525. Return Value:
  1526. TRUE if the function already patched the name.
  1527. FALSE otherwise.
  1528. --*/
  1529. {
  1530. WCHAR pBuff[512+20];
  1531. WCHAR pBackup[512+20];
  1532. PWCHAR pLoc;
  1533. BOOL bRet = FALSE;
  1534. DWORD Len;
  1535. //if there is any system32 replace that with WOW64_SYSTEM_DIRECTORY_NAME
  1536. PWCHAR pTemp;
  1537. Len = wcslen ( pName );
  1538. if ( Len > 512 || Len==0 )
  1539. return FALSE; //too long or too small to patch
  1540. wcscpy (pBackup, pName ); // backup the name to keep case as it was
  1541. wcscpy (pBuff, pName );
  1542. _wcsupr (pBuff);
  1543. pLoc = pBuff;
  1544. for (;;) {
  1545. pTemp = wcsstr (pLoc, L"SYSTEM32"); //todo check if this should be case incensative
  1546. if (pTemp == NULL )
  1547. return bRet; //nothing to patch
  1548. //
  1549. // sanity check
  1550. //
  1551. Len = wcslen (L"SYSTEM32");
  1552. if ( pTemp[Len] != UNICODE_NULL ) {
  1553. if ( pTemp[Len] != L'\\' ) {
  1554. pLoc++;
  1555. continue; //only patch system32 or system32\?*
  1556. }
  1557. }
  1558. wcscpy (pName + (pTemp-pBuff), WOW64_SYSTEM_DIRECTORY_NAME );
  1559. wcscat (pName, pBackup + (pTemp-pBuff)+wcslen (L"SYSTEM32")) ;
  1560. pLoc++;
  1561. bRet = TRUE;
  1562. }
  1563. return TRUE;
  1564. }
  1565. BOOL
  1566. HandleRunonce(
  1567. PWCHAR pKeyName
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. Its a special case handling runonce key in the registry. Like 32bit apps can register
  1572. something that need to be reflected on the 64bit side so that right things happen.
  1573. Arguments:
  1574. pKeyName - name of the key, there might be multiple one like run, runonce, runonceex
  1575. Return Value:
  1576. TRUE if the function succeed.
  1577. FALSE otherwise.
  1578. --*/
  1579. {
  1580. WCHAR pName64[256];
  1581. HKEY Key1;
  1582. HKEY Key2;
  1583. Map32bitTo64bitKeyName ( pKeyName, pName64 );
  1584. if ( (Key1 = OpenNode ( pKeyName ) ) == NULL )
  1585. return FALSE;
  1586. if ( (Key2 = OpenNode ( pName64 ) ) == NULL ) {
  1587. RegCloseKey (Key1);
  1588. return FALSE;
  1589. }
  1590. Wow64RegDbgPrint ( ("\nCopying runonce Key %S", pKeyName));
  1591. //
  1592. // make source taking 64bit name
  1593. // Read check the timestamp on the source and the dest.
  1594. // If src is the newer copy content otherwise ignore it.
  1595. // PatchContent
  1596. //
  1597. MergeK1K2Value ( Key1, Key2, PATCH_PATHNAME | DELETE_VALUEKEY | NOT_MARK_SOURCE | NOT_MARK_DESTINATION );
  1598. return TRUE;
  1599. }