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.

1303 lines
42 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. wow64reg.c
  5. Abstract:
  6. This module implement some APIs for client who need to access registry in a mix way.
  7. The client need to link againest wow64reg.lib files. The available APIs has been defined
  8. in the wow64reg.h files.
  9. The possible scenario is
  10. 1. 32 bit Apps need to access 64 bit registry key.
  11. 2. 64 bit Apps need to access 32-bit registry key.
  12. 3. The actual redirected path from a given path.
  13. Author:
  14. ATM Shafiqul Khalid (askhalid) 10-Nov-1999
  15. Revision History:
  16. --*/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <ntregapi.h>
  23. #include <stdlib.h>
  24. #include "regremap.h"
  25. #include "wow64reg.h"
  26. #include "reflectr.h"
  27. #define WOW6432NODELEN 15
  28. VOID
  29. GetPatchedName (
  30. PWCHAR Dest,
  31. LPCTSTR Source,
  32. DWORD Count
  33. )
  34. /*++
  35. Routine Description:
  36. This function patches 32bit equivalent name from a given name and location to patch from.
  37. XX\ ==>> XX\Wow6432Node count==3
  38. XX ==>> XX\Wow6432Node count==2
  39. XX\PP ==>> XX\Wow6432Node count ==3
  40. Arguments:
  41. Dest - receive the result.
  42. Source - Name to patch
  43. Count - where to patch the string.
  44. Return Value:
  45. None.
  46. --*/
  47. {
  48. BOOL PerfectIsnNode = FALSE;
  49. if (Count) {
  50. wcsncpy ( Dest, Source, Count );
  51. if (Dest[Count-1] != L'\\' ) {
  52. Dest[Count] = L'\\'; // at the end case
  53. Count++;
  54. PerfectIsnNode = TRUE;
  55. }
  56. }
  57. wcscpy ( Dest+Count, NODE_NAME_32BIT );
  58. if ( !PerfectIsnNode ) {
  59. wcscat ( Dest, L"\\");
  60. wcscat ( Dest, Source + Count );
  61. }
  62. //
  63. // Make sure that the patched key are not on the exempt list.
  64. //
  65. }
  66. LONG
  67. Wow64RegOpenKeyEx(
  68. HKEY hKey,
  69. LPCTSTR lpSubKey,
  70. DWORD ulOptions,
  71. REGSAM samDesired,
  72. PHKEY phkResult
  73. )
  74. /*++
  75. Routine Description:
  76. This is the equivalent of RegOpenExW to access reggistry in the mix mode. This code will be
  77. compiled only for 64bit environment. In the 32bit environment WOW64 will take care of everything.
  78. We are nor worried much about performance hit due to opening key twice or retranslating path.
  79. Because only few people will access the registry in the mix mode.
  80. Arguments:
  81. hKey - handle to open key
  82. lpSubKey - address of name of subkey to open
  83. ulOptions - typically 0.
  84. samDesired - security access mask might have WOW64_RES flag
  85. KEY_WOW64_32KEY - this will open 32bit equivalent key disregarding
  86. the process.
  87. KEY_WOW64_64KEY - this will open 64bit equivalent key disregarding the process.
  88. phkResult -address of handle to open key
  89. Return Value:
  90. WIN32 Error code.
  91. --*/
  92. {
  93. OBJECT_ATTRIBUTES Obja;
  94. UNICODE_STRING Parent;
  95. WCHAR ParentName[WOW64_MAX_PATH+WOW6432NODELEN];
  96. WCHAR TempName[WOW64_MAX_PATH+WOW6432NODELEN];
  97. DWORD dwBuffLen = WOW64_MAX_PATH;
  98. DWORD dwSubKeyLen;
  99. DWORD dwParentKeyLen;
  100. WCHAR NullString;
  101. PWCHAR p32bitNode;
  102. PWCHAR pPatchLoc;
  103. PWCHAR pDivider;
  104. NTSTATUS st;
  105. BOOL bHandle64 = TRUE; // assume all the handle passed in is 64bit.
  106. if( lpSubKey == NULL ) {
  107. NullString = UNICODE_NULL;
  108. lpSubKey = &NullString;
  109. }
  110. //
  111. // check if the WOW64 reserve bit set. If none of them is set we can't proceede.
  112. //
  113. dwSubKeyLen = wcslen (lpSubKey);
  114. if (dwSubKeyLen > WOW64_MAX_PATH)
  115. return ERROR_INVALID_PARAMETER;
  116. {
  117. BOOL
  118. AdvapiAccessDenied (
  119. HKEY hKey,
  120. const WCHAR * lpSubKey,
  121. PWCHAR ParentName,
  122. DWORD dwLen,
  123. DWORD *pAccessMask,
  124. BOOL Flag
  125. );
  126. if ( samDesired & KEY_WOW64_32KEY){
  127. if (AdvapiAccessDenied (
  128. hKey,
  129. lpSubKey,
  130. ParentName,
  131. WOW64_MAX_PATH,
  132. &samDesired,
  133. FALSE
  134. ))
  135. return ERROR_ACCESS_DENIED;
  136. }
  137. }
  138. if (!(samDesired & KEY_WOW64_RES) ) {
  139. //
  140. // return ERROR_INVALID_PARAMETER; try to be optimistic
  141. //
  142. return RegOpenKeyEx (
  143. hKey,
  144. lpSubKey,
  145. ulOptions,
  146. samDesired,
  147. phkResult
  148. );
  149. }
  150. if( hKey == NULL ) {
  151. return ERROR_INVALID_HANDLE;
  152. }
  153. //
  154. // makesure that subkey doesn't have the special wow string
  155. //
  156. if ( ( p32bitNode = wcsistr ((PWCHAR)lpSubKey, NODE_NAME_32BIT)) != NULL ) {
  157. //
  158. // if access 64bit hive compress the subkey, if 32bit hive just pass as it is.
  159. //
  160. if ( samDesired & KEY_WOW64_64KEY ) {
  161. wcscpy (ParentName, lpSubKey);
  162. p32bitNode = ParentName + ( p32bitNode- lpSubKey);
  163. wcscpy ( p32bitNode, p32bitNode + NODE_NAME_32BIT_LEN );
  164. }
  165. return RegOpenKeyEx (
  166. hKey,
  167. ParentName,
  168. ulOptions,
  169. samDesired & (~KEY_WOW64_RES),
  170. phkResult
  171. );
  172. }
  173. //
  174. // Check predefined handle like HKEY_CLASSES_ROOT if so you only need to patch subkey
  175. //
  176. //
  177. // Client must pass meaningful handle to this function.
  178. //
  179. if ( hKey == HKEY_CLASSES_ROOT ) {
  180. wcscpy ( ParentName, MACHINE_CLASSES_ROOT);
  181. } else if ( !HandleToKeyName ( hKey, ParentName, &dwBuffLen ) ) {
  182. //
  183. // should we recoved from buffer overflow. We are not going to support all possible combination.
  184. //
  185. return ERROR_INVALID_HANDLE;
  186. }
  187. //
  188. // If parent has already been patched just call the RegOpenKeyEx for 32bit open
  189. //
  190. if ((p32bitNode = wcsistr (ParentName, NODE_NAME_32BIT)) != NULL ) {
  191. //
  192. // [todo] do you need to make sure that the substring mustbe the subkey
  193. // for an ISN node on 64bit registry to satisfy this condition.
  194. // if we assume that noy key will have this name then the checking is
  195. // good enough.
  196. //
  197. bHandle64 = FALSE; // it's not handle to 64 bit Key
  198. }
  199. //
  200. // Get complete qualified path to do sanity check.
  201. //
  202. dwParentKeyLen = wcslen(ParentName);
  203. if (( dwParentKeyLen + dwSubKeyLen ) > WOW64_MAX_PATH )
  204. return ERROR_INVALID_PARAMETER;
  205. pDivider = ParentName + dwParentKeyLen + 1; //point to the divider location
  206. *(pDivider-1)= L'\\';
  207. wcscpy (pDivider, (PWCHAR)lpSubKey);
  208. if (IsExemptRedirectedKey(ParentName, TempName)) {
  209. //
  210. // If the path is on the exempt list we access 64bit hive
  211. //
  212. samDesired = (samDesired & (~KEY_WOW64_RES)) | KEY_WOW64_64KEY; //make sure access 64bit hive
  213. }
  214. if ( ( bHandle64 && (samDesired & KEY_WOW64_64KEY ) ) // if totally 64
  215. || ( !bHandle64 && (samDesired & KEY_WOW64_32KEY ) ) // if totally 32
  216. || !IsIsnNode (ParentName, &pPatchLoc) ) { // if not a ISN node don't care
  217. return RegOpenKeyEx (
  218. hKey,
  219. lpSubKey,
  220. ulOptions,
  221. samDesired & (~KEY_WOW64_RES),
  222. phkResult
  223. );
  224. }
  225. //
  226. // Now it might be mix mode access
  227. //
  228. if ( pPatchLoc >= pDivider ) {
  229. //
  230. // patching only the subkey will be good enough
  231. //
  232. if ( samDesired & KEY_WOW64_64KEY ) { // want to access 64bit just disregard
  233. wcscpy ( ParentName, lpSubKey );
  234. } else {
  235. GetPatchedName (ParentName,lpSubKey, (DWORD)(pPatchLoc-pDivider) );
  236. }
  237. return RegOpenKeyEx (
  238. hKey,
  239. ParentName,
  240. ulOptions,
  241. samDesired & (~KEY_WOW64_RES),
  242. phkResult
  243. );
  244. } else {
  245. if ( samDesired & KEY_WOW64_64KEY ) { // want to access 64bit just disregard
  246. if (p32bitNode != NULL) //compress
  247. wcscpy ( p32bitNode, p32bitNode + NODE_NAME_32BIT_LEN );
  248. RtlInitUnicodeString (&Parent, ParentName );
  249. } else {
  250. GetPatchedName (TempName,ParentName, (DWORD)(pPatchLoc-ParentName));
  251. RtlInitUnicodeString (&Parent, TempName );
  252. }
  253. InitializeObjectAttributes (&Obja,
  254. &Parent,
  255. OBJ_CASE_INSENSITIVE,
  256. NULL,
  257. NULL
  258. );
  259. samDesired &= (~KEY_WOW64_RES);
  260. st = NtOpenKey (phkResult, samDesired, &Obja);
  261. if ( !NT_SUCCESS(st))
  262. return RtlNtStatusToDosError (st);
  263. return 0;
  264. }
  265. }
  266. LONG
  267. Wow64pRegCreateKeyEx(
  268. HKEY hKey, // handle to an open key
  269. LPCWSTR lpSubKey, // address of subkey name
  270. DWORD Reserved, // reserved
  271. LPWSTR lpClass, // address of class string
  272. DWORD dwOptions, // special options flag
  273. REGSAM samDesired, // desired security access
  274. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  275. // address of key security structure
  276. PHKEY phkResult, // address of buffer for opened handle
  277. LPDWORD lpdwDisposition, // address of disposition value buffer
  278. WCHAR *ParentName
  279. )
  280. /*++
  281. Routine Description:
  282. An existing registry key may be opened, or a new one created,
  283. with NtCreateKey.
  284. If the specified key does not exist, an attempt is made to create it.
  285. For the create attempt to succeed, the new node must be a direct
  286. child of the node referred to by KeyHandle. If the node exists,
  287. it is opened. Its value is not affected in any way.
  288. Share access is computed from desired access.
  289. NOTE:
  290. If CreateOptions has REG_OPTION_BACKUP_RESTORE set, then
  291. DesiredAccess will be ignored. If the caller has the
  292. privilege SeBackupPrivilege asserted, a handle with
  293. KEY_READ | ACCESS_SYSTEM_SECURITY will be returned.
  294. If SeRestorePrivilege, then same but KEY_WRITE rather
  295. than KEY_READ. If both, then both access sets. If neither
  296. privilege is asserted, then the call will fail.
  297. Arguments:
  298. hKey - Handle to a currently open key or one of the following predefined reserved
  299. handle values:
  300. HKEY_CLASSES_ROOT
  301. HKEY_CURRENT_CONFIG
  302. HKEY_CURRENT_USER
  303. HKEY_LOCAL_MACHINE
  304. HKEY_USERS
  305. The key opened or created by the RegCreateKeyEx function is a subkey of the key
  306. identified by the hKey parameter.
  307. lpSubKey - Pointer to a null-terminated string specifying the name of a subkey
  308. that this function opens or creates. The subkey specified must be a subkey of the
  309. key identified by the hKey parameter. This subkey must not begin with the backslash
  310. character ('\'). This parameter cannot be NULL.
  311. Reserved -Reserved; must be zero.
  312. lpClass - Pointer to a null-terminated string that specifies the class (object type)
  313. of this key. This parameter is ignored if the key already exists. No classes are
  314. currently defined; applications should pass a null string.
  315. dwOptions - Specifies special options for the key. This parameter can be one of the
  316. following values.
  317. REG_OPTION_NON_VOLATILE This key is not volatile. This is the default. The
  318. information is stored in a file and is preserved when the system is restarted.
  319. REG_OPTION_VOLATILE
  320. REG_OPTION_BACKUP_RESTORE Windows NT/2000: If this flag is set, the function
  321. ignores the samDesired parameter and attempts to open the key with the access
  322. required to backup or restore the key. If the calling thread has the
  323. SE_BACKUP_NAME privilege enabled, the key is opened with
  324. ACCESS_SYSTEM_SECURITY and KEY_READ access. If the calling thread
  325. has the SE_RESTORE_NAME privilege enabled, the key is opened with
  326. ACCESS_SYSTEM_SECURITY and KEY_WRITE access.
  327. If both privileges are enabled, the key has the combined accesses
  328. for both privileges.
  329. samDesired - Specifies an access mask that specifies the desired security access
  330. for the new key. This parameter can be a combination of the following values:
  331. KEY_ALL_ACCESS Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS,
  332. KEY_NOTIFY, KEY_CREATE_SUB_KEY, KEY_CREATE_LINK,
  333. and KEY_SET_VALUE access.
  334. KEY_CREATE_LINK Permission to create a symbolic link.
  335. KEY_CREATE_SUB_KEY Permission to create subkeys.
  336. KEY_ENUMERATE_SUB_KEYS Permission to enumerate subkeys.
  337. KEY_EXECUTE Permission for read access.
  338. KEY_NOTIFY Permission for change notification.
  339. KEY_QUERY_VALUE Permission to query subkey data.
  340. KEY_READ Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY access.
  341. KEY_SET_VALUE Permission to set subkey data.
  342. KEY_WRITE Combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY access.
  343. Security access mask might also have WOW64_RES flag
  344. KEY_WOW64_32KEY this will open 32bit equivalent key disregarding
  345. the process.
  346. KEY_WOW64_64KEY this will open 64bit equivalent key disregarding the process.
  347. lpSecurityAttributes - Pointer to a SECURITY_ATTRIBUTES structure that determines
  348. whether the returned handle can be inherited by child processes. If
  349. lpSecurityAttributes is NULL, the handle cannot be inherited.
  350. phkResult - Pointer to a variable that receives a handle to the opened or
  351. created key. When you no longer need the returned handle, call the RegCloseKey
  352. function to close it.
  353. lpdwDisposition - Pointer to a variable that receives one of the following
  354. disposition values: Value Meaning REG_CREATED_NEW_KEY The key did not exist
  355. and was created. REG_OPENED_EXISTING_KEY The key existed and was simply
  356. opened without being changed. If lpdwDisposition is NULL, no disposition
  357. information is returned.
  358. Return Values:
  359. If the function succeeds, the return value is ERROR_SUCCESS.
  360. If the function fails, the return value is a nonzero error code defined in WINERROR.H.
  361. --*/
  362. {
  363. OBJECT_ATTRIBUTES Obja;
  364. UNICODE_STRING Parent;
  365. WCHAR TempName[WOW64_MAX_PATH+WOW6432NODELEN];
  366. DWORD dwBuffLen = WOW64_MAX_PATH;
  367. DWORD dwSubKeyLen;
  368. DWORD dwParentKeyLen;
  369. PWCHAR p32bitNode;
  370. PWCHAR pPatchLoc;
  371. PWCHAR pDivider;
  372. NTSTATUS st;
  373. BOOL bHandle64 = TRUE; // assume all the handle passed in is 64bit.
  374. //
  375. // check if the WOW64 reserve bit set. If none of them is set we can't proceede.
  376. //
  377. dwSubKeyLen = wcslen (lpSubKey);
  378. if (dwSubKeyLen > WOW64_MAX_PATH)
  379. return ERROR_INVALID_PARAMETER;
  380. if (!(samDesired & KEY_WOW64_RES) ) {
  381. //
  382. // return ERROR_INVALID_PARAMETER; try to be optimistic
  383. //
  384. return RegCreateKeyEx (
  385. hKey, // handle to an open key
  386. lpSubKey, // address of subkey name
  387. Reserved, // reserved
  388. lpClass, // address of class string
  389. dwOptions, // special options flag
  390. samDesired, // desired security access
  391. lpSecurityAttributes,
  392. // address of key security structure
  393. phkResult, // address of buffer for opened handle
  394. lpdwDisposition // address of disposition value buffer
  395. );
  396. }
  397. if( hKey == NULL ) {
  398. return ERROR_INVALID_HANDLE;
  399. }
  400. //
  401. // makesure that subkey doesn't have the special wow string
  402. //
  403. if ( ( p32bitNode = wcsistr ((PWCHAR)lpSubKey, NODE_NAME_32BIT)) != NULL ) {
  404. //
  405. // if access 64bit hive compress the subkey, if 32bit hive just pass as it is.
  406. //
  407. if ( samDesired & KEY_WOW64_64KEY ) {
  408. wcscpy (ParentName, lpSubKey);
  409. p32bitNode = ParentName + ( p32bitNode- lpSubKey);
  410. wcscpy ( p32bitNode, p32bitNode + NODE_NAME_32BIT_LEN );
  411. }
  412. return RegCreateKeyEx (
  413. hKey, // handle to an open key
  414. lpSubKey, // address of subkey name
  415. Reserved, // reserved
  416. lpClass, // address of class string
  417. dwOptions, // special options flag
  418. samDesired & (~KEY_WOW64_RES), // desired security access
  419. lpSecurityAttributes,
  420. // address of key security structure
  421. phkResult, // address of buffer for opened handle
  422. lpdwDisposition // address of disposition value buffer
  423. );
  424. }
  425. //
  426. // Check predefined handle like HKEY_CLASSES_ROOT if so you only need to patch subkey
  427. //
  428. //
  429. // Client must pass meaningful handle to this function.
  430. //
  431. if ( hKey == HKEY_CLASSES_ROOT ) {
  432. wcscpy ( ParentName, MACHINE_CLASSES_ROOT);
  433. } else if ( !HandleToKeyName ( hKey, ParentName, &dwBuffLen ) ) {
  434. //
  435. // should we recoved from buffer overflow. We are not going to support all possible combination.
  436. //
  437. return ERROR_INVALID_HANDLE;
  438. }
  439. //
  440. // If parent has already been patched just call the RegOpenKeyEx for 32bit open
  441. //
  442. if ((p32bitNode = wcsistr (ParentName, NODE_NAME_32BIT)) != NULL ) {
  443. //
  444. // [todo] do you need to make sure that the substring mustbe the subkey
  445. // for an ISN node on 64bit registry to satisfy this condition.
  446. // if we assume that noy key will have this name then the checking is
  447. // good enough.
  448. //
  449. bHandle64 = FALSE; // it's not handle to 64 bit Key
  450. }
  451. //
  452. // Get complete qualified path to do sanity check.
  453. //
  454. dwParentKeyLen = wcslen(ParentName);
  455. if (( dwParentKeyLen + dwSubKeyLen ) > WOW64_MAX_PATH )
  456. return ERROR_INVALID_PARAMETER;
  457. pDivider = ParentName + dwParentKeyLen + 1; //point to the divider location
  458. *(pDivider-1)= L'\\';
  459. wcscpy (pDivider, (PWCHAR)lpSubKey);
  460. if (IsExemptRedirectedKey(ParentName, TempName)) {
  461. //
  462. // If the path is on the exempt list we access 64bit hive
  463. //
  464. samDesired = (samDesired & (~KEY_WOW64_RES)) | KEY_WOW64_64KEY; //make sure access 64bit hive
  465. }
  466. if ( ( bHandle64 && (samDesired & KEY_WOW64_64KEY ) ) // if totally 64
  467. || ( !bHandle64 && (samDesired & KEY_WOW64_32KEY ) ) // if totally 32
  468. || !IsIsnNode (ParentName, &pPatchLoc) ) { // if not a ISN node don't care
  469. return RegCreateKeyExW (
  470. hKey, // handle to an open key
  471. lpSubKey, // address of subkey name
  472. Reserved, // reserved
  473. lpClass, // address of class string
  474. dwOptions, // special options flag
  475. samDesired & (~KEY_WOW64_RES), // desired security access
  476. lpSecurityAttributes,
  477. // address of key security structure
  478. phkResult, // address of buffer for opened handle
  479. lpdwDisposition // address of disposition value buffer
  480. );
  481. }
  482. //
  483. // Now it might be mix mode access
  484. //
  485. if ( pPatchLoc >= pDivider ) {
  486. //
  487. // patching only the subkey will be good enough
  488. //
  489. if ( samDesired & KEY_WOW64_64KEY ) { // want to access 64bit just disregard
  490. wcscpy ( ParentName, lpSubKey );
  491. } else {
  492. GetPatchedName (ParentName,lpSubKey, (DWORD)(pPatchLoc-pDivider) );
  493. }
  494. return RegCreateKeyExW (
  495. hKey, // handle to an open key
  496. ParentName, // address of subkey name
  497. Reserved, // reserved
  498. lpClass, // address of class string
  499. dwOptions, // special options flag
  500. samDesired & (~KEY_WOW64_RES), // desired security access
  501. lpSecurityAttributes,
  502. // address of key security structure
  503. phkResult, // address of buffer for opened handle
  504. lpdwDisposition // address of disposition value buffer
  505. );
  506. } else {
  507. HKEY hNewParent = NULL;
  508. LONG Ret;
  509. PWCHAR pSubKey;
  510. //
  511. // get new handle on the parent and then create the child
  512. //
  513. if ( samDesired & KEY_WOW64_64KEY ) { // want to access 64bit just disregard
  514. if (p32bitNode != NULL) {//compress
  515. *(p32bitNode-1) = UNICODE_NULL;
  516. wcscpy ( p32bitNode, p32bitNode + NODE_NAME_32BIT_LEN +
  517. (p32bitNode[NODE_NAME_32BIT_LEN]==L'\\'? 1:0));
  518. }
  519. pSubKey = p32bitNode;
  520. RtlInitUnicodeString (&Parent, ParentName );
  521. } else {
  522. pSubKey = pPatchLoc;
  523. GetPatchedName (TempName,ParentName, (DWORD)(pPatchLoc-ParentName));
  524. TempName[pPatchLoc-ParentName+NODE_NAME_32BIT_LEN]=UNICODE_NULL; //repatch
  525. RtlInitUnicodeString (&Parent, TempName );
  526. }
  527. InitializeObjectAttributes (&Obja,
  528. &Parent,
  529. OBJ_CASE_INSENSITIVE,
  530. NULL,
  531. NULL
  532. );
  533. samDesired &= (~KEY_WOW64_RES);
  534. //
  535. // if key doesn't exist try to create
  536. // Try to avoid using NtOpenKey rather use RegOpenKey
  537. //
  538. st = NtOpenKey (&hNewParent,
  539. MAXIMUM_ALLOWED,
  540. &Obja);
  541. if ( !NT_SUCCESS(st))
  542. return RtlNtStatusToDosError (st);
  543. return RegCreateKeyExW (
  544. hNewParent, // handle to an open key
  545. pSubKey, // address of subkey name
  546. Reserved, // reserved
  547. lpClass, // address of class string
  548. dwOptions, // special options flag
  549. samDesired & (~KEY_WOW64_RES), // desired security access
  550. lpSecurityAttributes,
  551. // address of key security structure
  552. phkResult, // address of buffer for opened handle
  553. lpdwDisposition // address of disposition value buffer
  554. );
  555. NtClose (hNewParent);
  556. return 0;
  557. }
  558. }
  559. DWORD
  560. GetExistingParentLevel (
  561. PWCHAR Path
  562. )
  563. {
  564. NTSTATUS st;
  565. HANDLE hKey;
  566. HANDLE hKeyCreate;
  567. OBJECT_ATTRIBUTES Obja;
  568. UNICODE_STRING KeyName;
  569. PWCHAR pTrace;
  570. PWCHAR p;
  571. pTrace = Path+wcslen (Path); //pTrace point at the end of path
  572. p=pTrace;
  573. for (;;) {
  574. RtlInitUnicodeString (&KeyName, Path);
  575. InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
  576. st = NtOpenKey (&hKey, KEY_WRITE | KEY_READ, &Obja);
  577. if ( st == STATUS_OBJECT_NAME_NOT_FOUND ) {
  578. //backtrack until you hit the line
  579. while ( *p != L'\\' && p!= Path)
  580. p--;
  581. //LOGPRINT( (ERRORLOG, "\nTest Code[%S]",p ));
  582. if ( p == Path ) break;
  583. *p = UNICODE_NULL;
  584. continue;
  585. }
  586. break;
  587. }
  588. if (!NT_SUCCESS(st)) {
  589. return 0;
  590. }
  591. //
  592. // Point to the code
  593. //
  594. return wcslen (Path);
  595. }
  596. BOOL
  597. UpdateKeyTagWithLevel (
  598. HKEY hKey,
  599. DWORD Tag,
  600. DWORD dwLevel,
  601. PWCHAR ParentName
  602. )
  603. {
  604. PWCHAR p;
  605. HKEY hKeyTemp;
  606. UpdateKeyTag(hKey, Tag);
  607. if ( dwLevel == 0) {
  608. return TRUE;
  609. }
  610. p = &ParentName [dwLevel];
  611. if (*p != L'\\')
  612. return FALSE;
  613. for (;;) {
  614. while (*(++p) != L'\\' && *p != UNICODE_NULL)
  615. ;
  616. if (*p == L'\\')
  617. *p = UNICODE_NULL;
  618. else
  619. return TRUE;
  620. //DbgPrint ("Updating Key Tag [%S]", ParentName);
  621. hKeyTemp = OpenNode (ParentName);
  622. UpdateKeyTag(hKeyTemp, Tag);
  623. NtClose (hKeyTemp);
  624. *p = L'\\';
  625. }
  626. }
  627. LONG
  628. Wow64RegCreateKeyEx(
  629. HKEY hKey, // handle to an open key
  630. LPCWSTR lpSubKey, // address of subkey name
  631. DWORD Reserved, // reserved
  632. LPWSTR lpClass, // address of class string
  633. DWORD dwOptions, // special options flag
  634. REGSAM samDesired, // desired security access
  635. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  636. // address of key security structure
  637. PHKEY phkResult, // address of buffer for opened handle
  638. LPDWORD lpdwDisposition // address of disposition value buffer
  639. )
  640. /*++
  641. Routine Description:
  642. An existing registry key may be opened, or a new one created,
  643. with NtCreateKey.
  644. If the specified key does not exist, an attempt is made to create it.
  645. For the create attempt to succeed, the new node must be a direct
  646. child of the node referred to by KeyHandle. If the node exists,
  647. it is opened. Its value is not affected in any way.
  648. Share access is computed from desired access.
  649. NOTE:
  650. If CreateOptions has REG_OPTION_BACKUP_RESTORE set, then
  651. DesiredAccess will be ignored. If the caller has the
  652. privilege SeBackupPrivilege asserted, a handle with
  653. KEY_READ | ACCESS_SYSTEM_SECURITY will be returned.
  654. If SeRestorePrivilege, then same but KEY_WRITE rather
  655. than KEY_READ. If both, then both access sets. If neither
  656. privilege is asserted, then the call will fail.
  657. Arguments:
  658. hKey - Handle to a currently open key or one of the following predefined reserved
  659. handle values:
  660. HKEY_CLASSES_ROOT
  661. HKEY_CURRENT_CONFIG
  662. HKEY_CURRENT_USER
  663. HKEY_LOCAL_MACHINE
  664. HKEY_USERS
  665. The key opened or created by the RegCreateKeyEx function is a subkey of the key
  666. identified by the hKey parameter.
  667. lpSubKey - Pointer to a null-terminated string specifying the name of a subkey
  668. that this function opens or creates. The subkey specified must be a subkey of the
  669. key identified by the hKey parameter. This subkey must not begin with the backslash
  670. character ('\'). This parameter cannot be NULL.
  671. Reserved -Reserved; must be zero.
  672. lpClass - Pointer to a null-terminated string that specifies the class (object type)
  673. of this key. This parameter is ignored if the key already exists. No classes are
  674. currently defined; applications should pass a null string.
  675. dwOptions - Specifies special options for the key. This parameter can be one of the
  676. following values.
  677. REG_OPTION_NON_VOLATILE This key is not volatile. This is the default. The
  678. information is stored in a file and is preserved when the system is restarted.
  679. REG_OPTION_VOLATILE
  680. REG_OPTION_BACKUP_RESTORE Windows NT/2000: If this flag is set, the function
  681. ignores the samDesired parameter and attempts to open the key with the access
  682. required to backup or restore the key. If the calling thread has the
  683. SE_BACKUP_NAME privilege enabled, the key is opened with
  684. ACCESS_SYSTEM_SECURITY and KEY_READ access. If the calling thread
  685. has the SE_RESTORE_NAME privilege enabled, the key is opened with
  686. ACCESS_SYSTEM_SECURITY and KEY_WRITE access.
  687. If both privileges are enabled, the key has the combined accesses
  688. for both privileges.
  689. samDesired - Specifies an access mask that specifies the desired security access
  690. for the new key. This parameter can be a combination of the following values:
  691. KEY_ALL_ACCESS Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS,
  692. KEY_NOTIFY, KEY_CREATE_SUB_KEY, KEY_CREATE_LINK,
  693. and KEY_SET_VALUE access.
  694. KEY_CREATE_LINK Permission to create a symbolic link.
  695. KEY_CREATE_SUB_KEY Permission to create subkeys.
  696. KEY_ENUMERATE_SUB_KEYS Permission to enumerate subkeys.
  697. KEY_EXECUTE Permission for read access.
  698. KEY_NOTIFY Permission for change notification.
  699. KEY_QUERY_VALUE Permission to query subkey data.
  700. KEY_READ Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY access.
  701. KEY_SET_VALUE Permission to set subkey data.
  702. KEY_WRITE Combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY access.
  703. Security access mask might also have WOW64_RES flag
  704. KEY_WOW64_32KEY this will open 32bit equivalent key disregarding
  705. the process.
  706. KEY_WOW64_64KEY this will open 64bit equivalent key disregarding the process.
  707. lpSecurityAttributes - Pointer to a SECURITY_ATTRIBUTES structure that determines
  708. whether the returned handle can be inherited by child processes. If
  709. lpSecurityAttributes is NULL, the handle cannot be inherited.
  710. phkResult - Pointer to a variable that receives a handle to the opened or
  711. created key. When you no longer need the returned handle, call the RegCloseKey
  712. function to close it.
  713. lpdwDisposition - Pointer to a variable that receives one of the following
  714. disposition values: Value Meaning REG_CREATED_NEW_KEY The key did not exist
  715. and was created. REG_OPENED_EXISTING_KEY The key existed and was simply
  716. opened without being changed. If lpdwDisposition is NULL, no disposition
  717. information is returned.
  718. Return Values:
  719. If the function succeeds, the return value is ERROR_SUCCESS.
  720. If the function fails, the return value is a nonzero error code defined in WINERROR.H.
  721. --*/
  722. {
  723. DWORD Ret;
  724. DWORD Temp = 0;
  725. DWORD dwLevel;
  726. DWORD dwLen;
  727. WCHAR ParentName[WOW64_MAX_PATH+WOW6432NODELEN];
  728. if (lpdwDisposition == NULL) {
  729. lpdwDisposition = &Temp;
  730. }
  731. if ( samDesired & KEY_WOW64_32KEY){
  732. dwLen = WOW64_MAX_PATH;
  733. ParentName[0]= UNICODE_NULL;
  734. HandleToKeyName ( hKey, ParentName, &dwLen);
  735. dwLen = wcslen (lpSubKey);
  736. if (dwLen>1) {
  737. wcscat (ParentName, L"\\");
  738. wcscat (ParentName, lpSubKey);
  739. }
  740. if (AdvapiAccessDenied (
  741. hKey,
  742. lpSubKey,
  743. ParentName,
  744. WOW64_MAX_PATH,
  745. &samDesired,
  746. TRUE
  747. ))
  748. return ERROR_ACCESS_DENIED;
  749. //
  750. // Check how many level parent keys exists so that KeyTag can be updated properly.
  751. //
  752. dwLevel = GetExistingParentLevel (ParentName);
  753. }
  754. Ret = Wow64pRegCreateKeyEx(
  755. hKey, // handle to an open key
  756. lpSubKey, // address of subkey name
  757. Reserved, // reserved
  758. lpClass, // address of class string
  759. dwOptions, // special options flag
  760. samDesired, // desired security access
  761. lpSecurityAttributes,// address of key security structure
  762. phkResult, // address of buffer for opened handle
  763. lpdwDisposition, // address of disposition value buffer
  764. ParentName
  765. );
  766. //
  767. // If this is a newly created key and 32bit flag is passed in then you must set the owner
  768. //
  769. if ( (Ret == ERROR_SUCCESS) && (*lpdwDisposition == REG_CREATED_NEW_KEY) && ( samDesired & KEY_WOW64_32KEY )) {
  770. //
  771. // Sometimes caller create multiple Keys in a single call.
  772. // Need to determine what node has been created
  773. //
  774. dwLen = WOW64_MAX_PATH;
  775. ParentName[0]= UNICODE_NULL;
  776. HandleToKeyName ( hKey, ParentName, &dwLen);
  777. dwLen = wcslen (lpSubKey);
  778. if (dwLen>1) {
  779. wcscat (ParentName, L"\\");
  780. wcscat (ParentName, lpSubKey);
  781. }
  782. //DbgPrint ("ADVAPI:Created a new key with tag: [%S]", lpSubKey);
  783. UpdateKeyTagWithLevel ( *phkResult,TAG_KEY_ATTRIBUTE_32BIT_WRITE,dwLevel, ParentName );
  784. }
  785. return Ret;
  786. }
  787. BOOL
  788. Wow64RegNotifyLoadHive (
  789. PWCHAR Name
  790. )
  791. /*++
  792. Routine Description:
  793. This function will Notify running Wow64 Service that some hive has been loaded in the
  794. system. Wow64 should respond if it care to handle this.
  795. Arguments:
  796. Name - Absolute path of the registry that has been loaded.
  797. Return Value:
  798. TRUE if everything under the has been deleted.
  799. FALSE otherwise.
  800. failure scenarion:
  801. Wow64 service isn't running.
  802. there is nothing the caller do, there for this will be a non blocking call.
  803. In the future caller should try to lunch the service...<TBD>
  804. --*/
  805. {
  806. DWORD Ret;
  807. HANDLE hEvent;
  808. if (!CreateSharedMemory ( OPEN_EXISTING_SHARED_RESOURCES )) {
  809. Wow64RegDbgPrint ( ("\nSorry! Couldn't open shared memory Ret:%d", GetLastError ()) );
  810. return FALSE;
  811. }
  812. if (!Wow64CreateEvent ( OPEN_EXISTING_SHARED_RESOURCES, &hEvent) ) {
  813. CloseSharedMemory ();
  814. Wow64RegDbgPrint ( ("\nSorry! couldn't open event to ping reflector..") );
  815. return FALSE;
  816. }
  817. Ret = EnQueueObject ( Name, HIVE_LOADING);
  818. CloseSharedMemory ();
  819. Wow64CloseEvent ();
  820. return Ret;
  821. }
  822. BOOL
  823. Wow64RegNotifyUnloadHive (
  824. PWCHAR Name
  825. )
  826. /*++
  827. Routine Description:
  828. This function will Notify running Wow64 Service that some hive going to be unloaded
  829. in the system. Wow64 should respond if it care to handle this. Normally Wow64 will
  830. close any open handle to that hive.
  831. Arguments:
  832. Name - Absolute path of the registry that going to unloaded.
  833. Return Value:
  834. TRUE if everything under the has been deleted.
  835. FALSE otherwise.
  836. failure scenarion:
  837. Wow64 service isn't running.
  838. there is nothing the caller do, there for this will be a non blocking call.
  839. In the future caller should try to lunch the service...<TBD>
  840. --*/
  841. {
  842. DWORD Ret;
  843. HANDLE hEvent;
  844. if (!CreateSharedMemory ( OPEN_EXISTING_SHARED_RESOURCES )) {
  845. Wow64RegDbgPrint ( ("\nSorry! Couldn't open shared memory Ret:%d", GetLastError ()));
  846. return FALSE;
  847. }
  848. if (!Wow64CreateEvent ( OPEN_EXISTING_SHARED_RESOURCES, &hEvent) ) {
  849. CloseSharedMemory ();
  850. Wow64RegDbgPrint ( ("\nSorry! couldn't open event to ping reflector..") );
  851. return FALSE;
  852. }
  853. Ret = EnQueueObject ( Name, HIVE_UNLOADING);
  854. CloseSharedMemory ();
  855. Wow64CloseEvent ();
  856. return Ret;
  857. }
  858. BOOL
  859. Wow64RegNotifyLoadHiveByHandle (
  860. HKEY hKey
  861. )
  862. /*++
  863. Routine Description:
  864. This function will Notify running Wow64 Service that some hive has been loaded in the
  865. system. Wow64 should respond if it care to handle this.
  866. Arguments:
  867. hKey - handle to the key that has been loaded.
  868. Return Value:
  869. TRUE if everything under the has been deleted.
  870. FALSE otherwise.
  871. failure scenarion:
  872. Wow64 service isn't running.
  873. there is nothing the caller do, there for this will be a non blocking call.
  874. In the future caller should try to lunch the service...<TBD>
  875. --*/
  876. {
  877. WCHAR Name [256];
  878. DWORD Len = 256;
  879. if (!HandleToKeyName ( hKey, Name, &Len ))
  880. return FALSE;
  881. return Wow64RegNotifyLoadHive( Name );
  882. }
  883. BOOL
  884. Wow64RegNotifyUnloadHiveByHandle (
  885. HKEY hKey
  886. )
  887. /*++
  888. Routine Description:
  889. This function will Notify running Wow64 Service that some hive going to be unloaded
  890. in the system. Wow64 should respond if it care to handle this. Normally Wow64 will
  891. close any open handle to that hive.
  892. Arguments:
  893. hKey - handle to the key that going to unloaded.
  894. Return Value:
  895. TRUE if everything under the has been deleted.
  896. FALSE otherwise.
  897. failure scenarion:
  898. Wow64 service isn't running.
  899. there is nothing the caller do, there for this will be a non blocking call.
  900. In the future caller should try to lunch the service...<TBD>
  901. --*/
  902. {
  903. WCHAR Name [256];
  904. DWORD Len = 256;
  905. if (!HandleToKeyName ( hKey, Name, &Len ))
  906. return FALSE;
  907. return Wow64RegNotifyUnloadHive( Name );
  908. }
  909. BOOL
  910. Wow64RegNotifyLoadHiveUserSid (
  911. PWCHAR lpwUserSid
  912. )
  913. /*++
  914. Routine Description:
  915. This function will Notify running Wow64 Service that some hive has been loaded in the
  916. system. Wow64 should respond if it care to handle this.
  917. Arguments:
  918. hKey - handle to the key that has been loaded.
  919. Return Value:
  920. TRUE if everything under the has been deleted.
  921. FALSE otherwise.
  922. failure scenarion:
  923. Wow64 service isn't running.
  924. there is nothing the caller do, there for this will be a non blocking call.
  925. In the future caller should try to lunch the service...<TBD>
  926. --*/
  927. {
  928. WCHAR Name [256];
  929. HKEY hUserRoot;
  930. wcscpy (Name, L"\\REGISTRY\\USER\\");
  931. wcscat (Name, lpwUserSid );
  932. if (wcsistr (Name, L"_Classes")) {
  933. wcscat (Name, L"\\Wow6432Node");
  934. hUserRoot = OpenNode (Name);
  935. //
  936. // DbgPrint ("\nWow64:Creating Hive %S",Name);
  937. //
  938. // Create the 32bit user hive if applicable
  939. //
  940. if ( hUserRoot == NULL ) {
  941. CreateNode (Name);
  942. } else
  943. NtClose (hUserRoot);
  944. }
  945. return TRUE;
  946. //return Wow64RegNotifyLoadHive( Name );
  947. }
  948. BOOL
  949. Wow64RegNotifyUnloadHiveUserSid (
  950. PWCHAR lpwUserSid
  951. )
  952. /*++
  953. Routine Description:
  954. This function will Notify running Wow64 Service that some hive going to be unloaded
  955. in the system. Wow64 should respond if it care to handle this. Normally Wow64 will
  956. close any open handle to that hive.
  957. Arguments:
  958. hKey - handle to the key that going to unloaded.
  959. Return Value:
  960. TRUE if everything under the has been deleted.
  961. FALSE otherwise.
  962. failure scenarion:
  963. Wow64 service isn't running.
  964. there is nothing the caller do, there for this will be a non blocking call.
  965. In the future caller should try to lunch the service...<TBD>
  966. --*/
  967. {
  968. WCHAR Name [256];
  969. wcscpy (Name, L"\\REGISTRY\\USER\\");
  970. wcscat (Name, lpwUserSid );
  971. //
  972. //return Wow64RegNotifyUnloadHive( Name );
  973. //
  974. return TRUE;
  975. }