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.

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