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.

1092 lines
29 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. data.c
  5. Abstract:
  6. This module contains global data for SAC.
  7. Author:
  8. Sean Selitrennikoff (v-seans) - Jan 11, 1999
  9. Revision History:
  10. --*/
  11. #include "sac.h"
  12. NTSTATUS
  13. CreateDeviceSecurityDescriptor(
  14. IN PVOID DeviceOrDriverObject
  15. );
  16. NTSTATUS
  17. BuildDeviceAcl(
  18. OUT PACL *DeviceAcl
  19. );
  20. VOID
  21. WorkerThreadStartUp(
  22. IN PVOID StartContext
  23. );
  24. VOID
  25. InitializeCmdEventInfo(
  26. VOID
  27. );
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text( INIT, InitializeGlobalData)
  30. #pragma alloc_text( INIT, CreateDeviceSecurityDescriptor )
  31. #pragma alloc_text( INIT, BuildDeviceAcl )
  32. #endif
  33. //
  34. // Globally defined variables are here.
  35. //
  36. //
  37. // Define the I/O Manager methods.
  38. //
  39. // The I/O manager is responsible for the behavior layer between
  40. // the channels and the serial port.
  41. //
  42. // Note: currently, the cmd routines are not-multithreadable.
  43. //
  44. #if 0
  45. IO_MGR_HANDLE_EVENT IoMgrHandleEvent = XmlMgrHandleEvent;
  46. IO_MGR_INITITIALIZE IoMgrInitialize = XmlMgrInitialize;
  47. IO_MGR_SHUTDOWN IoMgrShutdown = XmlMgrShutdown;
  48. IO_MGR_WORKER IoMgrWorkerProcessEvents = XmlMgrWorkerProcessEvents;
  49. IO_MGR_IS_CURRENT_CHANNEL IoMgrIsCurrentChannel = XmlMgrIsCurrentChannel;
  50. #else
  51. IO_MGR_HANDLE_EVENT IoMgrHandleEvent = ConMgrHandleEvent;
  52. IO_MGR_INITITIALIZE IoMgrInitialize = ConMgrInitialize;
  53. IO_MGR_SHUTDOWN IoMgrShutdown = ConMgrShutdown;
  54. IO_MGR_WORKER IoMgrWorkerProcessEvents = ConMgrWorkerProcessEvents;
  55. IO_MGR_IS_WRITE_ENABLED IoMgrIsWriteEnabled = ConMgrIsWriteEnabled;
  56. IO_MGR_WRITE_DATA IoMgrWriteData = ConMgrWriteData;
  57. IO_MGR_FLUSH_DATA IoMgrFlushData = ConMgrFlushData;
  58. #endif
  59. PMACHINE_INFORMATION MachineInformation = NULL;
  60. BOOLEAN GlobalDataInitialized = FALSE;
  61. UCHAR TmpBuffer[sizeof(PROCESS_PRIORITY_CLASS)];
  62. BOOLEAN IoctlSubmitted;
  63. LONG ProcessingType = SAC_NO_OP;
  64. HANDLE SACEventHandle;
  65. PKEVENT SACEvent=NULL;
  66. #if ENABLE_CMD_SESSION_PERMISSION_CHECKING
  67. BOOLEAN CommandConsoleLaunchingEnabled;
  68. #endif
  69. //
  70. // Globals for communicating with the user process responsible
  71. // for launching CMD consoles
  72. //
  73. PVOID RequestSacCmdEventObjectBody = NULL;
  74. PVOID RequestSacCmdEventWaitObjectBody = NULL;
  75. PVOID RequestSacCmdSuccessEventObjectBody = NULL;
  76. PVOID RequestSacCmdSuccessEventWaitObjectBody = NULL;
  77. PVOID RequestSacCmdFailureEventObjectBody = NULL;
  78. PVOID RequestSacCmdFailureEventWaitObjectBody = NULL;
  79. BOOLEAN HaveUserModeServiceCmdEventInfo = FALSE;
  80. KMUTEX SACCmdEventInfoMutex;
  81. #if ENABLE_SERVICE_FILE_OBJECT_CHECKING
  82. //
  83. // In order to prevent a rogue process from unregistering the
  84. // cmd event info from underneath the service, we only allow
  85. // the process that registered to unregister.
  86. //
  87. PFILE_OBJECT ServiceProcessFileObject = NULL;
  88. #endif
  89. //
  90. // Globals for managing incremental UTF8 encoding for VTUTF8 channels
  91. //
  92. WCHAR IncomingUnicodeValue;
  93. UCHAR IncomingUtf8ConversionBuffer[3];
  94. #if DBG
  95. ULONG SACDebug = 0x0;
  96. #endif
  97. BOOLEAN
  98. InitializeGlobalData(
  99. IN PUNICODE_STRING RegistryPath,
  100. IN PDRIVER_OBJECT DriverObject
  101. )
  102. /*++
  103. Routine Description:
  104. This routine initializes all the driver components that are shared across devices.
  105. Arguments:
  106. RegistryPath - A pointer to the location in the registry to read values from.
  107. DriverObject - pointer to DriverObject
  108. Return Value:
  109. TRUE if successful, else FALSE
  110. --*/
  111. {
  112. NTSTATUS Status;
  113. UNICODE_STRING DosName;
  114. UNICODE_STRING NtName;
  115. UNICODE_STRING UnicodeString;
  116. UNREFERENCED_PARAMETER(RegistryPath);
  117. PAGED_CODE();
  118. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  119. KdPrint(("SAC InitializeGlobalData: Entering.\n")));
  120. if (!GlobalDataInitialized) {
  121. //
  122. // Create a symbolic link from a DosDevice to this device so that a user-mode app can open us.
  123. //
  124. RtlInitUnicodeString(&DosName, SAC_DOSDEVICE_NAME);
  125. RtlInitUnicodeString(&NtName, SAC_DEVICE_NAME);
  126. Status = IoCreateSymbolicLink(&DosName, &NtName);
  127. if (!NT_SUCCESS(Status)) {
  128. return FALSE;
  129. }
  130. //
  131. // Initialize internal memory system
  132. //
  133. if (!InitializeMemoryManagement()) {
  134. IoDeleteSymbolicLink(&DosName);
  135. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  136. KdPrint(("SAC InitializeGlobalData: Exiting with status FALSE\n")));
  137. return FALSE;
  138. }
  139. Status = PreloadGlobalMessageTable(DriverObject->DriverStart);
  140. if (!NT_SUCCESS(Status)) {
  141. IoDeleteSymbolicLink(&DosName);
  142. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  143. KdPrint(( "SAC DriverEntry: unable to pre-load message table: %X\n", Status )));
  144. return FALSE;
  145. }
  146. #if ENABLE_CMD_SESSION_PERMISSION_CHECKING
  147. //
  148. // determine if the SAC driver has permission to launch cmd sessions
  149. //
  150. Status = GetCommandConsoleLaunchingPermission(&CommandConsoleLaunchingEnabled);
  151. if (!NT_SUCCESS(Status)) {
  152. IF_SAC_DEBUG(
  153. SAC_DEBUG_FAILS,
  154. KdPrint(( "SAC DriverEntry: failed GetCommandConsoleLaunchingPermission: %X\n", Status))
  155. );
  156. //
  157. // We don't want to fail on this operation
  158. //
  159. NOTHING;
  160. }
  161. #if ENABLE_SACSVR_START_TYPE_OVERRIDE
  162. else {
  163. //
  164. // Here we execute the command console service
  165. // start type policy. The goal is to provide
  166. // a means for the service to automatically start
  167. // when the cmd session feature is not explicitly
  168. // turned off.
  169. //
  170. // Here is the state table:
  171. //
  172. // Command Console Feature Enabled:
  173. //
  174. // service start type:
  175. //
  176. // automatic --> NOP
  177. // manual --> automatic
  178. // disabled --> NOP
  179. //
  180. // Command Console Feature Disabled:
  181. //
  182. // service start type:
  183. //
  184. // automatic --> NOP
  185. // manual --> NOP
  186. // disabled --> NOP
  187. //
  188. // service (sacsvr) fails registration
  189. //
  190. if (IsCommandConsoleLaunchingEnabled()) {
  191. //
  192. // Modify the service start type if appropriate
  193. //
  194. Status = ImposeSacCmdServiceStartTypePolicy();
  195. if (!NT_SUCCESS(Status)) {
  196. IF_SAC_DEBUG(
  197. SAC_DEBUG_FAILS,
  198. KdPrint(( "SAC DriverEntry: failed ImposeSacCmdServiceStartTypePolicy: %X\n", Status ))
  199. );
  200. // We don't want to fail on this operation
  201. //
  202. NOTHING;
  203. }
  204. } else {
  205. //
  206. // We do nothing here
  207. //
  208. NOTHING;
  209. }
  210. }
  211. #endif
  212. #endif
  213. //
  214. //
  215. //
  216. Utf8ConversionBuffer = (PUCHAR)ALLOCATE_POOL(
  217. Utf8ConversionBufferSize,
  218. GENERAL_POOL_TAG
  219. );
  220. if (!Utf8ConversionBuffer) {
  221. TearDownGlobalMessageTable();
  222. IoDeleteSymbolicLink(&DosName);
  223. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  224. KdPrint(( "SAC DriverEntry: unable to allocate memory for UTF8 translation." )));
  225. return FALSE;
  226. }
  227. //
  228. // initialize the channel manager
  229. //
  230. Status = ChanMgrInitialize();
  231. if (!NT_SUCCESS(Status)) {
  232. FREE_POOL(&Utf8ConversionBuffer);
  233. TearDownGlobalMessageTable();
  234. IoDeleteSymbolicLink(&DosName);
  235. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  236. KdPrint(( "SAC DriverEntry: Failed to create SAC Channel" )));
  237. return FALSE;
  238. }
  239. //
  240. // Initialize the serial port buffer
  241. //
  242. SerialPortBuffer = ALLOCATE_POOL(SERIAL_PORT_BUFFER_SIZE, GENERAL_POOL_TAG);
  243. if (! SerialPortBuffer) {
  244. IF_SAC_DEBUG(
  245. SAC_DEBUG_FAILS,
  246. KdPrint(("SAC InitializeDeviceData: Failed to allocate Serial Port Buffer\n"))
  247. );
  248. return FALSE;
  249. }
  250. RtlZeroMemory(SerialPortBuffer, SERIAL_PORT_BUFFER_SIZE);
  251. //
  252. // Initialize the Cmd Console Event information
  253. //
  254. KeInitializeMutex(&SACCmdEventInfoMutex, 0);
  255. InitializeCmdEventInfo();
  256. //
  257. // Globals are initialized
  258. //
  259. GlobalDataInitialized = TRUE;
  260. ProcessingType = SAC_NO_OP;
  261. IoctlSubmitted = FALSE;
  262. //
  263. // Setup notification event
  264. //
  265. RtlInitUnicodeString(&UnicodeString, L"\\SACEvent");
  266. SACEvent = IoCreateSynchronizationEvent(&UnicodeString, &SACEventHandle);
  267. if (SACEvent == NULL) {
  268. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  269. KdPrint(("SAC InitializeGlobalData: Exiting with Event NULL\n")));
  270. return FALSE;
  271. }
  272. //
  273. // Retrieve all the machine-specific identification information.
  274. //
  275. InitializeMachineInformation();
  276. //
  277. // Populate the HeadlessDispatch structure with the Machine info
  278. //
  279. Status = RegisterBlueScreenMachineInformation();
  280. if (! NT_SUCCESS(Status)) {
  281. IF_SAC_DEBUG(
  282. SAC_DEBUG_FAILS,
  283. KdPrint(("SAC InitializeGlobalData: Failed to register blue screen machine info\n"))
  284. );
  285. return FALSE;
  286. }
  287. }
  288. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  289. KdPrint(("SAC InitializeGlobalData: Exiting with status TRUE\n")));
  290. return TRUE;
  291. } // InitializeGlobalData
  292. VOID
  293. FreeGlobalData(
  294. VOID
  295. )
  296. /*++
  297. Routine Description:
  298. This routine frees all shared components.
  299. Arguments:
  300. None.
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. UNICODE_STRING DosName;
  306. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeGlobalData: Entering.\n")));
  307. if (GlobalDataInitialized) {
  308. //
  309. //
  310. //
  311. if(SACEvent != NULL){
  312. ZwClose(SACEventHandle);
  313. SACEvent = NULL;
  314. }
  315. //
  316. //
  317. //
  318. TearDownGlobalMessageTable();
  319. //
  320. //
  321. //
  322. RtlInitUnicodeString(&DosName, SAC_DOSDEVICE_NAME);
  323. IoDeleteSymbolicLink(&DosName);
  324. //
  325. // Shutdown the console manager
  326. //
  327. // Note: this should be done before shutting down
  328. // the channel manager to give the IO manager
  329. // a chance to cleanly shut itself down.
  330. //
  331. IoMgrShutdown();
  332. //
  333. // Shutdown the channel manager
  334. //
  335. ChanMgrShutdown();
  336. //
  337. // Release the serial port buffer
  338. //
  339. SAFE_FREE_POOL(&SerialPortBuffer);
  340. //
  341. // Release the machine information gathered at driver entry
  342. //
  343. FreeMachineInformation();
  344. //
  345. // Free the internal memory management system
  346. //
  347. FreeMemoryManagement();
  348. //
  349. // Global data is no longer present
  350. //
  351. GlobalDataInitialized = FALSE;
  352. }
  353. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeGlobalData: Exiting.\n")));
  354. } // FreeGlobalData
  355. BOOLEAN
  356. InitializeDeviceData(
  357. PDEVICE_OBJECT DeviceObject
  358. )
  359. /*++
  360. Routine Description:
  361. This routine initializes all the parts specific for each device.
  362. Arguments:
  363. DeviceObject - pointer to device object to be initialized.
  364. Return Value:
  365. TRUE if successful, else FALSE
  366. --*/
  367. {
  368. NTSTATUS Status;
  369. LARGE_INTEGER Time;
  370. LONG Priority;
  371. HEADLESS_CMD_ENABLE_TERMINAL Command;
  372. PSAC_DEVICE_CONTEXT DeviceContext;
  373. PWSTR XMLBuffer;
  374. PAGED_CODE();
  375. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  376. KdPrint(("SAC InitializeDeviceData: Entering.\n")));
  377. DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  378. if (!DeviceContext->InitializedAndReady) {
  379. DeviceObject->StackSize = DEFAULT_IRP_STACK_SIZE;
  380. DeviceObject->Flags |= DO_DIRECT_IO;
  381. DeviceContext->DeviceObject = DeviceObject;
  382. DeviceContext->PriorityBoost = DEFAULT_PRIORITY_BOOST;
  383. DeviceContext->ExitThread = FALSE;
  384. DeviceContext->Processing = FALSE;
  385. //
  386. //
  387. //
  388. KeInitializeTimer(&(DeviceContext->Timer));
  389. KeInitializeDpc(&(DeviceContext->Dpc), &TimerDpcRoutine, DeviceContext);
  390. KeInitializeSpinLock(&(DeviceContext->SpinLock));
  391. KeInitializeEvent(&(DeviceContext->ProcessEvent), SynchronizationEvent, FALSE);
  392. InitializeListHead(&(DeviceContext->IrpQueue));
  393. //
  394. // Enable the terminal
  395. //
  396. Command.Enable = TRUE;
  397. Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
  398. &Command,
  399. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  400. NULL,
  401. NULL
  402. );
  403. if (!NT_SUCCESS(Status)) {
  404. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  405. KdPrint(("SAC InitializeDeviceData: Exiting (1) with status FALSE\n")));
  406. return FALSE;
  407. }
  408. //
  409. // Remember a pointer to the system process. We'll use this pointer
  410. // for KeAttachProcess() calls so that we can open handles in the
  411. // context of the system process.
  412. //
  413. DeviceContext->SystemProcess = (PKPROCESS)IoGetCurrentProcess();
  414. //
  415. // Create the security descriptor used for raw access checks.
  416. //
  417. Status = CreateDeviceSecurityDescriptor(DeviceContext);
  418. if (!NT_SUCCESS(Status)) {
  419. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  420. KdPrint(("SAC InitializeDeviceData: Exiting (2) with status FALSE\n")));
  421. Command.Enable = FALSE;
  422. Status = HeadlessDispatch(
  423. HeadlessCmdEnableTerminal,
  424. &Command,
  425. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  426. NULL,
  427. NULL
  428. );
  429. if (! NT_SUCCESS(Status)) {
  430. IF_SAC_DEBUG(
  431. SAC_DEBUG_FAILS,
  432. KdPrint(("SAC InitializeDeviceData: Failed dispatch\n")));
  433. }
  434. return FALSE;
  435. }
  436. //
  437. // Start a thread to handle requests
  438. //
  439. Status = PsCreateSystemThread(&(DeviceContext->ThreadHandle),
  440. PROCESS_ALL_ACCESS,
  441. NULL,
  442. NULL,
  443. NULL,
  444. WorkerThreadStartUp,
  445. DeviceContext
  446. );
  447. if (!NT_SUCCESS(Status)) {
  448. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  449. KdPrint(("SAC InitializeDeviceData: Exiting (3) with status FALSE\n")));
  450. Command.Enable = FALSE;
  451. Status = HeadlessDispatch(
  452. HeadlessCmdEnableTerminal,
  453. &Command,
  454. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  455. NULL,
  456. NULL
  457. );
  458. if (! NT_SUCCESS(Status)) {
  459. IF_SAC_DEBUG(
  460. SAC_DEBUG_FAILS,
  461. KdPrint(("SAC InitializeDeviceData: Failed dispatch\n")));
  462. }
  463. return FALSE;
  464. }
  465. //
  466. // Set this thread to the real-time highest priority so that it will be
  467. // responsive.
  468. //
  469. Priority = HIGH_PRIORITY;
  470. Status = NtSetInformationThread(DeviceContext->ThreadHandle,
  471. ThreadPriority,
  472. &Priority,
  473. sizeof(Priority)
  474. );
  475. if (!NT_SUCCESS(Status)) {
  476. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  477. KdPrint(("SAC InitializeDeviceData: Exiting (6) with status FALSE\n")));
  478. //
  479. // Tell thread to exit.
  480. //
  481. DeviceContext->ExitThread = TRUE;
  482. KeInitializeEvent(&(DeviceContext->ThreadExitEvent), SynchronizationEvent, FALSE);
  483. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  484. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->ThreadExitEvent), Executive, KernelMode, FALSE, NULL);
  485. ASSERT(Status == STATUS_SUCCESS);
  486. Command.Enable = FALSE;
  487. Status = HeadlessDispatch(
  488. HeadlessCmdEnableTerminal,
  489. &Command,
  490. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  491. NULL,
  492. NULL
  493. );
  494. if (! NT_SUCCESS(Status)) {
  495. IF_SAC_DEBUG(
  496. SAC_DEBUG_FAILS,
  497. KdPrint(("SAC InitializeDeviceData: Failed dispatch\n")));
  498. }
  499. return FALSE;
  500. }
  501. //
  502. // Send XML machine information to management application
  503. //
  504. Status = TranslateMachineInformationXML(
  505. &XMLBuffer,
  506. NULL
  507. );
  508. if (NT_SUCCESS(Status)) {
  509. UTF8EncodeAndSend(XML_VERSION_HEADER);
  510. UTF8EncodeAndSend(XMLBuffer);
  511. FREE_POOL(&XMLBuffer);
  512. }
  513. //
  514. // Initialize the console manager
  515. //
  516. Status = IoMgrInitialize();
  517. if (! NT_SUCCESS(Status)) {
  518. return FALSE;
  519. }
  520. //
  521. // Start our timer
  522. //
  523. Time.QuadPart = Int32x32To64((LONG)4, -1000);
  524. KeSetTimerEx(&(DeviceContext->Timer), Time, (LONG)4, &(DeviceContext->Dpc));
  525. DeviceContext->InitializedAndReady = TRUE;
  526. }
  527. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  528. KdPrint(("SAC InitializeDeviceData: Exiting with status TRUE\n")));
  529. return TRUE;
  530. } // InitializeDeviceData
  531. VOID
  532. FreeDeviceData(
  533. PDEVICE_OBJECT DeviceObject
  534. )
  535. /*++
  536. Routine Description:
  537. This routine frees all components specific to a device..
  538. Arguments:
  539. DeviceContext - The device to work on.
  540. Return Value:
  541. It will stop and wait, if necessary, for any processing to complete.
  542. --*/
  543. {
  544. KIRQL OldIrql;
  545. NTSTATUS Status;
  546. PSAC_DEVICE_CONTEXT DeviceContext;
  547. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Entering.\n")));
  548. DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  549. if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) {
  550. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Exiting.\n")));
  551. return;
  552. }
  553. //
  554. // Wait for all processing to complete
  555. //
  556. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  557. while (DeviceContext->Processing) {
  558. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Waiting....\n")));
  559. KeInitializeEvent(&(DeviceContext->UnloadEvent), SynchronizationEvent, FALSE);
  560. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  561. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->UnloadEvent), Executive, KernelMode, FALSE, NULL);
  562. ASSERT(Status == STATUS_SUCCESS);
  563. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  564. }
  565. DeviceContext->Processing = TRUE;
  566. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  567. KeCancelTimer(&(DeviceContext->Timer));
  568. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  569. DeviceContext->Processing = FALSE;
  570. //
  571. // Signal the thread to exit
  572. //
  573. KeInitializeEvent(&(DeviceContext->UnloadEvent), SynchronizationEvent, FALSE);
  574. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  575. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  576. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->UnloadEvent), Executive, KernelMode, FALSE, NULL);
  577. ASSERT(Status == STATUS_SUCCESS);
  578. //
  579. // Finish up cleaning up.
  580. //
  581. IoUnregisterShutdownNotification(DeviceObject);
  582. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  583. DeviceContext->InitializedAndReady = FALSE;
  584. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  585. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Exiting.\n")));
  586. } // FreeDeviceData
  587. VOID
  588. WorkerThreadStartUp(
  589. IN PVOID StartContext
  590. )
  591. /*++
  592. Routine Description:
  593. This routine is the start up routine for the worker thread. It justn
  594. sends the worker thread to the processing routine.
  595. Arguments:
  596. StartContext - A pointer to the device to work on.
  597. Return Value:
  598. None.
  599. --*/
  600. {
  601. WorkerProcessEvents((PSAC_DEVICE_CONTEXT)StartContext);
  602. }
  603. NTSTATUS
  604. BuildDeviceAcl(
  605. OUT PACL *pDAcl
  606. )
  607. /*++
  608. Routine Description:
  609. This routine builds an ACL which gives System READ/WRITE access.
  610. All other principals have no access.
  611. Arguments:
  612. pDAcl - Output pointer to the new ACL.
  613. Return Value:
  614. STATUS_SUCCESS or an appropriate error code.
  615. --*/
  616. {
  617. NTSTATUS status;
  618. PACL dacl;
  619. SECURITY_DESCRIPTOR securityDescriptor;
  620. ULONG length;
  621. //
  622. // Default:
  623. //
  624. if( !pDAcl ) {
  625. return STATUS_INVALID_PARAMETER;
  626. }
  627. *pDAcl = NULL;
  628. //
  629. // Build an appropriate discretionary ACL.
  630. //
  631. length = (ULONG) sizeof( ACL ) +
  632. (ULONG)( 1 * sizeof( ACCESS_ALLOWED_ACE )) +
  633. RtlLengthSid( SeExports->SeLocalSystemSid );
  634. dacl = (PACL) ALLOCATE_POOL( length, GENERAL_POOL_TAG );
  635. if (!dacl) {
  636. return STATUS_NO_MEMORY;
  637. }
  638. status = RtlCreateAcl( dacl, length, ACL_REVISION2 );
  639. if (NT_SUCCESS( status )) {
  640. status = RtlAddAccessAllowedAce(
  641. dacl,
  642. ACL_REVISION2,
  643. GENERIC_READ | GENERIC_WRITE,
  644. SeExports->SeLocalSystemSid
  645. );
  646. }
  647. if (NT_SUCCESS( status )) {
  648. //
  649. // Put it in a security descriptor so that it may be applied to
  650. // the system partition device.
  651. //
  652. status = RtlCreateSecurityDescriptor(
  653. &securityDescriptor,
  654. SECURITY_DESCRIPTOR_REVISION
  655. );
  656. }
  657. if (NT_SUCCESS( status )) {
  658. status = RtlSetDaclSecurityDescriptor(
  659. &securityDescriptor,
  660. TRUE,
  661. dacl,
  662. FALSE
  663. );
  664. }
  665. if (!NT_SUCCESS( status )) {
  666. FREE_POOL( &dacl );
  667. }
  668. //
  669. // Send back the dacl
  670. //
  671. *pDAcl = dacl;
  672. return status;
  673. }
  674. NTSTATUS
  675. CreateDeviceSecurityDescriptor(
  676. PSAC_DEVICE_CONTEXT DeviceContext
  677. )
  678. /*++
  679. Routine Description:
  680. This routine creates a security descriptor which controls access to
  681. the SAC device.
  682. Arguments:
  683. DeviceContext - A pointer to the device to work on.
  684. Return Value:
  685. STATUS_SUCCESS or an appropriate error code.
  686. Security:
  687. Currently, only the System user has access (READ/WRITE) to this device.
  688. --*/
  689. {
  690. PACL RawAcl = NULL;
  691. NTSTATUS Status;
  692. BOOLEAN MemoryAllocated = FALSE;
  693. PSECURITY_DESCRIPTOR SecurityDescriptor;
  694. ULONG SecurityDescriptorLength;
  695. CHAR Buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  696. PSECURITY_DESCRIPTOR LocalSecurityDescriptor = (PSECURITY_DESCRIPTOR) Buffer;
  697. PSECURITY_DESCRIPTOR DeviceSecurityDescriptor = NULL;
  698. SECURITY_INFORMATION SecurityInformation = DACL_SECURITY_INFORMATION;
  699. IF_SAC_DEBUG(
  700. SAC_DEBUG_FUNC_TRACE,
  701. KdPrint(("SAC CreateDeviceSecurityDescriptor: Entering.\n"))
  702. );
  703. //
  704. // Get a pointer to the security descriptor from the device object.
  705. //
  706. Status = ObGetObjectSecurity(
  707. DeviceContext->DeviceObject,
  708. &SecurityDescriptor,
  709. &MemoryAllocated
  710. );
  711. if (!NT_SUCCESS(Status)) {
  712. IF_SAC_DEBUG(
  713. SAC_DEBUG_FAILS,
  714. KdPrint(("SAC: Unable to get security descriptor, error: %x\n", Status))
  715. );
  716. ASSERT(MemoryAllocated == FALSE);
  717. IF_SAC_DEBUG(
  718. SAC_DEBUG_FUNC_TRACE,
  719. KdPrint(("SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status))
  720. );
  721. return(Status);
  722. }
  723. //
  724. // Build a local security descriptor
  725. //
  726. Status = BuildDeviceAcl(&RawAcl);
  727. if (!NT_SUCCESS(Status)) {
  728. IF_SAC_DEBUG(
  729. SAC_DEBUG_FAILS,
  730. KdPrint(("SAC CreateDeviceSecurityDescriptor: Unable to create Raw ACL, error: %x\n", Status))
  731. );
  732. goto ErrorExit;
  733. }
  734. (VOID)RtlCreateSecurityDescriptor(
  735. LocalSecurityDescriptor,
  736. SECURITY_DESCRIPTOR_REVISION
  737. );
  738. (VOID)RtlSetDaclSecurityDescriptor(
  739. LocalSecurityDescriptor,
  740. TRUE,
  741. RawAcl,
  742. FALSE
  743. );
  744. //
  745. // Make a copy of the security descriptor. This copy will be the raw descriptor.
  746. //
  747. SecurityDescriptorLength = RtlLengthSecurityDescriptor(SecurityDescriptor);
  748. DeviceSecurityDescriptor = ExAllocatePoolWithTag(
  749. PagedPool,
  750. SecurityDescriptorLength,
  751. SECURITY_POOL_TAG
  752. );
  753. if (DeviceSecurityDescriptor == NULL) {
  754. IF_SAC_DEBUG(
  755. SAC_DEBUG_FAILS,
  756. KdPrint(("SAC CreateDeviceSecurityDescriptor: couldn't allocate security descriptor\n"))
  757. );
  758. goto ErrorExit;
  759. }
  760. RtlMoveMemory(
  761. DeviceSecurityDescriptor,
  762. SecurityDescriptor,
  763. SecurityDescriptorLength
  764. );
  765. //
  766. // Now apply the local descriptor to the raw descriptor.
  767. //
  768. Status = SeSetSecurityDescriptorInfo(
  769. NULL,
  770. &SecurityInformation,
  771. LocalSecurityDescriptor,
  772. &DeviceSecurityDescriptor,
  773. NonPagedPool,
  774. IoGetFileObjectGenericMapping()
  775. );
  776. if (!NT_SUCCESS(Status)) {
  777. IF_SAC_DEBUG(
  778. SAC_DEBUG_FAILS,
  779. KdPrint(("SAC CreateDeviceSecurityDescriptor: SeSetSecurity failed, %lx\n", Status))
  780. );
  781. goto ErrorExit;
  782. }
  783. //
  784. // Update the driver DACL
  785. //
  786. Status = ObSetSecurityObjectByPointer(
  787. DeviceContext->DeviceObject,
  788. SecurityInformation,
  789. DeviceSecurityDescriptor
  790. );
  791. ErrorExit:
  792. ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);
  793. if (DeviceSecurityDescriptor) {
  794. ExFreePool(DeviceSecurityDescriptor);
  795. }
  796. SAFE_FREE_POOL(&RawAcl);
  797. IF_SAC_DEBUG(
  798. SAC_DEBUG_FUNC_TRACE,
  799. KdPrint(("SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status))
  800. );
  801. return(Status);
  802. }