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.

1758 lines
52 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. srvinit.c
  5. Abstract:
  6. This is the main initialization module for the Server side of the Client
  7. Server Runtime Subsystem (CSRSS)
  8. Author:
  9. Steve Wood (stevewo) 08-Oct-1990
  10. Environment:
  11. User Mode Only
  12. Revision History:
  13. --*/
  14. #include "csrsrv.h"
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <wow64reg.h>
  18. PCSR_API_ROUTINE CsrServerApiDispatchTable[ CsrpMaxApiNumber ] = {
  19. (PCSR_API_ROUTINE)CsrSrvClientConnect,
  20. (PCSR_API_ROUTINE)CsrSrvUnusedFunction,
  21. (PCSR_API_ROUTINE)CsrSrvUnusedFunction,
  22. (PCSR_API_ROUTINE)CsrSrvIdentifyAlertableThread,
  23. (PCSR_API_ROUTINE)CsrSrvSetPriorityClass
  24. };
  25. BOOLEAN CsrServerApiServerValidTable[ CsrpMaxApiNumber ] = {
  26. TRUE, // CsrSrvClientConnect,
  27. FALSE, // CsrSrvThreadConnect,
  28. TRUE, // CsrSrvProfileControl,
  29. TRUE, // CsrSrvIdentifyAlertableThread
  30. TRUE // CsrSrvSetPriorityClass
  31. };
  32. #if DBG
  33. PSZ CsrServerApiNameTable[ CsrpMaxApiNumber ] = {
  34. "ClientConnect",
  35. "ThreadConnect",
  36. "ProfileControl",
  37. "IdentifyAlertableThread",
  38. "SetPriorityClass"
  39. };
  40. #endif // DBG
  41. NTSTATUS
  42. CsrSetProcessSecurity(
  43. VOID
  44. );
  45. NTSTATUS
  46. CsrSetDirectorySecurity(
  47. IN HANDLE DirectoryHandle
  48. );
  49. NTSTATUS
  50. GetDosDevicesProtection (
  51. PSECURITY_DESCRIPTOR SecurityDescriptor
  52. );
  53. VOID
  54. FreeDosDevicesProtection (
  55. PSECURITY_DESCRIPTOR SecurityDescriptor
  56. );
  57. NTSTATUS
  58. CsrPopulateDosDevicesDirectory(
  59. HANDLE NewDirectoryHandle,
  60. PPROCESS_DEVICEMAP_INFORMATION pGlobalProcessDeviceMapInfo
  61. );
  62. NTSTATUS
  63. CsrServerInitialization(
  64. IN ULONG argc,
  65. IN PCH argv[]
  66. )
  67. {
  68. NTSTATUS Status;
  69. ULONG i;
  70. PVOID ProcessDataPtr;
  71. PCSR_SERVER_DLL LoadedServerDll;
  72. #if DBG
  73. BOOLEAN bIsRemoteSession = NtCurrentPeb()->SessionId != 0;
  74. #endif
  75. //
  76. // Initialize Wow64 stuffs
  77. //
  78. #ifdef _WIN64
  79. InitializeWow64OnBoot(1);
  80. #endif
  81. // Though this function does not seem to cleanup on failure, failure
  82. // will cause Csrss to exit, so any allocated memory will be freed and
  83. // any open handle will be closed.
  84. Status = NtCreateEvent(&CsrInitializationEvent,
  85. EVENT_ALL_ACCESS,
  86. NULL,
  87. SynchronizationEvent,
  88. FALSE
  89. );
  90. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  91. if (!NT_SUCCESS( Status )) {
  92. return Status;
  93. }
  94. //
  95. // Save away system information in a global variable
  96. //
  97. Status = NtQuerySystemInformation( SystemBasicInformation,
  98. &CsrNtSysInfo,
  99. sizeof( CsrNtSysInfo ),
  100. NULL
  101. );
  102. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  103. if (!NT_SUCCESS( Status )) {
  104. return Status;
  105. }
  106. //
  107. // Use the process heap for memory allocation.
  108. //
  109. CsrHeap = RtlProcessHeap();
  110. CsrBaseTag = RtlCreateTagHeap( CsrHeap,
  111. 0,
  112. L"CSRSS!",
  113. L"TMP\0"
  114. L"INIT\0"
  115. L"CAPTURE\0"
  116. L"PROCESS\0"
  117. L"THREAD\0"
  118. L"SECURITY\0"
  119. L"SESSION\0"
  120. L"WAIT\0"
  121. );
  122. //
  123. // Set up CSRSS process security
  124. //
  125. Status = CsrSetProcessSecurity();
  126. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  127. if (!NT_SUCCESS( Status )) {
  128. return Status;
  129. }
  130. //
  131. // Initialize the Session List
  132. //
  133. Status = CsrInitializeNtSessionList();
  134. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  135. if (!NT_SUCCESS( Status )) {
  136. return Status;
  137. }
  138. //
  139. // Initialize the Process List
  140. //
  141. Status = CsrInitializeProcessStructure();
  142. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  143. if (!NT_SUCCESS( Status )) {
  144. return Status;
  145. }
  146. //
  147. // Process the command line arguments
  148. //
  149. Status = CsrParseServerCommandLine( argc, argv );
  150. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  151. if (!NT_SUCCESS( Status )) {
  152. return Status;
  153. }
  154. //
  155. // Fix up per-process data for root process
  156. //
  157. ProcessDataPtr = (PCSR_PROCESS)RtlAllocateHeap( CsrHeap,
  158. MAKE_TAG( PROCESS_TAG ) | HEAP_ZERO_MEMORY,
  159. CsrTotalPerProcessDataLength
  160. );
  161. if (ProcessDataPtr == NULL) {
  162. return STATUS_NO_MEMORY;
  163. }
  164. for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
  165. LoadedServerDll = CsrLoadedServerDll[ i ];
  166. if (LoadedServerDll && LoadedServerDll->PerProcessDataLength) {
  167. CsrRootProcess->ServerDllPerProcessData[i] = ProcessDataPtr;
  168. ProcessDataPtr = (PVOID)QUAD_ALIGN((PCHAR)ProcessDataPtr + LoadedServerDll->PerProcessDataLength);
  169. }
  170. else {
  171. CsrRootProcess->ServerDllPerProcessData[i] = NULL;
  172. }
  173. }
  174. //
  175. // Let server dlls know about the root process.
  176. //
  177. for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
  178. LoadedServerDll = CsrLoadedServerDll[ i ];
  179. if (LoadedServerDll && LoadedServerDll->AddProcessRoutine) {
  180. (*LoadedServerDll->AddProcessRoutine)( NULL, CsrRootProcess );
  181. }
  182. }
  183. //
  184. // Initialize the Windows Server API Port, and one or more
  185. // request threads.
  186. //
  187. Status = CsrApiPortInitialize();
  188. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  189. if (!NT_SUCCESS( Status )) {
  190. return Status;
  191. }
  192. //
  193. // Initialize the Server Session Manager API Port and one
  194. // request thread.
  195. //
  196. Status = CsrSbApiPortInitialize();
  197. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession);
  198. if (!NT_SUCCESS( Status )) {
  199. return Status;
  200. }
  201. //
  202. // Connect to the session manager so we can start foreign sessions
  203. //
  204. Status = SmConnectToSm( &CsrSbApiPortName,
  205. CsrSbApiPort,
  206. IMAGE_SUBSYSTEM_WINDOWS_GUI,
  207. &CsrSmApiPort
  208. );
  209. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  210. if (!NT_SUCCESS( Status )) {
  211. return Status;
  212. }
  213. Status = NtSetEvent(CsrInitializationEvent,NULL);
  214. ASSERT( NT_SUCCESS( Status ) || bIsRemoteSession );
  215. if (!NT_SUCCESS( Status )) {
  216. return Status;
  217. }
  218. NtClose(CsrInitializationEvent);
  219. //
  220. // Only on Console (HYDRA)
  221. //
  222. if (NtCurrentPeb()->SessionId == 0)
  223. Status = NtSetDefaultHardErrorPort(CsrApiPort);
  224. return( Status );
  225. }
  226. NTSTATUS
  227. CsrParseServerCommandLine(
  228. IN ULONG argc,
  229. IN PCH argv[]
  230. )
  231. {
  232. NTSTATUS Status;
  233. OBJECT_ATTRIBUTES ObjectAttributes;
  234. ULONG i, ServerDllIndex;
  235. PCH KeyName, KeyValue, s;
  236. PCH InitRoutine;
  237. CsrTotalPerProcessDataLength = 0;
  238. CsrObjectDirectory = NULL;
  239. CsrMaxApiRequestThreads = CSR_MAX_THREADS;
  240. SessionId = NtCurrentPeb()->SessionId;
  241. //
  242. // Create session specific object directories
  243. //
  244. Status = CsrCreateSessionObjectDirectory ( SessionId );
  245. if (!NT_SUCCESS(Status)) {
  246. if (SessionId == 0) {
  247. ASSERT( NT_SUCCESS( Status ) );
  248. DbgPrint("CSRSS: CsrCreateSessionObjectDirectory failed status = %lx\n", Status);
  249. } else {
  250. DbgPrint("CSRSS: CsrCreateSessionObjectDirectory failed status = %lx\n", Status);
  251. return Status;
  252. }
  253. }
  254. for (i=1; i<argc ; i++) {
  255. KeyName = argv[ i ];
  256. KeyValue = NULL;
  257. while (*KeyName) {
  258. if (*KeyName == '=') {
  259. *KeyName++ = '\0';
  260. KeyValue = KeyName;
  261. break;
  262. }
  263. KeyName++;
  264. }
  265. KeyName = argv[ i ];
  266. if (!_stricmp( KeyName, "ObjectDirectory" )) {
  267. ANSI_STRING AnsiString;
  268. ULONG attributes;
  269. CHAR SessionDirectory[MAX_SESSION_PATH];
  270. if (SessionId != 0) {
  271. //
  272. // Non-Console session
  273. //
  274. sprintf(SessionDirectory,"%ws\\%ld",SESSION_ROOT,SessionId);
  275. strcat(SessionDirectory,KeyValue);
  276. }
  277. //
  278. // Create an object directory in the object name space with the
  279. // name specified. It will be the root for all object names
  280. // created by the Server side of the Client Server Runtime
  281. // SubSystem.
  282. //
  283. attributes = OBJ_OPENIF | OBJ_CASE_INSENSITIVE;
  284. if (SessionId == 0) {
  285. attributes |= OBJ_PERMANENT;
  286. RtlInitString( &AnsiString, KeyValue );
  287. } else {
  288. RtlInitString( &AnsiString, SessionDirectory );
  289. }
  290. Status = RtlAnsiStringToUnicodeString( &CsrDirectoryName, &AnsiString, TRUE );
  291. ASSERT(NT_SUCCESS(Status) || SessionId != 0);
  292. if (!NT_SUCCESS( Status )) {
  293. break;
  294. }
  295. InitializeObjectAttributes( &ObjectAttributes,
  296. &CsrDirectoryName,
  297. attributes,
  298. NULL,
  299. NULL
  300. );
  301. Status = NtCreateDirectoryObject( &CsrObjectDirectory,
  302. DIRECTORY_ALL_ACCESS,
  303. &ObjectAttributes
  304. );
  305. if (!NT_SUCCESS( Status )) {
  306. break;
  307. }
  308. Status = CsrSetDirectorySecurity( CsrObjectDirectory );
  309. if (!NT_SUCCESS( Status )) {
  310. break;
  311. }
  312. }
  313. else
  314. if (!_stricmp( KeyName, "SubSystemType" )) {
  315. }
  316. else
  317. if (!_stricmp( KeyName, "MaxRequestThreads" )) {
  318. Status = RtlCharToInteger( KeyValue,
  319. 0,
  320. &CsrMaxApiRequestThreads
  321. );
  322. }
  323. else
  324. if (!_stricmp( KeyName, "RequestThreads" )) {
  325. #if 0
  326. Status = RtlCharToInteger( KeyValue,
  327. 0,
  328. &CsrNumberApiRequestThreads
  329. );
  330. #else
  331. //
  332. // wait until hive change !
  333. //
  334. Status = STATUS_SUCCESS;
  335. #endif
  336. }
  337. else
  338. if (!_stricmp( KeyName, "ProfileControl" )) {
  339. }
  340. else
  341. if (!_stricmp( KeyName, "SharedSection" )) {
  342. Status = CsrSrvCreateSharedSection( KeyValue );
  343. if (!NT_SUCCESS( Status )) {
  344. IF_DEBUG {
  345. DbgPrint( "CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
  346. KeyName,
  347. KeyValue,
  348. Status
  349. );
  350. }
  351. return Status;
  352. }
  353. Status = CsrLoadServerDll( "CSRSS", NULL, CSRSRV_SERVERDLL_INDEX );
  354. }
  355. else
  356. if (!_stricmp( KeyName, "ServerDLL" )) {
  357. s = KeyValue;
  358. InitRoutine = NULL;
  359. Status = STATUS_INVALID_PARAMETER;
  360. while (*s) {
  361. if ((*s == ':') && (InitRoutine == NULL)) {
  362. *s++ = '\0';
  363. InitRoutine = s;
  364. }
  365. if (*s++ == ',') {
  366. Status = RtlCharToInteger ( s, 10, &ServerDllIndex );
  367. if (NT_SUCCESS( Status )) {
  368. s[ -1 ] = '\0';
  369. }
  370. break;
  371. }
  372. }
  373. if (!NT_SUCCESS( Status )) {
  374. IF_DEBUG {
  375. DbgPrint( "CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
  376. KeyValue,
  377. Status
  378. );
  379. }
  380. }
  381. else {
  382. IF_CSR_DEBUG( INIT) {
  383. DbgPrint( "CSRSS: Loading ServerDll=%s:%s\n", KeyValue, InitRoutine );
  384. }
  385. Status = CsrLoadServerDll( KeyValue, InitRoutine, ServerDllIndex);
  386. if (!NT_SUCCESS( Status )) {
  387. IF_DEBUG {
  388. DbgPrint( "CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
  389. KeyValue,
  390. Status
  391. );
  392. }
  393. return Status;
  394. }
  395. }
  396. }
  397. else
  398. //
  399. // This is a temporary hack until Windows & Console are friends.
  400. //
  401. if (!_stricmp( KeyName, "Windows" )) {
  402. }
  403. else {
  404. Status = STATUS_INVALID_PARAMETER;
  405. }
  406. }
  407. return( Status );
  408. }
  409. NTSTATUS
  410. CsrServerDllInitialization(
  411. IN PCSR_SERVER_DLL LoadedServerDll
  412. )
  413. {
  414. LoadedServerDll->ApiNumberBase = CSRSRV_FIRST_API_NUMBER;
  415. LoadedServerDll->MaxApiNumber = CsrpMaxApiNumber;
  416. LoadedServerDll->ApiDispatchTable = CsrServerApiDispatchTable;
  417. LoadedServerDll->ApiServerValidTable = CsrServerApiServerValidTable;
  418. #if DBG
  419. LoadedServerDll->ApiNameTable = CsrServerApiNameTable;
  420. #else
  421. LoadedServerDll->ApiNameTable = NULL;
  422. #endif
  423. LoadedServerDll->PerProcessDataLength = 0;
  424. LoadedServerDll->ConnectRoutine = NULL;
  425. LoadedServerDll->DisconnectRoutine = NULL;
  426. return( STATUS_SUCCESS );
  427. }
  428. NTSTATUS
  429. CsrSrvUnusedFunction(
  430. IN OUT PCSR_API_MSG m,
  431. IN OUT PCSR_REPLY_STATUS ReplyStatus
  432. )
  433. {
  434. IF_DEBUG {
  435. DbgPrint("CSRSS: Calling obsolete function %x\n", m->ApiNumber);
  436. }
  437. return STATUS_INVALID_PARAMETER;
  438. }
  439. NTSTATUS
  440. CsrSetProcessSecurity(
  441. VOID
  442. )
  443. {
  444. HANDLE Token;
  445. NTSTATUS Status;
  446. PTOKEN_USER User = NULL;
  447. ULONG LengthSid, Length;
  448. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  449. PACL Dacl;
  450. //
  451. // Open the token and get the system sid
  452. //
  453. Status = NtOpenProcessToken( NtCurrentProcess(),
  454. TOKEN_QUERY,
  455. &Token
  456. );
  457. if (!NT_SUCCESS(Status)) {
  458. return Status;
  459. }
  460. NtQueryInformationToken( Token,
  461. TokenUser,
  462. NULL,
  463. 0,
  464. &Length
  465. );
  466. User = (PTOKEN_USER)RtlAllocateHeap( CsrHeap,
  467. MAKE_TAG( SECURITY_TAG ) | HEAP_ZERO_MEMORY,
  468. Length
  469. );
  470. if (User == NULL) {
  471. Status = STATUS_NO_MEMORY;
  472. goto error_cleanup;
  473. }
  474. Status = NtQueryInformationToken( Token,
  475. TokenUser,
  476. User,
  477. Length,
  478. &Length
  479. );
  480. NtClose( Token );
  481. if (!NT_SUCCESS(Status)) {
  482. RtlFreeHeap( CsrHeap, 0, User );
  483. return Status;
  484. }
  485. LengthSid = RtlLengthSid( User->User.Sid );
  486. //
  487. // Allocate a buffer to hold the SD
  488. //
  489. SecurityDescriptor = RtlAllocateHeap( CsrHeap,
  490. MAKE_TAG( SECURITY_TAG ) | HEAP_ZERO_MEMORY,
  491. SECURITY_DESCRIPTOR_MIN_LENGTH +
  492. sizeof(ACL) + LengthSid +
  493. sizeof(ACCESS_ALLOWED_ACE)
  494. );
  495. if (SecurityDescriptor == NULL) {
  496. Status = STATUS_NO_MEMORY;
  497. goto error_cleanup;
  498. }
  499. Dacl = (PACL)((PCHAR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
  500. //
  501. // Create the SD
  502. //
  503. Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
  504. SECURITY_DESCRIPTOR_REVISION);
  505. if (!NT_SUCCESS(Status)) {
  506. IF_DEBUG {
  507. DbgPrint("CSRSS: SD creation failed - status = %lx\n", Status);
  508. }
  509. goto error_cleanup;
  510. }
  511. RtlCreateAcl( Dacl,
  512. sizeof(ACL) + LengthSid + sizeof(ACCESS_ALLOWED_ACE),
  513. ACL_REVISION2
  514. );
  515. Status = RtlAddAccessAllowedAce( Dacl,
  516. ACL_REVISION,
  517. ( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION |
  518. PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SET_PORT |
  519. READ_CONTROL | PROCESS_QUERY_INFORMATION ),
  520. User->User.Sid
  521. );
  522. if (!NT_SUCCESS(Status)) {
  523. IF_DEBUG {
  524. DbgPrint("CSRSS: ACE creation failed - status = %lx\n", Status);
  525. }
  526. goto error_cleanup;
  527. }
  528. //
  529. // Set DACL to NULL to deny all access
  530. //
  531. Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
  532. TRUE,
  533. Dacl,
  534. FALSE);
  535. if (!NT_SUCCESS(Status)) {
  536. IF_DEBUG {
  537. DbgPrint("CSRSS: set DACL failed - status = %lx\n", Status);
  538. }
  539. goto error_cleanup;
  540. }
  541. //
  542. // Put the DACL onto the process
  543. //
  544. Status = NtSetSecurityObject(NtCurrentProcess(),
  545. DACL_SECURITY_INFORMATION,
  546. SecurityDescriptor);
  547. if (!NT_SUCCESS(Status)) {
  548. IF_DEBUG {
  549. DbgPrint("CSRSS: set process DACL failed - status = %lx\n", Status);
  550. }
  551. }
  552. //
  553. // Cleanup
  554. //
  555. error_cleanup:
  556. if (SecurityDescriptor != NULL) {
  557. RtlFreeHeap( CsrHeap, 0, SecurityDescriptor );
  558. }
  559. if (User != NULL) {
  560. RtlFreeHeap( CsrHeap, 0, User );
  561. }
  562. return Status;
  563. }
  564. NTSTATUS
  565. CsrSetDirectorySecurity(
  566. IN HANDLE DirectoryHandle
  567. )
  568. {
  569. PSID WorldSid = NULL;
  570. PSID SystemSid = NULL;
  571. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  572. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  573. NTSTATUS Status;
  574. ULONG AclLength;
  575. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  576. PACL Dacl;
  577. //
  578. // Get the SIDs for world and system
  579. //
  580. Status = RtlAllocateAndInitializeSid( &WorldAuthority,
  581. 1,
  582. SECURITY_WORLD_RID,
  583. 0, 0, 0, 0, 0, 0, 0,
  584. &WorldSid
  585. );
  586. if (!NT_SUCCESS(Status)) {
  587. goto error_cleanup;
  588. }
  589. Status = RtlAllocateAndInitializeSid( &NtAuthority,
  590. 1,
  591. SECURITY_LOCAL_SYSTEM_RID,
  592. 0, 0, 0, 0, 0, 0, 0,
  593. &SystemSid
  594. );
  595. if (!NT_SUCCESS(Status)) {
  596. goto error_cleanup;
  597. }
  598. //
  599. // Allocate a buffer to hold the SD
  600. //
  601. AclLength = sizeof(ACL) +
  602. RtlLengthSid( WorldSid ) +
  603. RtlLengthSid( SystemSid ) +
  604. 2 * sizeof(ACCESS_ALLOWED_ACE);
  605. SecurityDescriptor = RtlAllocateHeap( CsrHeap,
  606. MAKE_TAG( SECURITY_TAG ) | HEAP_ZERO_MEMORY,
  607. SECURITY_DESCRIPTOR_MIN_LENGTH +
  608. AclLength
  609. );
  610. if (SecurityDescriptor == NULL) {
  611. Status = STATUS_NO_MEMORY;
  612. goto error_cleanup;
  613. }
  614. //
  615. // Create the SD
  616. //
  617. Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
  618. SECURITY_DESCRIPTOR_REVISION);
  619. if (!NT_SUCCESS(Status)) {
  620. IF_DEBUG {
  621. DbgPrint("CSRSS: SD creation failed - status = %lx\n", Status);
  622. }
  623. goto error_cleanup;
  624. }
  625. //
  626. // Create the DACL
  627. //
  628. Dacl = (PACL)((PCHAR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
  629. RtlCreateAcl( Dacl,
  630. AclLength,
  631. ACL_REVISION
  632. );
  633. Status = RtlAddAccessAllowedAce( Dacl,
  634. ACL_REVISION,
  635. STANDARD_RIGHTS_READ | DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
  636. WorldSid
  637. );
  638. if (!NT_SUCCESS(Status)) {
  639. IF_DEBUG {
  640. DbgPrint("CSRSS: ACE creation failed - status = %lx\n", Status);
  641. }
  642. goto error_cleanup;
  643. }
  644. Status = RtlAddAccessAllowedAce( Dacl,
  645. ACL_REVISION,
  646. DIRECTORY_ALL_ACCESS,
  647. SystemSid
  648. );
  649. if (!NT_SUCCESS(Status)) {
  650. IF_DEBUG {
  651. DbgPrint("CSRSS: ACE creation failed - status = %lx\n", Status);
  652. }
  653. goto error_cleanup;
  654. }
  655. //
  656. // Set DACL into the SD
  657. //
  658. Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
  659. TRUE,
  660. Dacl,
  661. FALSE);
  662. if (!NT_SUCCESS(Status)) {
  663. IF_DEBUG {
  664. DbgPrint("CSRSS: set DACL failed - status = %lx\n", Status);
  665. }
  666. goto error_cleanup;
  667. }
  668. //
  669. // Put the DACL onto the direcory
  670. //
  671. Status = NtSetSecurityObject(DirectoryHandle,
  672. DACL_SECURITY_INFORMATION,
  673. SecurityDescriptor);
  674. if (!NT_SUCCESS(Status)) {
  675. IF_DEBUG {
  676. DbgPrint("CSRSS: set directory DACL failed - status = %lx\n", Status);
  677. }
  678. }
  679. //
  680. // Cleanup
  681. //
  682. error_cleanup:
  683. if (SecurityDescriptor != NULL) {
  684. RtlFreeHeap( CsrHeap, 0, SecurityDescriptor );
  685. }
  686. if (WorldSid != NULL) {
  687. RtlFreeSid( WorldSid );
  688. }
  689. if (SystemSid != NULL) {
  690. RtlFreeSid( SystemSid );
  691. }
  692. return Status;
  693. }
  694. /*******************************************************************************
  695. *
  696. * CsrPopulateDosDevices
  697. *
  698. * Populate the new session specific DosDevices Directory. This is an
  699. * export called by ntuser\server when a connection is completed.
  700. *
  701. * The security descriptor on the sessions \DosDevices should already
  702. * have been set.
  703. *
  704. * ENTRY:
  705. * HANDLE NewDosDevicesDirectory - Session specific DosDevices Directory
  706. * PPROCESS_DEVICEMAP_INFORMATION pGlobalProcessDeviceMapInfo
  707. *
  708. * EXIT:
  709. * STATUS_SUCCESS
  710. *
  711. ******************************************************************************/
  712. NTSTATUS
  713. CsrPopulateDosDevices(
  714. VOID
  715. )
  716. {
  717. NTSTATUS Status = STATUS_SUCCESS;
  718. PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
  719. PROCESS_DEVICEMAP_INFORMATION GlobalProcessDeviceMapInfo;
  720. //
  721. // Get the global ProcessDeviceMap. We will use this to only add
  722. // non-network drive letters to the session specific dos devices
  723. // directory
  724. //
  725. Status = NtQueryInformationProcess( NtCurrentProcess(),
  726. ProcessDeviceMap,
  727. &GlobalProcessDeviceMapInfo.Query,
  728. sizeof( GlobalProcessDeviceMapInfo.Query ),
  729. NULL
  730. );
  731. if (!NT_SUCCESS( Status )) {
  732. DbgPrint("CSRSS: NtQueryInformationProcess failed in CsrPopulateDosDevices - status = %lx\n", Status);
  733. return Status;
  734. }
  735. //
  736. // Set the CSRSS's ProcessDeviceMap to the newly created DosDevices Directory
  737. //
  738. ProcessDeviceMapInfo.Set.DirectoryHandle = DosDevicesDirectory;
  739. Status = NtSetInformationProcess( NtCurrentProcess(),
  740. ProcessDeviceMap,
  741. &ProcessDeviceMapInfo.Set,
  742. sizeof( ProcessDeviceMapInfo.Set )
  743. );
  744. if (!NT_SUCCESS( Status )) {
  745. DbgPrint("CSRSS: NtSetInformationProcess failed in CsrPopulateDosDevices - status = %lx\n", Status);
  746. return Status;
  747. }
  748. //
  749. // Populate the session specfic DosDevices Directory
  750. //
  751. Status = CsrPopulateDosDevicesDirectory( DosDevicesDirectory, &GlobalProcessDeviceMapInfo );
  752. return Status;
  753. }
  754. /*******************************************************************************
  755. *
  756. * CsrPopulateDosDevicesDirectory
  757. *
  758. * Populate the new session specific DosDevices Direcotory
  759. *
  760. * ENTRY:
  761. * HANDLE NewDosDevicesDirectory - Session specific DosDevices Directory
  762. * PPROCESS_DEVICEMAP_INFORMATION pGlobalProcessDeviceMapInfo
  763. *
  764. * EXIT:
  765. * STATUS_SUCCESS
  766. *
  767. ******************************************************************************/
  768. NTSTATUS
  769. CsrPopulateDosDevicesDirectory( HANDLE NewDirectoryHandle,
  770. PPROCESS_DEVICEMAP_INFORMATION pGlobalProcessDeviceMapInfo )
  771. {
  772. NTSTATUS Status;
  773. UNICODE_STRING UnicodeString;
  774. UNICODE_STRING Target;
  775. OBJECT_ATTRIBUTES Attributes;
  776. HANDLE DirectoryHandle = NULL;
  777. HANDLE LinkHandle;
  778. POBJECT_DIRECTORY_INFORMATION DirInfo;
  779. ULONG DirInfoBufferLength = 16384; //16K
  780. PVOID DirInfoBuffer = NULL;
  781. WCHAR lpTargetPath[ 4096 ];
  782. ULONG Context;
  783. ULONG ReturnedLength = 0;
  784. ULONG DosDeviceDriveIndex = 0;
  785. WCHAR DosDeviceDriveLetter;
  786. //
  787. // Open the global DosDevices Directory. This used to populate the
  788. // the session specific DosDevices Directory
  789. //
  790. RtlInitUnicodeString( &UnicodeString, L"\\GLOBAL??" );
  791. InitializeObjectAttributes( &Attributes,
  792. &UnicodeString,
  793. OBJ_CASE_INSENSITIVE,
  794. NULL,
  795. NULL
  796. );
  797. Status = NtOpenDirectoryObject( &DirectoryHandle,
  798. DIRECTORY_QUERY,
  799. &Attributes
  800. );
  801. if (!NT_SUCCESS( Status )) {
  802. DbgPrint("CSRSS: NtOpenDirectoryObject failed in CsrPopulateDosDevicesDirectory - status = %lx\n", Status);
  803. return Status;
  804. }
  805. Restart:
  806. Context = 0;
  807. DirInfoBuffer = RtlAllocateHeap( CsrHeap,
  808. MAKE_TAG( PROCESS_TAG ) | HEAP_ZERO_MEMORY,
  809. DirInfoBufferLength
  810. );
  811. if (DirInfoBuffer == NULL) {
  812. Status = STATUS_NO_MEMORY;
  813. goto cleanup;
  814. }
  815. while (TRUE) {
  816. DirInfo = (POBJECT_DIRECTORY_INFORMATION)DirInfoBuffer;
  817. Status = NtQueryDirectoryObject( DirectoryHandle,
  818. (PVOID)DirInfo,
  819. DirInfoBufferLength,
  820. FALSE,
  821. FALSE,
  822. &Context,
  823. &ReturnedLength
  824. );
  825. //
  826. // Check the status of the operation.
  827. //
  828. if (!NT_SUCCESS( Status )) {
  829. if (Status == STATUS_BUFFER_TOO_SMALL) {
  830. DirInfoBufferLength = ReturnedLength;
  831. RtlFreeHeap( CsrHeap, 0, DirInfoBuffer );
  832. goto Restart;
  833. }
  834. if (Status == STATUS_NO_MORE_ENTRIES) {
  835. Status = STATUS_SUCCESS;
  836. }
  837. break;
  838. }
  839. while (DirInfo->Name.Length != 0) {
  840. if (!wcscmp( DirInfo->TypeName.Buffer, L"SymbolicLink" )) {
  841. InitializeObjectAttributes( &Attributes,
  842. &DirInfo->Name,
  843. OBJ_CASE_INSENSITIVE,
  844. DirectoryHandle,
  845. NULL
  846. );
  847. Status = NtOpenSymbolicLinkObject( &LinkHandle,
  848. SYMBOLIC_LINK_QUERY,
  849. &Attributes
  850. );
  851. if (NT_SUCCESS( Status )) {
  852. Target.Buffer = lpTargetPath;
  853. Target.Length = 0;
  854. Target.MaximumLength = 4096;
  855. ReturnedLength = 0;
  856. Status = NtQuerySymbolicLinkObject( LinkHandle,
  857. &Target,
  858. &ReturnedLength
  859. );
  860. NtClose( LinkHandle );
  861. if (NT_SUCCESS( Status )) {
  862. //
  863. // We only want to add Non-DOSDEVICE_DRIVE_REMOTE symbolic
  864. // links to the session specific directory
  865. //
  866. if ((DirInfo->Name.Length == 2 * sizeof( WCHAR )) &&
  867. (DirInfo->Name.Buffer[ 1 ] == L':')) {
  868. DosDeviceDriveLetter = RtlUpcaseUnicodeChar( DirInfo->Name.Buffer[ 0 ] );
  869. if ((DosDeviceDriveLetter >= L'A') && (DosDeviceDriveLetter <= L'Z')) {
  870. DosDeviceDriveIndex = DosDeviceDriveLetter - L'A';
  871. if ( (
  872. (pGlobalProcessDeviceMapInfo->Query.DriveType[DosDeviceDriveIndex] == DOSDEVICE_DRIVE_REMOTE)
  873. &&
  874. !(
  875. //Need to populate the Netware gateway drive
  876. ((Target.Length >= 13) && ((_wcsnicmp(Target.Buffer,L"\\Device\\NwRdr",13)==0)))
  877. &&
  878. ((Target.Length >= 16) && (Target.Buffer[15] != L':'))
  879. )
  880. )
  881. ||
  882. (
  883. (pGlobalProcessDeviceMapInfo->Query.DriveType[DosDeviceDriveIndex] == DOSDEVICE_DRIVE_CALCULATE)
  884. &&
  885. (
  886. ((Target.Length > 4) && (!_wcsnicmp(Target.Buffer,L"\\??\\",4)))
  887. ||
  888. ((Target.Length >= 14) && (!_wcsnicmp(Target.Buffer,L"\\Device\\WinDfs",14)))
  889. )
  890. )
  891. )
  892. {
  893. //Skip remote drives and virtual drives (subst)
  894. DirInfo = (POBJECT_DIRECTORY_INFORMATION)(((PUCHAR) DirInfo) + sizeof(OBJECT_DIRECTORY_INFORMATION));
  895. continue;
  896. }
  897. }
  898. }
  899. //
  900. // Create the new Symbolic Link
  901. //
  902. // The security on the new link is inherited
  903. // from the parent directory, which is setup
  904. // at create time.
  905. //
  906. InitializeObjectAttributes( &Attributes,
  907. &DirInfo->Name,
  908. 0,
  909. NewDirectoryHandle,
  910. NULL // Default security
  911. );
  912. Target.MaximumLength = Target.Length + sizeof( WCHAR );
  913. Attributes.Attributes |= OBJ_PERMANENT;
  914. Status = NtCreateSymbolicLinkObject( &LinkHandle,
  915. SYMBOLIC_LINK_ALL_ACCESS,
  916. &Attributes,
  917. &Target
  918. );
  919. Target.MaximumLength = 4096;
  920. // Don't close the handles. Cleaned up when CSRSS goes away
  921. if (!NT_SUCCESS( Status )) {
  922. #if DBG
  923. DbgPrint("CSRSS: Symbolic link creation failed in CsrPopulateDosDevicesDirectory for Name %ws and Target %ws- status = %lx for Session %ld\n", DirInfo->Name.Buffer, Target.Buffer, Status,NtCurrentPeb()->SessionId);
  924. #endif
  925. ASSERT(FALSE);
  926. }
  927. else {
  928. NtClose( LinkHandle );
  929. }
  930. }
  931. }
  932. }
  933. DirInfo = (POBJECT_DIRECTORY_INFORMATION)(((PUCHAR) DirInfo) + sizeof(OBJECT_DIRECTORY_INFORMATION));
  934. }
  935. }
  936. cleanup:
  937. if (DirectoryHandle) {
  938. NtClose(DirectoryHandle);
  939. }
  940. if (DirInfoBuffer) {
  941. RtlFreeHeap( CsrHeap, 0, DirInfoBuffer );
  942. }
  943. return Status;
  944. }
  945. /*******************************************************************************
  946. *
  947. * CsrCreateSessionObjectDirectory
  948. *
  949. * Creates \Sessions\<SessionId> and \Sessions\<SessionId>\DosDevices
  950. * Object Directories
  951. *
  952. * ENTRY:
  953. * ULONG SessionId
  954. *
  955. * EXIT:
  956. * STATUS_SUCCESS
  957. *
  958. ******************************************************************************/
  959. NTSTATUS
  960. CsrCreateSessionObjectDirectory( ULONG SessionId )
  961. {
  962. NTSTATUS Status = STATUS_SUCCESS;
  963. WCHAR szString[MAX_SESSION_PATH];
  964. WCHAR szTargetString[MAX_SESSION_PATH];
  965. UNICODE_STRING UnicodeString, LinkTarget;
  966. OBJECT_ATTRIBUTES Obja;
  967. HANDLE SymbolicLinkHandle;
  968. SECURITY_DESCRIPTOR DosDevicesSD;
  969. /*
  970. * \Sessions\BNOLINKS\0 -> \BaseNamedObjects
  971. * \Sessions\BNOLINKS\6 -> \Sessions\6\BaseNamedObjects
  972. * \Sessions\BNOLINKS\7 -> \Sessions\7\BaseNamedObjects
  973. */
  974. //
  975. //Create/Open the \\Sessions\BNOLINKS directory
  976. //
  977. swprintf(szString,L"%ws\\BNOLINKS",SESSION_ROOT);
  978. RtlInitUnicodeString( &UnicodeString, szString );
  979. InitializeObjectAttributes( &Obja,
  980. &UnicodeString,
  981. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  982. NULL,
  983. NULL
  984. );
  985. Status = NtCreateDirectoryObject( &BNOLinksDirectory,
  986. DIRECTORY_ALL_ACCESS,
  987. &Obja
  988. );
  989. if (!NT_SUCCESS( Status )) {
  990. DbgPrint("CSRSS: NtCreateDirectoryObject failed in CsrCreateSessionObjectDirectory - status = %lx\n", Status);
  991. return Status;
  992. }
  993. //
  994. // Create a symbolic link \\Sessions\BNOLINKS\<sessionid> pointing
  995. // to the session specific BaseNamedObjects directory
  996. // This symbolic link will be used by proccesses that want to e.g. access a
  997. // event in another session. This will be done by using the following
  998. // naming convention : Session\\<sessionid>\\ObjectName
  999. //
  1000. swprintf(szString,L"%ld",SessionId);
  1001. RtlInitUnicodeString( &UnicodeString, szString );
  1002. if (SessionId == 0) {
  1003. RtlInitUnicodeString( &LinkTarget, L"\\BaseNamedObjects" );
  1004. } else {
  1005. swprintf(szTargetString,L"%ws\\%ld\\BaseNamedObjects",SESSION_ROOT,SessionId);
  1006. RtlInitUnicodeString(&LinkTarget, szTargetString);
  1007. }
  1008. InitializeObjectAttributes( &Obja,
  1009. &UnicodeString,
  1010. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  1011. (HANDLE)BNOLinksDirectory,
  1012. NULL);
  1013. Status = NtCreateSymbolicLinkObject( &SymbolicLinkHandle,
  1014. SYMBOLIC_LINK_ALL_ACCESS,
  1015. &Obja,
  1016. &LinkTarget );
  1017. if (!NT_SUCCESS( Status )) {
  1018. DbgPrint("CSRSS: NtCreateSymbolicLinkObject failed in CsrCreateSessionObjectDirectory - status = %lx\n", Status);
  1019. return Status;
  1020. }
  1021. //
  1022. // Create the security descriptor to use for the object directories
  1023. //
  1024. Status = GetDosDevicesProtection( &DosDevicesSD );
  1025. if (!NT_SUCCESS( Status )) {
  1026. return Status;
  1027. }
  1028. //
  1029. // Create the Sessions\\<sessionid directory
  1030. //
  1031. swprintf(szString,L"%ws\\%ld",SESSION_ROOT,SessionId);
  1032. RtlInitUnicodeString( &UnicodeString, szString );
  1033. InitializeObjectAttributes( &Obja,
  1034. &UnicodeString,
  1035. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  1036. NULL,
  1037. &DosDevicesSD
  1038. );
  1039. Status = NtCreateDirectoryObject( &SessionObjectDirectory,
  1040. DIRECTORY_ALL_ACCESS,
  1041. &Obja
  1042. );
  1043. if (!NT_SUCCESS( Status )) {
  1044. DbgPrint("CSRSS: NtCreateDirectoryObject failed in CsrCreateSessionObjectDirectory - status = %lx\n", Status);
  1045. FreeDosDevicesProtection( &DosDevicesSD );
  1046. return Status;
  1047. }
  1048. RtlInitUnicodeString( &UnicodeString, L"DosDevices" );
  1049. InitializeObjectAttributes( &Obja,
  1050. &UnicodeString,
  1051. OBJ_CASE_INSENSITIVE,
  1052. SessionObjectDirectory,
  1053. &DosDevicesSD
  1054. );
  1055. //
  1056. // Create the Session specific DosDevices Directory
  1057. //
  1058. Status = NtCreateDirectoryObject( &DosDevicesDirectory,
  1059. DIRECTORY_ALL_ACCESS,
  1060. &Obja
  1061. );
  1062. if (!NT_SUCCESS( Status )) {
  1063. DbgPrint("CSRSS: NtCreateDirectoryObject failed in CsrCreateSessionObjectDirectory - status = %lx\n", Status);
  1064. FreeDosDevicesProtection( &DosDevicesSD );
  1065. return Status;
  1066. }
  1067. FreeDosDevicesProtection( &DosDevicesSD );
  1068. return Status;
  1069. }
  1070. NTSTATUS
  1071. GetDosDevicesProtection (
  1072. PSECURITY_DESCRIPTOR SecurityDescriptor
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This routine builds a security descriptor for use in creating
  1077. the \DosDevices object directory. The protection of \DosDevices
  1078. must establish inheritable protection which will dictate how
  1079. dos devices created via the DefineDosDevice() and
  1080. IoCreateUnprotectedSymbolicLink() apis can be managed.
  1081. The protection assigned is dependent upon an administrable registry
  1082. key:
  1083. Key: \hkey_local_machine\System\CurrentControlSet\Control\Session Manager
  1084. Value: [REG_DWORD] ProtectionMode
  1085. If this value is 0x1, then
  1086. Administrators may control all Dos devices,
  1087. Anyone may create new Dos devices (such as net drives
  1088. or additional printers),
  1089. Anyone may use any Dos device,
  1090. The creator of a Dos device may delete it.
  1091. Note that this protects system-defined LPTs and COMs so that only
  1092. administrators may redirect them. However, anyone may add
  1093. additional printers and direct them to wherever they would
  1094. like.
  1095. This is achieved with the following protection for the DosDevices
  1096. Directory object:
  1097. Grant: World: Execute | Read | Write (No Inherit)
  1098. Grant: System: All Access (No Inherit)
  1099. Grant: World: Execute (Inherit Only)
  1100. Grant: Admins: All Access (Inherit Only)
  1101. Grant: System: All Access (Inherit Only)
  1102. Grant: Owner: All Access (Inherit Only)
  1103. If this value is 0x0, or not present, then
  1104. Administrators may control all Dos devices,
  1105. Anyone may create new Dos devices (such as net drives
  1106. or additional printers),
  1107. Anyone may use any Dos device,
  1108. Anyone may delete Dos devices created with either DefineDosDevice()
  1109. or IoCreateUnprotectedSymbolicLink(). This is how network drives
  1110. and LPTs are created (but not COMs).
  1111. This is achieved with the following protection for the DosDevices
  1112. Directory object:
  1113. Grant: World: Execute | Read | Write (No Inherit)
  1114. Grant: System: All Access (No Inherit)
  1115. Grant: World: All Access (Inherit Only)
  1116. Arguments:
  1117. SecurityDescriptor - The address of a security descriptor to be
  1118. initialized and filled in. When this security descriptor is no
  1119. longer needed, you should call FreeDosDevicesProtection() to
  1120. free the protection information.
  1121. Return Value:
  1122. Returns one of the following status codes:
  1123. STATUS_SUCCESS - normal, successful completion.
  1124. --*/
  1125. {
  1126. NTSTATUS Status = STATUS_SUCCESS;
  1127. ULONG aceIndex, aclLength;
  1128. PACL dacl = NULL;
  1129. PACE_HEADER ace;
  1130. ACCESS_MASK accessMask;
  1131. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1132. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1133. SID_IDENTIFIER_AUTHORITY CreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  1134. PSID LocalSystemSid;
  1135. PSID WorldSid;
  1136. PSID CreatorOwnerSid;
  1137. PSID AliasAdminsSid;
  1138. UNICODE_STRING NameString;
  1139. OBJECT_ATTRIBUTES Obja;
  1140. ULONG ProtectionMode = 0;
  1141. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  1142. WCHAR ValueBuffer[ 32 ];
  1143. ULONG ResultLength;
  1144. HANDLE KeyHandle;
  1145. UCHAR inheritOnlyFlags = (OBJECT_INHERIT_ACE |
  1146. CONTAINER_INHERIT_ACE |
  1147. INHERIT_ONLY_ACE
  1148. );
  1149. UCHAR inheritFlags = (OBJECT_INHERIT_ACE |
  1150. CONTAINER_INHERIT_ACE
  1151. );
  1152. Status = RtlCreateSecurityDescriptor( SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  1153. if (!NT_SUCCESS( Status )) {
  1154. ASSERT( NT_SUCCESS( Status ) );
  1155. return( Status );
  1156. }
  1157. Status = RtlAllocateAndInitializeSid(
  1158. &NtAuthority,
  1159. 1,
  1160. SECURITY_LOCAL_SYSTEM_RID,
  1161. 0, 0, 0, 0, 0, 0, 0,
  1162. &LocalSystemSid
  1163. );
  1164. if (!NT_SUCCESS( Status )) {
  1165. ASSERT( NT_SUCCESS( Status ) );
  1166. return( Status );
  1167. }
  1168. Status = RtlAllocateAndInitializeSid(
  1169. &WorldAuthority,
  1170. 1,
  1171. SECURITY_WORLD_RID,
  1172. 0, 0, 0, 0, 0, 0, 0,
  1173. &WorldSid
  1174. );
  1175. if (!NT_SUCCESS( Status )) {
  1176. RtlFreeSid( LocalSystemSid );
  1177. ASSERT( NT_SUCCESS( Status ) );
  1178. return( Status );
  1179. }
  1180. Status = RtlAllocateAndInitializeSid(
  1181. &NtAuthority,
  1182. 2,
  1183. SECURITY_BUILTIN_DOMAIN_RID,
  1184. DOMAIN_ALIAS_RID_ADMINS,
  1185. 0, 0, 0, 0, 0, 0,
  1186. &AliasAdminsSid
  1187. );
  1188. if (!NT_SUCCESS( Status )) {
  1189. RtlFreeSid( LocalSystemSid );
  1190. RtlFreeSid( WorldSid );
  1191. ASSERT( NT_SUCCESS( Status ) );
  1192. return( Status );
  1193. }
  1194. Status = RtlAllocateAndInitializeSid(
  1195. &CreatorAuthority,
  1196. 1,
  1197. SECURITY_CREATOR_OWNER_RID,
  1198. 0, 0, 0, 0, 0, 0, 0,
  1199. &CreatorOwnerSid
  1200. );
  1201. if (!NT_SUCCESS( Status )) {
  1202. RtlFreeSid( LocalSystemSid );
  1203. RtlFreeSid( WorldSid );
  1204. RtlFreeSid( AliasAdminsSid );
  1205. ASSERT( NT_SUCCESS( Status ) );
  1206. return( Status );
  1207. }
  1208. RtlInitUnicodeString( &NameString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager" );
  1209. InitializeObjectAttributes( &Obja,
  1210. &NameString,
  1211. OBJ_CASE_INSENSITIVE,
  1212. NULL,
  1213. NULL );
  1214. Status = NtOpenKey( &KeyHandle,
  1215. KEY_READ,
  1216. &Obja
  1217. );
  1218. if (NT_SUCCESS(Status)) {
  1219. RtlInitUnicodeString( &NameString, L"ProtectionMode" );
  1220. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
  1221. Status = NtQueryValueKey( KeyHandle,
  1222. &NameString,
  1223. KeyValuePartialInformation,
  1224. KeyValueInformation,
  1225. sizeof( ValueBuffer ),
  1226. &ResultLength
  1227. );
  1228. if (NT_SUCCESS(Status)) {
  1229. if (KeyValueInformation->Type == REG_DWORD &&
  1230. *(PULONG)KeyValueInformation->Data) {
  1231. ProtectionMode = *(PULONG)KeyValueInformation->Data;
  1232. }
  1233. }
  1234. NtClose( KeyHandle );
  1235. }
  1236. if (ProtectionMode & 0x00000003) {
  1237. //
  1238. // If ProtectionMode is set to 1 or 2 Terminal Server
  1239. // locks down sessions tight.
  1240. //
  1241. // Dacl:
  1242. // Grant: System: All Access (With Inherit)
  1243. // Grant: Admins: All Access (With Inherit)
  1244. // Grant: Owner: All Access (Inherit Only)
  1245. // Grant: World: No Access
  1246. //
  1247. aclLength = sizeof( ACL ) +
  1248. 3 * sizeof( ACCESS_ALLOWED_ACE ) +
  1249. RtlLengthSid( LocalSystemSid ) +
  1250. RtlLengthSid( AliasAdminsSid ) +
  1251. RtlLengthSid( CreatorOwnerSid );
  1252. dacl = (PACL)RtlAllocateHeap( CsrHeap,
  1253. MAKE_TAG( SECURITY_TAG ) | HEAP_ZERO_MEMORY,
  1254. aclLength );
  1255. if (dacl == NULL) {
  1256. Status = STATUS_NO_MEMORY;
  1257. ASSERT( NT_SUCCESS( Status ) );
  1258. goto cleanup;
  1259. }
  1260. Status = RtlCreateAcl( dacl, aclLength, ACL_REVISION2);
  1261. if (!NT_SUCCESS( Status )) {
  1262. ASSERT( NT_SUCCESS( Status ) );
  1263. goto cleanup;
  1264. }
  1265. aceIndex = 0;
  1266. accessMask = (GENERIC_ALL);
  1267. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, LocalSystemSid );
  1268. if (!NT_SUCCESS( Status )) {
  1269. ASSERT( NT_SUCCESS( Status ) );
  1270. goto cleanup;
  1271. }
  1272. Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace );
  1273. if (!NT_SUCCESS( Status )) {
  1274. ASSERT( NT_SUCCESS( Status ) );
  1275. goto cleanup;
  1276. }
  1277. ace->AceFlags |= inheritFlags;
  1278. aceIndex++;
  1279. accessMask = (GENERIC_ALL);
  1280. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, AliasAdminsSid );
  1281. if (!NT_SUCCESS( Status )) {
  1282. ASSERT( NT_SUCCESS( Status ) );
  1283. goto cleanup;
  1284. }
  1285. Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace );
  1286. if (!NT_SUCCESS( Status )) {
  1287. ASSERT( NT_SUCCESS( Status ) );
  1288. goto cleanup;
  1289. }
  1290. ace->AceFlags |= inheritFlags;
  1291. //
  1292. // Inherit only ACE at the end of the ACL
  1293. // Owner
  1294. //
  1295. aceIndex++;
  1296. accessMask = (GENERIC_ALL);
  1297. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, CreatorOwnerSid );
  1298. if (!NT_SUCCESS( Status )) {
  1299. ASSERT( NT_SUCCESS( Status ) );
  1300. goto cleanup;
  1301. }
  1302. Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace );
  1303. if (!NT_SUCCESS( Status )) {
  1304. ASSERT( NT_SUCCESS( Status ) );
  1305. goto cleanup;
  1306. }
  1307. ace->AceFlags |= inheritOnlyFlags;
  1308. Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor,
  1309. TRUE, //DaclPresent,
  1310. dacl, //Dacl
  1311. FALSE ); //!DaclDefaulted
  1312. if (!NT_SUCCESS( Status )) {
  1313. ASSERT( NT_SUCCESS( Status ) );
  1314. goto cleanup;
  1315. }
  1316. } else {
  1317. //
  1318. // DACL:
  1319. // Grant: World: Execute | Read | Write (No Inherit)
  1320. // Grant: System: All Access (No Inherit)
  1321. // Grant: World: All Access (Inherit Only)
  1322. //
  1323. aclLength = sizeof( ACL ) +
  1324. 3 * sizeof( ACCESS_ALLOWED_ACE ) +
  1325. (2*RtlLengthSid( WorldSid )) +
  1326. RtlLengthSid( LocalSystemSid );
  1327. dacl = (PACL)RtlAllocateHeap( CsrHeap,
  1328. MAKE_TAG( SECURITY_TAG ) | HEAP_ZERO_MEMORY,
  1329. aclLength );
  1330. if (dacl == NULL) {
  1331. ASSERT( NT_SUCCESS( Status ) );
  1332. Status = STATUS_NO_MEMORY;
  1333. goto cleanup;
  1334. }
  1335. Status = RtlCreateAcl( dacl, aclLength, ACL_REVISION2);
  1336. if (!NT_SUCCESS( Status )) {
  1337. ASSERT( NT_SUCCESS( Status ) );
  1338. goto cleanup;
  1339. }
  1340. //
  1341. // Non-inheritable ACEs first
  1342. // World
  1343. // System
  1344. //
  1345. aceIndex = 0;
  1346. accessMask = (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
  1347. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, WorldSid );
  1348. if (!NT_SUCCESS( Status )) {
  1349. ASSERT( NT_SUCCESS( Status ) );
  1350. goto cleanup;
  1351. }
  1352. aceIndex++;
  1353. accessMask = (GENERIC_ALL);
  1354. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, LocalSystemSid );
  1355. if (!NT_SUCCESS( Status )) {
  1356. ASSERT( NT_SUCCESS( Status ) );
  1357. goto cleanup;
  1358. }
  1359. //
  1360. // Inheritable ACEs at the end of the ACL
  1361. // World
  1362. //
  1363. aceIndex++;
  1364. accessMask = (GENERIC_ALL);
  1365. Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, WorldSid );
  1366. if (!NT_SUCCESS( Status )) {
  1367. ASSERT( NT_SUCCESS( Status ) );
  1368. goto cleanup;
  1369. }
  1370. Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace );
  1371. if (!NT_SUCCESS( Status )) {
  1372. ASSERT( NT_SUCCESS( Status ) );
  1373. goto cleanup;
  1374. }
  1375. ace->AceFlags |= inheritOnlyFlags;
  1376. Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor,
  1377. TRUE, //DaclPresent,
  1378. dacl, //Dacl
  1379. FALSE ); //!DaclDefaulted
  1380. if (!NT_SUCCESS( Status )) {
  1381. ASSERT( NT_SUCCESS( Status ) );
  1382. goto cleanup;
  1383. }
  1384. }
  1385. cleanup:
  1386. if (!NT_SUCCESS( Status ) && (dacl != NULL)) {
  1387. RtlFreeHeap( CsrHeap, 0, dacl);
  1388. }
  1389. RtlFreeSid( LocalSystemSid );
  1390. RtlFreeSid( WorldSid );
  1391. RtlFreeSid( AliasAdminsSid );
  1392. RtlFreeSid( CreatorOwnerSid );
  1393. if (!NT_SUCCESS( Status )) {
  1394. DbgPrint("CSRSS: GetDosDevicesProtection failed - status = %lx\n", Status);
  1395. ASSERT( NT_SUCCESS( Status ) );
  1396. }
  1397. return Status;
  1398. }
  1399. VOID
  1400. FreeDosDevicesProtection (
  1401. PSECURITY_DESCRIPTOR SecurityDescriptor
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This routine frees memory allocated via GetDosDevicesProtection().
  1406. Arguments:
  1407. SecurityDescriptor - The address of a security descriptor initialized by
  1408. GetDosDevicesProtection().
  1409. Return Value:
  1410. None.
  1411. --*/
  1412. {
  1413. NTSTATUS Status;
  1414. PACL Dacl = NULL;
  1415. BOOLEAN DaclPresent, Defaulted;
  1416. Status = RtlGetDaclSecurityDescriptor ( SecurityDescriptor,
  1417. &DaclPresent,
  1418. &Dacl,
  1419. &Defaulted );
  1420. ASSERT( NT_SUCCESS( Status ) );
  1421. ASSERT( DaclPresent );
  1422. ASSERT( Dacl != NULL );
  1423. if ((NT_SUCCESS( Status )) && (Dacl != NULL ) ) {
  1424. RtlFreeHeap( CsrHeap, 0, Dacl);
  1425. }
  1426. }