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.

791 lines
17 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. Predefh.c
  5. Abstract:
  6. This module contains routines for opening the Win32 Registry API's
  7. predefined handles.
  8. A predefined handle is used as a root to an absolute or relative
  9. sub-tree in the real Nt Registry. An absolute predefined handle maps
  10. to a specific key within the Registry. A relative predefined handle
  11. maps to a key relative to some additional information such as the
  12. current user.
  13. Predefined handles are strictly part of the Win32 Registry API. The
  14. Nt Registry API knows nothing about them.
  15. A predefined handle can be used anywhere that a non-predefined handle
  16. (i.e. one returned from RegCreateKey(), RegOpenKey() or
  17. RegConnectRegistry()) can be used.
  18. Author:
  19. David J. Gilman (davegi) 15-Nov-1991
  20. --*/
  21. #include <rpc.h>
  22. #include "regrpc.h"
  23. #include "localreg.h"
  24. #include "regclass.h"
  25. #include "ntconreg.h"
  26. #include "regsec.h"
  27. #ifdef LOCAL
  28. #include "tsappcmp.h"
  29. #if defined(LEAK_TRACK)
  30. #include "regleak.h"
  31. #endif // LEAK_TRACK
  32. #endif
  33. //
  34. // Determine the length of a Unicode string w/o the trailing NULL.
  35. //
  36. #define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
  37. //
  38. // Nt Registry name space.
  39. //
  40. #define MACHINE L"\\REGISTRY\\MACHINE"
  41. #define USER L"\\REGISTRY\\USER"
  42. #define CLASSES L"\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES"
  43. #define CLASSES_SUFFIX L"\\SOFTWARE\\CLASSES"
  44. #define CURRENTCONFIG L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT"
  45. UNICODE_STRING MachineStringKey = {
  46. LENGTH( MACHINE ),
  47. LENGTH( MACHINE ),
  48. MACHINE
  49. };
  50. UNICODE_STRING UserStringKey = {
  51. LENGTH( USER ),
  52. LENGTH( USER ),
  53. USER
  54. };
  55. UNICODE_STRING ClassesStringKey = {
  56. LENGTH( CLASSES ),
  57. LENGTH( CLASSES ),
  58. CLASSES
  59. };
  60. UNICODE_STRING CurrentConfigStringKey = {
  61. LENGTH( CURRENTCONFIG ),
  62. LENGTH( CURRENTCONFIG ),
  63. CURRENTCONFIG
  64. };
  65. NTSTATUS
  66. InitSecurityAcls(PSECURITY_DESCRIPTOR *SecurityDescriptor)
  67. /*++
  68. Routine Description:
  69. Gives GENERIC_ALL to admins and denies WRITE_OWNER | WRITE_DAC from everyone
  70. Arguments:
  71. Return Value:
  72. --*/
  73. {
  74. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  75. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  76. PSID BuiltInAdministrators = NULL;
  77. PSID Everyone = NULL;
  78. NTSTATUS Status;
  79. ULONG AclSize;
  80. ACL *Acl;
  81. *SecurityDescriptor = NULL;
  82. Status = RtlAllocateAndInitializeSid(
  83. &WorldAuthority,
  84. 1,
  85. SECURITY_WORLD_RID,
  86. 0,0,0,0,0,0,0,
  87. &Everyone );
  88. if( !NT_SUCCESS(Status) ) {
  89. goto Exit;
  90. }
  91. Status = RtlAllocateAndInitializeSid(
  92. &NtAuthority,
  93. 2,
  94. SECURITY_BUILTIN_DOMAIN_RID,
  95. DOMAIN_ALIAS_RID_ADMINS,
  96. 0,0,0,0,0,0,
  97. &BuiltInAdministrators );
  98. if( !NT_SUCCESS(Status) ) {
  99. goto Exit;
  100. }
  101. AclSize = sizeof (ACL) +
  102. (2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
  103. GetLengthSid(BuiltInAdministrators) +
  104. GetLengthSid(Everyone);
  105. *SecurityDescriptor = (PSECURITY_DESCRIPTOR)RtlAllocateHeap( RtlProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
  106. if (!*SecurityDescriptor) {
  107. Status = STATUS_INSUFFICIENT_RESOURCES;
  108. goto Exit;
  109. }
  110. Acl = (ACL *)((BYTE *)(*SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH);
  111. Status = RtlCreateAcl( Acl,
  112. AclSize,
  113. ACL_REVISION);
  114. if( !NT_SUCCESS(Status) ) {
  115. goto Exit;
  116. }
  117. Status = RtlAddAccessAllowedAce(Acl,
  118. ACL_REVISION,
  119. (KEY_ALL_ACCESS & ~(WRITE_OWNER | WRITE_DAC)),
  120. Everyone);
  121. if( !NT_SUCCESS(Status) ) {
  122. goto Exit;
  123. }
  124. Status = RtlAddAccessAllowedAce(Acl,
  125. ACL_REVISION,
  126. GENERIC_ALL,
  127. BuiltInAdministrators);
  128. if( !NT_SUCCESS(Status) ) {
  129. goto Exit;
  130. }
  131. Status = RtlCreateSecurityDescriptor(
  132. *SecurityDescriptor,
  133. SECURITY_DESCRIPTOR_REVISION
  134. );
  135. if( !NT_SUCCESS(Status) ) {
  136. goto Exit;
  137. }
  138. Status = RtlSetDaclSecurityDescriptor( *SecurityDescriptor,
  139. TRUE,
  140. Acl,
  141. FALSE);
  142. Exit:
  143. if( Everyone ) {
  144. RtlFreeSid( Everyone );
  145. }
  146. if( BuiltInAdministrators ) {
  147. RtlFreeSid( BuiltInAdministrators );
  148. }
  149. return Status;
  150. }
  151. error_status_t
  152. OpenClassesRoot(
  153. IN PREGISTRY_SERVER_NAME ServerName,
  154. IN REGSAM samDesired,
  155. OUT PRPC_HKEY phKey
  156. )
  157. /*++
  158. Routine Description:
  159. Attempts to open the the HKEY_CLASSES_ROOT predefined handle.
  160. Arguments:
  161. ServerName - Not used.
  162. samDesired - This access mask describes the desired security access
  163. for the key.
  164. phKey - Returns a handle to the key \REGISTRY\MACHINE\SOFTWARE\CLASSES.
  165. Return Value:
  166. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  167. --*/
  168. {
  169. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  170. OBJECT_ATTRIBUTES Obja;
  171. NTSTATUS Status;
  172. UNICODE_STRING UsersHive;
  173. UNICODE_STRING UsersMergedHive;
  174. error_status_t Res;
  175. UNREFERENCED_PARAMETER( ServerName );
  176. //
  177. // Impersonate the client.
  178. //
  179. RPC_IMPERSONATE_CLIENT( NULL );
  180. #ifdef LOCAL
  181. //
  182. // Multiuser CLASSES key so each user has their own key. If opening
  183. // CLASSES in execute mode - open it under HKEY_CURRENT_USER else
  184. // just let it fall thru here and open the global one.
  185. //
  186. if (gpfnTermsrvOpenUserClasses) {
  187. Status = gpfnTermsrvOpenUserClasses(samDesired,phKey);
  188. } else {
  189. *phKey = NULL;
  190. }
  191. if (!(*phKey)) {
  192. #endif // LOCAL
  193. //
  194. // Initialize the SECURITY_DESCRIPTOR.
  195. //
  196. Status = InitSecurityAcls(&SecurityDescriptor);
  197. if( ! NT_SUCCESS( Status )) {
  198. goto error_exit;
  199. }
  200. #ifdef LOCAL
  201. if (gbCombinedClasses) {
  202. // first try for a per-user HKCR
  203. Res = OpenCombinedClassesRoot( samDesired, phKey );
  204. if ( NT_SUCCESS( Res ) ) {
  205. goto error_exit;
  206. }
  207. }
  208. #endif
  209. //
  210. // Initialize the OBJECT_ATTRIBUTES structure so that it creates
  211. // (opens) the key "\REGISTRY\MACHINE\SOFTWARE\CLASSES" with a Security
  212. // Descriptor that allows everyone complete access.
  213. //
  214. InitializeObjectAttributes(
  215. &Obja,
  216. &ClassesStringKey,
  217. OBJ_CASE_INSENSITIVE,
  218. NULL,
  219. SecurityDescriptor
  220. );
  221. Status = NtCreateKey(
  222. phKey,
  223. samDesired, // MAXIMUM_ALLOWED,
  224. &Obja,
  225. 0,
  226. NULL,
  227. REG_OPTION_NON_VOLATILE,
  228. NULL
  229. );
  230. #ifdef LOCAL
  231. }
  232. #endif // LOCAL
  233. #if DBG
  234. if( ! NT_SUCCESS( Status )) {
  235. DbgPrint(
  236. "Winreg Server: "
  237. "Creating HKEY_CLASSES_ROOT failed, status = 0x%x\n",
  238. Status
  239. );
  240. }
  241. #endif
  242. error_exit:
  243. if( SecurityDescriptor != NULL ) {
  244. RtlFreeHeap( RtlProcessHeap(), 0, SecurityDescriptor );
  245. }
  246. RPC_REVERT_TO_SELF();
  247. return (error_status_t)RtlNtStatusToDosError( Status );
  248. }
  249. error_status_t
  250. OpenCurrentUser(
  251. IN PREGISTRY_SERVER_NAME ServerName,
  252. IN REGSAM samDesired,
  253. OUT PRPC_HKEY phKey
  254. )
  255. /*++
  256. Routine Description:
  257. Attempts to open the the HKEY_CURRENT_USER predefined handle.
  258. Arguments:
  259. ServerName - Not used.
  260. samDesired - This access mask describes the desired security access
  261. for the key.
  262. phKey - Returns a handle to the key \REGISTRY\USER\*.
  263. Return Value:
  264. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  265. --*/
  266. {
  267. NTSTATUS Status;
  268. UNREFERENCED_PARAMETER( ServerName );
  269. //
  270. // Impersonate the client.
  271. //
  272. RPC_IMPERSONATE_CLIENT( NULL );
  273. //
  274. // Open the registry key.
  275. //
  276. Status = RtlOpenCurrentUser( samDesired, /* MAXIMUM_ALLOWED, */ phKey );
  277. RPC_REVERT_TO_SELF();
  278. //
  279. // Map the returned status
  280. //
  281. return (error_status_t)RtlNtStatusToDosError( Status );
  282. }
  283. error_status_t
  284. OpenLocalMachine(
  285. IN PREGISTRY_SERVER_NAME ServerName,
  286. IN REGSAM samDesired,
  287. OUT PRPC_HKEY phKey
  288. )
  289. /*++
  290. Routine Description:
  291. Attempt to open the the HKEY_LOCAL_MACHINE predefined handle.
  292. Arguments:
  293. ServerName - Not used.
  294. samDesired - This access mask describes the desired security access
  295. for the key.
  296. phKey - Returns a handle to the key \REGISTRY\MACHINE.
  297. Return Value:
  298. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  299. --*/
  300. {
  301. OBJECT_ATTRIBUTES Obja;
  302. NTSTATUS Status;
  303. UNREFERENCED_PARAMETER( ServerName );
  304. //
  305. // Impersonate the client.
  306. //
  307. RPC_IMPERSONATE_CLIENT( NULL );
  308. InitializeObjectAttributes(
  309. &Obja,
  310. &MachineStringKey,
  311. OBJ_CASE_INSENSITIVE,
  312. NULL,
  313. NULL
  314. );
  315. Status = NtOpenKey(
  316. phKey,
  317. samDesired, // MAXIMUM_ALLOWED,
  318. &Obja
  319. );
  320. #if DBG
  321. if( ! NT_SUCCESS( Status )) {
  322. DbgPrint(
  323. "Winreg Server: "
  324. "Opening HKEY_LOCAL_MACHINE failed, status = 0x%x\n",
  325. Status
  326. );
  327. }
  328. #endif
  329. if ( NT_SUCCESS( Status ) )
  330. {
  331. if (! REGSEC_CHECK_REMOTE( phKey ) )
  332. {
  333. *phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_MACHINE_PATHS );
  334. }
  335. }
  336. RPC_REVERT_TO_SELF();
  337. return (error_status_t)RtlNtStatusToDosError( Status );
  338. }
  339. error_status_t
  340. OpenUsers(
  341. IN PREGISTRY_SERVER_NAME ServerName,
  342. IN REGSAM samDesired,
  343. OUT PRPC_HKEY phKey
  344. )
  345. /*++
  346. Routine Description:
  347. Attempts to open the the HKEY_USERS predefined handle.
  348. Arguments:
  349. ServerName - Not used.
  350. samDesired - This access mask describes the desired security access
  351. for the key.
  352. phKey - Returns a handle to the key \REGISTRY\USER.
  353. Return Value:
  354. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  355. --*/
  356. {
  357. OBJECT_ATTRIBUTES Obja;
  358. NTSTATUS Status;
  359. UNREFERENCED_PARAMETER( ServerName );
  360. //
  361. // Impersonate the client.
  362. //
  363. RPC_IMPERSONATE_CLIENT( NULL );
  364. InitializeObjectAttributes(
  365. &Obja,
  366. &UserStringKey,
  367. OBJ_CASE_INSENSITIVE,
  368. NULL,
  369. NULL
  370. );
  371. Status = NtOpenKey(
  372. phKey,
  373. samDesired, // MAXIMUM_ALLOWED,
  374. &Obja
  375. );
  376. #if DBG
  377. if( ! NT_SUCCESS( Status )) {
  378. DbgPrint(
  379. "Winreg Server: "
  380. "Opening HKEY_USERS failed, status = 0x%x\n",
  381. Status
  382. );
  383. }
  384. #endif
  385. if ( NT_SUCCESS( Status ) )
  386. {
  387. if (! REGSEC_CHECK_REMOTE( phKey ) )
  388. {
  389. *phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_USER_PATHS );
  390. }
  391. }
  392. RPC_REVERT_TO_SELF();
  393. return (error_status_t)RtlNtStatusToDosError( Status );
  394. }
  395. error_status_t
  396. OpenCurrentConfig(
  397. IN PREGISTRY_SERVER_NAME ServerName,
  398. IN REGSAM samDesired,
  399. OUT PRPC_HKEY phKey
  400. )
  401. /*++
  402. Routine Description:
  403. Attempts to open the the HKEY_CURRENT_CONFIG predefined handle.
  404. Arguments:
  405. ServerName - Not used.
  406. samDesired - This access mask describes the desired security access
  407. for the key.
  408. phKey - Returns a handle to the key \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\HARDWARE PROFILES\CURRENT
  409. Return Value:
  410. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  411. --*/
  412. {
  413. OBJECT_ATTRIBUTES Obja;
  414. NTSTATUS Status;
  415. UNREFERENCED_PARAMETER( ServerName );
  416. //
  417. // Impersonate the client.
  418. //
  419. RPC_IMPERSONATE_CLIENT( NULL );
  420. InitializeObjectAttributes(
  421. &Obja,
  422. &CurrentConfigStringKey,
  423. OBJ_CASE_INSENSITIVE,
  424. NULL,
  425. NULL
  426. );
  427. Status = NtOpenKey(
  428. phKey,
  429. samDesired, // MAXIMUM_ALLOWED,
  430. &Obja
  431. );
  432. #if DBG
  433. if( ! NT_SUCCESS( Status )) {
  434. DbgPrint(
  435. "Winreg Server: "
  436. "Opening HKEY_CURRENT_CONFIG failed, status = 0x%x\n",
  437. Status
  438. );
  439. }
  440. #endif
  441. RPC_REVERT_TO_SELF();
  442. return (error_status_t)RtlNtStatusToDosError( Status );
  443. }
  444. error_status_t
  445. OpenPerformanceData(
  446. IN PREGISTRY_SERVER_NAME ServerName,
  447. IN REGSAM samDesired,
  448. OUT PRPC_HKEY phKey
  449. )
  450. /*++
  451. Routine Description:
  452. Attempts to open the the HKEY_PERFORMANCE_DATA predefined handle.
  453. Arguments:
  454. ServerName - Not used.
  455. samDesired - Not used.
  456. phKey - Returns a the predefined handle HKEY_PERFORMANCE_DATA.
  457. Return Value:
  458. Returns ERROR_SUCCESS (0) for success;
  459. or a DOS (not NT) error-code for failure.
  460. --*/
  461. {
  462. IO_STATUS_BLOCK IoStatusBlock;
  463. RTL_RELATIVE_NAME RelativeName;
  464. UNICODE_STRING DeviceNameU;
  465. OBJECT_ATTRIBUTES ObjectAttributes;
  466. STRING DeviceName;
  467. NTSTATUS status;
  468. if ( 0 ) {
  469. DBG_UNREFERENCED_PARAMETER(ServerName);
  470. DBG_UNREFERENCED_PARAMETER(samDesired);
  471. }
  472. //
  473. // Impersonate the client.
  474. //
  475. RPC_IMPERSONATE_CLIENT( NULL );
  476. if ( ! REGSEC_CHECK_REMOTE( phKey ) )
  477. {
  478. RPC_REVERT_TO_SELF();
  479. return( ERROR_ACCESS_DENIED );
  480. }
  481. // check if we are in the middle of Lodctr/unlodctr.
  482. // if so, don't open the performance data stuff.
  483. {
  484. HANDLE hFileMapping = NULL;
  485. WCHAR MapFileName[] = L"Perflib Busy";
  486. DWORD *lpData;
  487. BOOL bBusy = FALSE;
  488. hFileMapping = OpenFileMappingW (FILE_MAP_READ, TRUE, (LPCWSTR)MapFileName);
  489. if (hFileMapping) {
  490. // someone is running lodctr perhaps find out by reading the first DWORD
  491. lpData = MapViewOfFile (hFileMapping,
  492. FILE_MAP_READ, 0L, 0L, 0L);
  493. if (lpData) {
  494. // successfully mapped so read it
  495. // 1 = busy, 0 = not
  496. bBusy = (BOOL)(*lpData);
  497. UnmapViewOfFile (lpData);
  498. }
  499. CloseHandle (hFileMapping);
  500. if (bBusy) {
  501. *phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA;
  502. RPC_REVERT_TO_SELF();
  503. return ERROR_SUCCESS;
  504. }
  505. } else {
  506. // no lodctr so continue
  507. }
  508. }
  509. status = PerfOpenKey();
  510. RPC_REVERT_TO_SELF();
  511. *phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA;
  512. return ERROR_SUCCESS;
  513. RPC_REVERT_TO_SELF();
  514. return status;
  515. }
  516. error_status_t
  517. OpenPerformanceText(
  518. IN PREGISTRY_SERVER_NAME ServerName,
  519. IN REGSAM samDesired,
  520. OUT PRPC_HKEY phKey
  521. )
  522. /*++
  523. Routine Description:
  524. Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
  525. Arguments:
  526. ServerName - Not used.
  527. samDesired - Not used.
  528. phKey - Returns the predefined handle HKEY_PERFORMANCE_TEXT.
  529. Return Value:
  530. Returns ERROR_SUCCESS (0) for success;
  531. or a DOS (not NT) error-code for failure.
  532. --*/
  533. {
  534. error_status_t Status = ERROR_SUCCESS;
  535. // No need to call OpenPerformanceData for getting text (HWC 4/1994)
  536. // Status = OpenPerformanceData(ServerName, samDesired, phKey);
  537. // if (Status==ERROR_SUCCESS) {
  538. *phKey = HKEY_PERFORMANCE_TEXT;
  539. // }
  540. return(Status);
  541. }
  542. error_status_t
  543. OpenPerformanceNlsText(
  544. IN PREGISTRY_SERVER_NAME ServerName,
  545. IN REGSAM samDesired,
  546. OUT PRPC_HKEY phKey
  547. )
  548. /*++
  549. Routine Description:
  550. Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
  551. Arguments:
  552. ServerName - Not used.
  553. samDesired - Not used.
  554. phKey - Returns the predefined handle HKEY_PERFORMANCE_NLSTEXT.
  555. Return Value:
  556. Returns ERROR_SUCCESS (0) for success;
  557. or a DOS (not NT) error-code for failure.
  558. --*/
  559. {
  560. error_status_t Status = ERROR_SUCCESS;
  561. // No need to call OpenPerformanceData for getting text (HWC 4/1994)
  562. // Status = OpenPerformanceData(ServerName, samDesired, phKey);
  563. // if (Status==ERROR_SUCCESS) {
  564. *phKey = HKEY_PERFORMANCE_NLSTEXT;
  565. // }
  566. return(Status);
  567. }
  568. error_status_t
  569. OpenDynData(
  570. IN PREGISTRY_SERVER_NAME ServerName,
  571. IN REGSAM samDesired,
  572. OUT PRPC_HKEY phKey
  573. )
  574. /*++
  575. Routine Description:
  576. Attempts to open the the HKEY_DYN_DATA predefined handle.
  577. There is currently no HKEY_DYN_DATA on NT, thus this
  578. function always returns ERROR_CALL_NOT_IMPLEMENTED.
  579. Arguments:
  580. ServerName - Not used.
  581. samDesired - This access mask describes the desired security access
  582. for the key.
  583. phKey - Returns a handle to the key HKEY_DYN_DATA
  584. Return Value:
  585. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  586. --*/
  587. {
  588. return((error_status_t)ERROR_CALL_NOT_IMPLEMENTED);
  589. }