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.

1341 lines
29 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. Regkey.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 Registry
  7. APIs to open, create, flush and close keys. That is:
  8. - RegCloseKey
  9. - RegCreateKeyA
  10. - RegCreateKeyW
  11. - RegCreateKeyExA
  12. - RegCreateKeyExW
  13. - RegFlushKey
  14. - RegOpenKeyA
  15. - RegOpenKeyW
  16. - RegOpenKeyExA
  17. - RegOpenKeyExW
  18. - RegOverridePredefKey
  19. - RegOpenCurrentUser
  20. Author:
  21. David J. Gilman (davegi) 15-Nov-1991
  22. Notes:
  23. See the notes in server\regkey.c.
  24. --*/
  25. #include <rpc.h>
  26. #include "regrpc.h"
  27. #include "client.h"
  28. #include <wow64reg.h>
  29. #if defined(LEAK_TRACK)
  30. NTSTATUS TrackObject(HKEY hKey);
  31. #endif // defined(LEAK_TRACK)
  32. NTSTATUS DisablePredefinedHandleTable(HKEY Handle);
  33. LONG
  34. APIENTRY
  35. RegCloseKey (
  36. IN HKEY hKey
  37. )
  38. /*++
  39. Routine Description:
  40. Win32 RPC wrapper for closeing a key handle.
  41. --*/
  42. {
  43. #if DBG
  44. if ( BreakPointOnEntry ) {
  45. DbgBreakPoint();
  46. }
  47. #endif
  48. if( hKey == NULL ) {
  49. return ERROR_INVALID_HANDLE;
  50. }
  51. if( IsPredefinedRegistryHandle( hKey )) {
  52. return( ClosePredefinedHandle( hKey ) );
  53. }
  54. if( IsLocalHandle( hKey )) {
  55. #if defined(_WIN64)
  56. Wow64RegCloseKey (hKey);
  57. #endif
  58. return ( LONG ) LocalBaseRegCloseKey( &hKey );
  59. } else {
  60. hKey = DereferenceRemoteHandle( hKey );
  61. return ( LONG ) BaseRegCloseKey( &hKey );
  62. }
  63. }
  64. LONG
  65. APIENTRY
  66. RegOverridePredefKey (
  67. IN HKEY hKey,
  68. IN HKEY hNewKey
  69. )
  70. /*++
  71. Routine Description:
  72. Win32 wrapper to override the normal value for a predefined key.
  73. --*/
  74. {
  75. #if DBG
  76. if ( BreakPointOnEntry ) {
  77. DbgBreakPoint();
  78. }
  79. #endif
  80. if( hKey == NULL ) {
  81. return ERROR_INVALID_HANDLE;
  82. }
  83. if( !IsPredefinedRegistryHandle( hKey )) {
  84. return ERROR_INVALID_HANDLE;
  85. }
  86. {
  87. NTSTATUS Status;
  88. Status = RemapPredefinedHandle( hKey, hNewKey );
  89. return RtlNtStatusToDosError( Status );
  90. }
  91. }
  92. LONG
  93. APIENTRY
  94. RegCreateKeyA (
  95. HKEY hKey,
  96. LPCSTR lpSubKey,
  97. PHKEY phkResult
  98. )
  99. /*++
  100. Routine Description:
  101. Win 3.1 ANSI RPC wrapper for opening an existing key or creating a new one.
  102. --*/
  103. {
  104. LONG Error;
  105. #if DBG
  106. if ( BreakPointOnEntry ) {
  107. DbgBreakPoint();
  108. }
  109. #endif
  110. //
  111. // Win3.1ism - Win 3.1 allows the predefined handle to be opened by
  112. // specifying a pointer to an empty or NULL string for the sub-key.
  113. //
  114. //
  115. // If the subkey is NULL or points to a NUL string and the handle is
  116. // predefined, just return the predefined handle (a virtual open)
  117. // otherwise it's an error.
  118. //
  119. if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
  120. if( IsPredefinedRegistryHandle( hKey )) {
  121. *phkResult = hKey;
  122. return ERROR_SUCCESS;
  123. } else {
  124. return ERROR_BADKEY;
  125. }
  126. }
  127. Error = (LONG)RegCreateKeyExA(
  128. hKey,
  129. lpSubKey,
  130. 0,
  131. WIN31_CLASS,
  132. REG_OPTION_NON_VOLATILE,
  133. WIN31_REGSAM,
  134. NULL,
  135. phkResult,
  136. NULL
  137. );
  138. return Error;
  139. }
  140. LONG
  141. APIENTRY
  142. RegCreateKeyW (
  143. HKEY hKey,
  144. LPCWSTR lpSubKey,
  145. PHKEY phkResult
  146. )
  147. /*++
  148. Routine Description:
  149. Win 3.1 Unicode RPC wrapper for opening an existing key or creating a
  150. new one.
  151. --*/
  152. {
  153. LONG Error;
  154. #if DBG
  155. if ( BreakPointOnEntry ) {
  156. DbgBreakPoint();
  157. }
  158. #endif
  159. Error = (LONG)RegCreateKeyExW(
  160. hKey,
  161. lpSubKey,
  162. 0,
  163. WIN31_CLASS,
  164. REG_OPTION_NON_VOLATILE,
  165. WIN31_REGSAM,
  166. NULL,
  167. phkResult,
  168. NULL
  169. );
  170. return Error;
  171. }
  172. LONG
  173. APIENTRY
  174. RegCreateKeyExA (
  175. HKEY hKey,
  176. LPCSTR lpSubKey,
  177. DWORD Reserved,
  178. LPSTR lpClass,
  179. DWORD dwOptions,
  180. REGSAM samDesired,
  181. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  182. PHKEY phkResult,
  183. LPDWORD lpdwDisposition
  184. )
  185. /*++
  186. Routine Description:
  187. Win32 ANSI RPC wrapper for opening an existing key or creating a new one.
  188. RegCreateKeyExA converts the LPSECURITY_ATTRIBUTES argument to a
  189. RPC_SECURITY_ATTRIBUTES argument and calls BaseRegCreateKeyExA.
  190. --*/
  191. {
  192. UNICODE_STRING SubKey;
  193. UNICODE_STRING ClassUnicode;
  194. PUNICODE_STRING Class;
  195. ANSI_STRING AnsiString;
  196. PRPC_SECURITY_ATTRIBUTES pRpcSA;
  197. RPC_SECURITY_ATTRIBUTES RpcSA;
  198. NTSTATUS Status;
  199. LONG Error;
  200. HKEY TempHandle = NULL;
  201. #if DBG
  202. if ( BreakPointOnEntry ) {
  203. OutputDebugString( "In RegCreateKeyExA\n" );
  204. DbgBreakPoint();
  205. }
  206. #endif
  207. //
  208. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  209. //
  210. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  211. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  212. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  213. return ERROR_INVALID_HANDLE;
  214. }
  215. //
  216. // Ensure Reserved is zero to avoid future compatability problems.
  217. //
  218. if( Reserved != 0 ) {
  219. return ERROR_INVALID_PARAMETER;
  220. }
  221. //
  222. // Validate that the sub key is not NULL.
  223. //
  224. if( ! lpSubKey ) {
  225. return ERROR_BADKEY;
  226. }
  227. hKey = MapPredefinedHandle( hKey, &TempHandle );
  228. if( hKey == NULL ) {
  229. Error = ERROR_INVALID_HANDLE;
  230. goto ExitCleanup;
  231. }
  232. //
  233. // Convert the subkey to a counted Unicode string
  234. //
  235. if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
  236. Status = STATUS_NO_MEMORY;
  237. Error = RtlNtStatusToDosError( Status );
  238. goto ExitCleanup;
  239. }
  240. //
  241. // Add size of NULL so that RPC transmits the right
  242. // stuff.
  243. //
  244. SubKey.Length += sizeof( UNICODE_NULL );
  245. if (ARGUMENT_PRESENT( lpClass )) {
  246. //
  247. // Convert the class name to a counted Unicode string using a counted
  248. // Unicode string dynamically allocated by RtlAnsiStringToUnicodeString.
  249. //
  250. RtlInitAnsiString( &AnsiString, lpClass );
  251. Status = RtlAnsiStringToUnicodeString(
  252. &ClassUnicode,
  253. &AnsiString,
  254. TRUE
  255. );
  256. if( ! NT_SUCCESS( Status )) {
  257. Error = RtlNtStatusToDosError( Status );
  258. RtlFreeUnicodeString( &SubKey );
  259. goto ExitCleanup;
  260. }
  261. Class = &ClassUnicode;
  262. Class->Length += sizeof( UNICODE_NULL );
  263. } else {
  264. Class = &ClassUnicode;
  265. Class->Length = 0;
  266. Class->MaximumLength = 0;
  267. Class->Buffer = NULL;
  268. }
  269. //
  270. // If the caller supplied a LPSECURITY_ATTRIBUTES argument, map
  271. // it to the RPCable version.
  272. //
  273. if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
  274. pRpcSA = &RpcSA;
  275. Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
  276. if( Error != ERROR_SUCCESS ) {
  277. RtlFreeUnicodeString( &SubKey );
  278. goto ExitCleanup;
  279. }
  280. } else {
  281. //
  282. // No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
  283. //
  284. pRpcSA = NULL;
  285. }
  286. //
  287. // Call the Base API, passing it the supplied parameters and the
  288. // counted Unicode strings.
  289. //
  290. if( IsLocalHandle( hKey )) {
  291. #if defined(_WIN64)
  292. DWORD dwTempDisposition = 0;
  293. if ( lpdwDisposition == NULL )
  294. lpdwDisposition = &dwTempDisposition;
  295. //
  296. // if wow64 reserve field is set in the access mask, call
  297. // wow64 function to handle the scenario.
  298. //
  299. if ( samDesired & KEY_WOW64_RES ) {
  300. Error = (LONG)Wow64RegCreateKeyEx (
  301. hKey,
  302. SubKey.Buffer,
  303. 0, //reserved
  304. Class->Buffer,
  305. dwOptions,
  306. samDesired,
  307. lpSecurityAttributes,
  308. phkResult,
  309. lpdwDisposition
  310. );
  311. } else
  312. #endif
  313. Error = (LONG)LocalBaseRegCreateKey (
  314. hKey,
  315. &SubKey,
  316. Class,
  317. dwOptions,
  318. samDesired,
  319. pRpcSA,
  320. phkResult,
  321. lpdwDisposition
  322. );
  323. #if defined(_WIN64)
  324. if ( ( Error == 0) && ( REG_CREATED_NEW_KEY & *lpdwDisposition) ) //only set dirty if its a newly created key
  325. Wow64RegSetKeyDirty (*phkResult);
  326. #endif
  327. } else {
  328. Error = (LONG)BaseRegCreateKey (
  329. DereferenceRemoteHandle( hKey ),
  330. &SubKey,
  331. Class,
  332. dwOptions,
  333. samDesired,
  334. pRpcSA,
  335. phkResult,
  336. lpdwDisposition
  337. );
  338. if( Error == ERROR_SUCCESS) {
  339. TagRemoteHandle( phkResult );
  340. }
  341. }
  342. //
  343. // Free the counted Unicode string allocated by
  344. // RtlAnsiStringToUnicodeString.
  345. //
  346. if (Class != NULL) {
  347. RtlFreeUnicodeString( Class );
  348. }
  349. //
  350. // Free the RPC_SECURITY_DESCRIPTOR buffer and return the
  351. // Registry return value.
  352. //
  353. if( pRpcSA != NULL ) {
  354. RtlFreeHeap(
  355. RtlProcessHeap( ), 0,
  356. pRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor
  357. );
  358. }
  359. RtlFreeUnicodeString( &SubKey );
  360. ExitCleanup:
  361. CLOSE_LOCAL_HANDLE(TempHandle);
  362. return Error;
  363. }
  364. LONG
  365. APIENTRY
  366. RegCreateKeyExW (
  367. HKEY hKey,
  368. LPCWSTR lpSubKey,
  369. DWORD Reserved,
  370. LPWSTR lpClass,
  371. DWORD dwOptions,
  372. REGSAM samDesired,
  373. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  374. PHKEY phkResult,
  375. LPDWORD lpdwDisposition
  376. )
  377. /*++
  378. Routine Description:
  379. Win32 Unicode RPC wrapper for opening an existing key or creating a new one.
  380. RegCreateKeyExW converts the LPSECURITY_ATTRIBUTES argument to a
  381. RPC_SECURITY_ATTRIBUTES argument and calls BaseRegCreateKeyExW.
  382. --*/
  383. {
  384. UNICODE_STRING SubKey;
  385. UNICODE_STRING ClassUnicode;
  386. PUNICODE_STRING Class;
  387. PRPC_SECURITY_ATTRIBUTES pRpcSA;
  388. RPC_SECURITY_ATTRIBUTES RpcSA;
  389. LONG Error;
  390. PWSTR AuxBuffer;
  391. HKEY TempHandle = NULL;
  392. #if DBG
  393. if ( BreakPointOnEntry ) {
  394. DbgBreakPoint();
  395. }
  396. #endif
  397. //
  398. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  399. //
  400. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  401. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  402. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  403. return ERROR_INVALID_HANDLE;
  404. }
  405. //
  406. // Ensure Reserved is zero to avoid future compatability problems.
  407. //
  408. if( Reserved != 0 ) {
  409. return ERROR_INVALID_PARAMETER;
  410. }
  411. //
  412. // Validate that the sub key is not NULL.
  413. //
  414. if( ! lpSubKey ) {
  415. return ERROR_BADKEY;
  416. }
  417. hKey = MapPredefinedHandle( hKey, &TempHandle );
  418. if( hKey == NULL ) {
  419. Error = ERROR_INVALID_HANDLE;
  420. goto ExitCleanup;
  421. }
  422. //
  423. // Convert the subkey to a counted Unicode string.
  424. //
  425. RtlInitUnicodeString( &SubKey, lpSubKey );
  426. //
  427. // Add terminating NULL to Length so that RPC transmits it.
  428. //
  429. SubKey.Length += sizeof( UNICODE_NULL );
  430. if( SubKey.Length == 0 ) {
  431. //
  432. // overflow in RtlInitUnicodeString
  433. //
  434. Error = ERROR_INVALID_PARAMETER;
  435. goto ExitCleanup;
  436. }
  437. if (ARGUMENT_PRESENT( lpClass )) {
  438. //
  439. // Convert the class name to a counted Unicode string.
  440. //
  441. RtlInitUnicodeString( &ClassUnicode, lpClass );
  442. Class = &ClassUnicode;
  443. Class->Length += sizeof( UNICODE_NULL );
  444. } else {
  445. Class = &ClassUnicode;
  446. Class->Length = 0;
  447. Class->MaximumLength = 0;
  448. Class->Buffer = NULL;
  449. }
  450. //
  451. // If the caller supplied a LPSECURITY_ATTRIBUTES argument, map
  452. // it and call the private version of the create key API.
  453. //
  454. if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
  455. pRpcSA = &RpcSA;
  456. Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
  457. if( Error != ERROR_SUCCESS ) {
  458. goto ExitCleanup;
  459. }
  460. } else {
  461. //
  462. // No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
  463. //
  464. pRpcSA = NULL;
  465. }
  466. //
  467. // Call the Base API, passing it the supplied parameters and the
  468. // counted Unicode strings.
  469. //
  470. if( IsLocalHandle( hKey )) {
  471. #if defined(_WIN64)
  472. DWORD dwTempDisposition = 0;
  473. if ( lpdwDisposition == NULL )
  474. lpdwDisposition = &dwTempDisposition;
  475. //
  476. // if wow64 reserve field is set in the access mask, call
  477. // wow64 function to handle the scenario.
  478. //
  479. if ( samDesired & KEY_WOW64_RES ) {
  480. Error = (LONG)Wow64RegCreateKeyEx (
  481. hKey,
  482. SubKey.Buffer,
  483. 0, //reserved
  484. Class->Buffer,
  485. dwOptions,
  486. samDesired,
  487. lpSecurityAttributes,
  488. phkResult,
  489. lpdwDisposition
  490. );
  491. } else
  492. #endif
  493. Error = (LONG)LocalBaseRegCreateKey (
  494. hKey,
  495. &SubKey,
  496. Class,
  497. dwOptions,
  498. samDesired,
  499. pRpcSA,
  500. phkResult,
  501. lpdwDisposition
  502. );
  503. #if defined(_WIN64)
  504. if ( ( Error == 0) && ( REG_CREATED_NEW_KEY & *lpdwDisposition) ) //only set dirty if its a newly created key
  505. Wow64RegSetKeyDirty (*phkResult);
  506. #endif
  507. } else {
  508. Error = (LONG)BaseRegCreateKey (
  509. DereferenceRemoteHandle( hKey ),
  510. &SubKey,
  511. Class,
  512. dwOptions,
  513. samDesired,
  514. pRpcSA,
  515. phkResult,
  516. lpdwDisposition
  517. );
  518. if( Error == ERROR_SUCCESS) {
  519. TagRemoteHandle( phkResult );
  520. }
  521. }
  522. //
  523. // Free the RPC_SECURITY_DESCRIPTOR buffer and return the
  524. // Registry return value.
  525. //
  526. if( pRpcSA != NULL ) {
  527. RtlFreeHeap(
  528. RtlProcessHeap( ), 0,
  529. pRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor
  530. );
  531. }
  532. ExitCleanup:
  533. CLOSE_LOCAL_HANDLE(TempHandle);
  534. return Error;
  535. }
  536. LONG
  537. APIENTRY
  538. RegFlushKey (
  539. IN HKEY hKey
  540. )
  541. /*++
  542. Routine Description:
  543. Win32 RPC wrapper for flushing changes to backing store.
  544. --*/
  545. {
  546. LONG Error;
  547. HKEY TempHandle = NULL;
  548. #if DBG
  549. if ( BreakPointOnEntry ) {
  550. DbgBreakPoint();
  551. }
  552. #endif
  553. //
  554. // Flush is a NO-OP for HKEY_PERFORMANCE_DATA.
  555. //
  556. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  557. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  558. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  559. return ERROR_SUCCESS;
  560. }
  561. hKey = MapPredefinedHandle( hKey, &TempHandle );
  562. if( hKey == NULL ) {
  563. Error = ERROR_INVALID_HANDLE;
  564. goto ExitCleanup;
  565. }
  566. if( IsLocalHandle( hKey )) {
  567. Error = (LONG)LocalBaseRegFlushKey( hKey );
  568. } else {
  569. Error = (LONG)BaseRegFlushKey( DereferenceRemoteHandle( hKey ));
  570. }
  571. ExitCleanup:
  572. CLOSE_LOCAL_HANDLE(TempHandle);
  573. return Error;
  574. }
  575. LONG
  576. APIENTRY
  577. RegOpenKeyA (
  578. HKEY hKey,
  579. LPCSTR lpSubKey,
  580. PHKEY phkResult
  581. )
  582. /*++
  583. Routine Description:
  584. Win 3.1 ANSI RPC wrapper for opening an existing key.
  585. --*/
  586. {
  587. LONG Error;
  588. #if DBG
  589. if ( BreakPointOnEntry ) {
  590. DbgBreakPoint();
  591. }
  592. #endif
  593. if( phkResult == NULL ) {
  594. return ERROR_INVALID_PARAMETER;
  595. }
  596. //
  597. // Win3.1ism - Win 3.1 allows the predefined handle to be opened by
  598. // specifying a pointer to an empty or NULL string for the sub-key.
  599. //
  600. //
  601. // If the subkey is NULL or points to a NUL string and the handle is
  602. // predefined, just return the predefined handle (a virtual open)
  603. // otherwise return the same handle that was passed in.
  604. //
  605. if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
  606. if( !IsPredefinedRegistryHandle( hKey )) {
  607. *phkResult = hKey;
  608. return ERROR_SUCCESS;
  609. }
  610. /*
  611. if( IsPredefinedRegistryHandle( hKey )) {
  612. *phkResult = hKey;
  613. return ERROR_SUCCESS;
  614. } else {
  615. return ERROR_BADKEY;
  616. }
  617. */
  618. }
  619. Error = (LONG)RegOpenKeyExA(
  620. hKey,
  621. lpSubKey,
  622. REG_OPTION_RESERVED,
  623. WIN31_REGSAM,
  624. phkResult
  625. );
  626. return Error;
  627. }
  628. LONG
  629. APIENTRY
  630. RegOpenKeyW (
  631. HKEY hKey,
  632. LPCWSTR lpSubKey,
  633. PHKEY phkResult
  634. )
  635. /*++
  636. Routine Description:
  637. Win 3.1 Unicode RPC wrapper for opening an existing key.
  638. --*/
  639. {
  640. LONG Error;
  641. #if DBG
  642. if ( BreakPointOnEntry ) {
  643. OutputDebugString( "In RegOpenKeyW\n" );
  644. DbgBreakPoint();
  645. }
  646. #endif
  647. if( phkResult == NULL ) {
  648. return ERROR_INVALID_PARAMETER;
  649. }
  650. //
  651. // Win3.1ism - Win 3.1 allows the predefined handle to be opened by
  652. // specifying a pointer to an empty or NULL string for the sub-key.
  653. //
  654. //
  655. // If the subkey is NULL or points to a NUL string and the handle is
  656. // predefined, just return the predefined handle (a virtual open)
  657. // otherwise return the handle passed in.
  658. //
  659. if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
  660. if( !IsPredefinedRegistryHandle( hKey )) {
  661. *phkResult = hKey;
  662. return ERROR_SUCCESS;
  663. }
  664. /*
  665. if( IsPredefinedRegistryHandle( hKey )) {
  666. *phkResult = hKey;
  667. return ERROR_SUCCESS;
  668. } else {
  669. return ERROR_BADKEY;
  670. }
  671. */
  672. }
  673. Error = (LONG)RegOpenKeyExW(
  674. hKey,
  675. lpSubKey,
  676. REG_OPTION_RESERVED,
  677. WIN31_REGSAM,
  678. phkResult
  679. );
  680. return Error;
  681. }
  682. LONG
  683. APIENTRY
  684. RegOpenKeyExA (
  685. HKEY hKey,
  686. LPCSTR lpSubKey,
  687. DWORD dwOptions,
  688. REGSAM samDesired,
  689. PHKEY phkResult
  690. )
  691. /*++
  692. Routine Description:
  693. Win32 ANSI RPC wrapper for opening an existing key.
  694. RegOpenKeyExA converts the lpSubKey argument to a counted Unicode string
  695. and then calls BaseRegOpenKey.
  696. --*/
  697. {
  698. UNICODE_STRING SubKey;
  699. NTSTATUS Status;
  700. LONG Error;
  701. CHAR NullString;
  702. HKEY TempHandle = NULL;
  703. #if DBG
  704. if ( BreakPointOnEntry ) {
  705. DbgBreakPoint();
  706. }
  707. #endif
  708. //
  709. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  710. //
  711. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  712. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  713. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  714. return ERROR_INVALID_HANDLE;
  715. }
  716. //
  717. // Caller must pass pointer to the variable where the opened handle
  718. // will be returned
  719. //
  720. if( phkResult == NULL ) {
  721. return ERROR_INVALID_PARAMETER;
  722. }
  723. //
  724. // If lpSubKey is NULL, then assume NUL-string as subkey name
  725. //
  726. if( lpSubKey == NULL ) {
  727. NullString = ( CHAR )'\0';
  728. lpSubKey = &NullString;
  729. }
  730. //
  731. // If hKey is a predefined key, and lpSubKey is either a NULL pointer or
  732. // a NUL string, close the predefined key and clear the associated entry
  733. // in the PredefinedHandleTable (RegCloseKey will do the job).
  734. //
  735. if( IsPredefinedRegistryHandle( hKey ) && (!( samDesired & KEY_WOW64_RES )) &&
  736. ( ( lpSubKey == NULL ) || ( *lpSubKey == '\0' ) ) ) {
  737. if ( HKEY_CLASSES_ROOT != hKey ) {
  738. Error = RegCloseKey( hKey );
  739. if( Error != ERROR_SUCCESS ) {
  740. return( Error );
  741. }
  742. //
  743. // Create a handle and save it in the appropriate entry in
  744. // PredefinedHandleTable.
  745. // Notice that the client will be impersonated.
  746. // (MapPredefinedHandle will do all this stuff).
  747. //
  748. if( MapPredefinedHandle( hKey, &TempHandle ) == NULL ) {
  749. Error = ERROR_INVALID_HANDLE;
  750. goto ExitCleanup;
  751. }
  752. }
  753. //
  754. // Return to the user the handle passed in
  755. //
  756. *phkResult = hKey;
  757. Error = ERROR_SUCCESS;
  758. goto ExitCleanup;
  759. }
  760. //
  761. // Validate that the sub key is not NULL.
  762. //
  763. ASSERT( lpSubKey != NULL );
  764. if( ! lpSubKey ) {
  765. Error = ERROR_BADKEY;
  766. goto ExitCleanup;
  767. }
  768. hKey = MapPredefinedHandle( hKey, &TempHandle );
  769. if( hKey == NULL ) {
  770. Error = ERROR_INVALID_HANDLE;
  771. goto ExitCleanup;
  772. }
  773. //
  774. // Convert the subkey to a counted Unicode string
  775. //
  776. if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
  777. Status = STATUS_NO_MEMORY;
  778. Error = RtlNtStatusToDosError( Status );
  779. goto ExitCleanup;
  780. }
  781. //
  782. // Add terminating NULL to Length so that RPC transmits it.
  783. //
  784. SubKey.Length += sizeof( UNICODE_NULL );
  785. //
  786. // Call the Base API, passing it the supplied parameters and the
  787. // counted Unicode strings.
  788. //
  789. if( IsLocalHandle( hKey )) {
  790. #if defined(_WIN64)
  791. //
  792. // if wow64 reserve field is set in the access mask, call
  793. // wow64 function to handle the scenario.
  794. //
  795. if ( samDesired & KEY_WOW64_RES ) {
  796. Error = (LONG)Wow64RegOpenKeyEx (
  797. hKey,
  798. SubKey.Buffer,
  799. dwOptions,
  800. samDesired,
  801. phkResult
  802. );
  803. } else
  804. #endif
  805. Error = (LONG)LocalBaseRegOpenKey (
  806. hKey,
  807. &SubKey,
  808. dwOptions,
  809. samDesired,
  810. phkResult
  811. );
  812. } else {
  813. Error = (LONG)BaseRegOpenKey (
  814. DereferenceRemoteHandle( hKey ),
  815. &SubKey,
  816. dwOptions,
  817. samDesired,
  818. phkResult
  819. );
  820. if( Error == ERROR_SUCCESS) {
  821. TagRemoteHandle( phkResult );
  822. }
  823. }
  824. // free the allocated unicode string
  825. RtlFreeUnicodeString( &SubKey );
  826. ExitCleanup:
  827. CLOSE_LOCAL_HANDLE(TempHandle);
  828. return Error;
  829. }
  830. LONG
  831. APIENTRY
  832. RegOpenKeyExW (
  833. HKEY hKey,
  834. LPCWSTR lpSubKey,
  835. DWORD dwOptions,
  836. REGSAM samDesired,
  837. PHKEY phkResult
  838. )
  839. /*++
  840. Routine Description:
  841. Win32 Unicode RPC wrapper for opening an existing key.
  842. RegOpenKeyExW converts the lpSubKey argument to a counted Unicode string
  843. and then calls BaseRegOpenKey.
  844. --*/
  845. {
  846. UNICODE_STRING SubKey;
  847. LONG Error;
  848. WCHAR NullString;
  849. HKEY TempHandle = NULL;
  850. #if DBG
  851. if ( BreakPointOnEntry ) {
  852. DbgBreakPoint();
  853. }
  854. #endif
  855. //
  856. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  857. //
  858. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  859. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  860. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  861. return ERROR_INVALID_HANDLE;
  862. }
  863. //
  864. // Caller must pass pointer to the variable where the opened handle
  865. // will be returned
  866. //
  867. if( phkResult == NULL ) {
  868. return ERROR_INVALID_PARAMETER;
  869. }
  870. //
  871. // If lpSubKey is NULL, then assume NUL-string as subkey name
  872. //
  873. if( lpSubKey == NULL ) {
  874. NullString = UNICODE_NULL;
  875. lpSubKey = &NullString;
  876. }
  877. //
  878. // If hKey is a predefined key, and lpSubKey is either a NULL pointer or
  879. // a NUL string, close the predefined key and clear the associated entry
  880. // in the PredefinedHandleTable (RegCloseKey will do the job).
  881. //
  882. if( IsPredefinedRegistryHandle( hKey ) && (!( samDesired & KEY_WOW64_RES )) &&
  883. ( ( lpSubKey == NULL ) || ( *lpSubKey == ( WCHAR )'\0' ) ) ) {
  884. if ( HKEY_CLASSES_ROOT != hKey ) {
  885. Error = RegCloseKey( hKey );
  886. if( Error != ERROR_SUCCESS ) {
  887. return( Error );
  888. }
  889. //
  890. // Create a handle and save it in the appropriate entry in
  891. // PredefinedHandleTable.
  892. // Notice that the client will be impersonated.
  893. // (MapPredefinedHandle will do all this stuff).
  894. //
  895. if( MapPredefinedHandle( hKey, &TempHandle ) == NULL ) {
  896. Error = ERROR_INVALID_HANDLE;
  897. goto ExitCleanup;
  898. }
  899. }
  900. //
  901. // Return to the user the handle passed in
  902. //
  903. *phkResult = hKey;
  904. Error = ERROR_SUCCESS;
  905. goto ExitCleanup;
  906. }
  907. //
  908. // Validate that the sub key is not NULL.
  909. //
  910. ASSERT( lpSubKey != NULL );
  911. if( ! lpSubKey ) {
  912. Error = ERROR_BADKEY;
  913. goto ExitCleanup;
  914. }
  915. hKey = MapPredefinedHandle( hKey, &TempHandle );
  916. if( hKey == NULL ) {
  917. Error = ERROR_INVALID_HANDLE;
  918. goto ExitCleanup;
  919. }
  920. //
  921. // Convert the subkey to a counted Unicode string.
  922. //
  923. RtlInitUnicodeString( &SubKey, lpSubKey );
  924. //
  925. // Add terminating NULL to Length so that RPC transmits it
  926. //
  927. SubKey.Length += sizeof (UNICODE_NULL );
  928. //
  929. // Call the Base API, passing it the supplied parameters and the
  930. // counted Unicode strings.
  931. //
  932. if( IsLocalHandle( hKey )) {
  933. #if defined(_WIN64)
  934. //
  935. // if wow64 reserve field is set in the access mask, call
  936. // wow64 function to handle the scenario.
  937. //
  938. if ( samDesired & KEY_WOW64_RES ) {
  939. Error = (LONG)Wow64RegOpenKeyEx (
  940. hKey,
  941. SubKey.Buffer,
  942. dwOptions,
  943. samDesired,
  944. phkResult
  945. );
  946. } else
  947. #endif
  948. Error = (LONG)LocalBaseRegOpenKey (
  949. hKey,
  950. &SubKey,
  951. dwOptions,
  952. samDesired,
  953. phkResult
  954. );
  955. } else {
  956. Error = (LONG)BaseRegOpenKey (
  957. DereferenceRemoteHandle( hKey ),
  958. &SubKey,
  959. dwOptions,
  960. samDesired,
  961. phkResult
  962. );
  963. if( Error == ERROR_SUCCESS) {
  964. TagRemoteHandle( phkResult );
  965. }
  966. }
  967. ExitCleanup:
  968. CLOSE_LOCAL_HANDLE(TempHandle);
  969. return Error;
  970. }
  971. LONG
  972. APIENTRY
  973. RegOpenCurrentUser(
  974. REGSAM samDesired,
  975. PHKEY phkResult
  976. )
  977. /*++
  978. Routine Description:
  979. Win32 Client-Only function to open the key for HKEY_CURRENT_USER
  980. for the user that the thread is currently impersonating. Since
  981. HKEY_CURRENT_USER is cached for all threads in a process, if the
  982. process is impersonating multiple users, this allows access to
  983. the appropriate key.
  984. Arguments:
  985. samDesired - Supplies the requested security access mask.
  986. phkResult - Returns an open handle to the key.
  987. Return Value:
  988. Returns 0 (ERROR_SUCCESS) for success, otherwise a windows error code.
  989. --*/
  990. {
  991. NTSTATUS Status ;
  992. Status = RtlOpenCurrentUser( samDesired, phkResult );
  993. #if defined(LEAK_TRACK)
  994. if (NT_SUCCESS(Status)) {
  995. if (g_RegLeakTraceInfo.bEnableLeakTrack) {
  996. (void) TrackObject(*phkResult);
  997. }
  998. }
  999. #endif // (LEAK_TRACK)
  1000. return RtlNtStatusToDosError( Status );
  1001. }
  1002. LONG
  1003. APIENTRY
  1004. RegDisablePredefinedCache(
  1005. )
  1006. /*++
  1007. Routine Description:
  1008. Win32 Client-Only function to disable the predefined handle table
  1009. for HKEY_CURRENT_USER for the calling process
  1010. All references to HKEY_CURRENT_USER after this function is called
  1011. will result in a open/close on HKU\<sid>
  1012. Arguments:
  1013. Return Value:
  1014. Returns 0 (ERROR_SUCCESS) for success, otherwise a windows error code.
  1015. --*/
  1016. {
  1017. NTSTATUS Status ;
  1018. Status = DisablePredefinedHandleTable( HKEY_CURRENT_USER );
  1019. return RtlNtStatusToDosError( Status );
  1020. }