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.

764 lines
21 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. CreateAdminSecurityDescriptor(
  14. IN PSAC_DEVICE_CONTEXT DeviceContext
  15. );
  16. NTSTATUS
  17. BuildDeviceAcl(
  18. OUT PACL *DeviceAcl
  19. );
  20. VOID
  21. WorkerThreadStartUp(
  22. IN PVOID StartContext
  23. );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text( INIT, InitializeGlobalData)
  26. #pragma alloc_text( INIT, CreateAdminSecurityDescriptor )
  27. #pragma alloc_text( INIT, BuildDeviceAcl )
  28. #endif
  29. //
  30. // Globally defined variables are here.
  31. //
  32. BOOLEAN GlobalDataInitialized = FALSE;
  33. UCHAR TmpBuffer[sizeof(PROCESS_PRIORITY_CLASS)];
  34. BOOLEAN IoctlSubmitted;
  35. LONG ProcessingType;
  36. HANDLE SACEventHandle;
  37. PKEVENT SACEvent=NULL;
  38. LONG Attempts;
  39. #if DBG
  40. ULONG SACDebug = 0x0;
  41. #endif
  42. BOOLEAN
  43. InitializeGlobalData(
  44. IN PUNICODE_STRING RegistryPath,
  45. IN PDRIVER_OBJECT DriverObject
  46. )
  47. /*++
  48. Routine Description:
  49. This routine initializes all the driver components that are shared across devices.
  50. Arguments:
  51. RegistryPath - A pointer to the location in the registry to read values from.
  52. DriverObject - pointer to DriverObject
  53. Return Value:
  54. TRUE if successful, else FALSE
  55. --*/
  56. {
  57. NTSTATUS Status;
  58. UNICODE_STRING DosName;
  59. UNICODE_STRING NtName;
  60. UNICODE_STRING UnicodeString;
  61. UNREFERENCED_PARAMETER(RegistryPath);
  62. PAGED_CODE();
  63. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  64. KdPrint(("SAC InitializeGlobalData: Entering.\n")));
  65. if (!GlobalDataInitialized) {
  66. //
  67. // Create a symbolic link from a DosDevice to this device so that a user-mode app can open us.
  68. //
  69. RtlInitUnicodeString(&DosName, SAC_DOSDEVICE_NAME);
  70. RtlInitUnicodeString(&NtName, SAC_DEVICE_NAME);
  71. Status = IoCreateSymbolicLink(&DosName, &NtName);
  72. if (!NT_SUCCESS(Status)) {
  73. return FALSE;
  74. }
  75. //
  76. // Initialize internal memory system
  77. //
  78. if (!InitializeMemoryManagement()) {
  79. IoDeleteSymbolicLink(&DosName);
  80. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  81. KdPrint(("SAC InitializeGlobalData: Exiting with status FALSE\n")));
  82. return FALSE;
  83. }
  84. Status = PreloadGlobalMessageTable(DriverObject->DriverStart);
  85. if (!NT_SUCCESS(Status)) {
  86. IoDeleteSymbolicLink(&DosName);
  87. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  88. KdPrint(( "SAC DriverEntry: unable to pre-load message table: %X\n", Status )));
  89. return FALSE;
  90. }
  91. Utf8ConversionBuffer = (PUCHAR)ALLOCATE_POOL(MEMORY_INCREMENT, GENERAL_POOL_TAG);
  92. if (!Utf8ConversionBuffer) {
  93. TearDownGlobalMessageTable();
  94. IoDeleteSymbolicLink(&DosName);
  95. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  96. KdPrint(( "SAC DriverEntry: unable to allocate memory for UTF8 translation." )));
  97. return FALSE;
  98. }
  99. GlobalDataInitialized = TRUE;
  100. ProcessingType = SAC_NO_OP;
  101. IoctlSubmitted = FALSE;
  102. Attempts = 0;
  103. //
  104. // Setup notification event
  105. //
  106. RtlInitUnicodeString(&UnicodeString, L"\\SACEvent");
  107. SACEvent = IoCreateSynchronizationEvent(&UnicodeString, &SACEventHandle);
  108. if (SACEvent == NULL) {
  109. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  110. KdPrint(("SAC InitializeGlobalData: Exiting with Event NULL\n")));
  111. return FALSE;
  112. }
  113. //
  114. // Retrieve all the machine-specific identification information.
  115. //
  116. InitializeMachineInformation();
  117. }
  118. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  119. KdPrint(("SAC InitializeGlobalData: Exiting with status TRUE\n")));
  120. return TRUE;
  121. } // InitializeGlobalData
  122. VOID
  123. FreeGlobalData(
  124. VOID
  125. )
  126. /*++
  127. Routine Description:
  128. This routine frees all shared components.
  129. Arguments:
  130. None.
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. UNICODE_STRING DosName;
  136. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeGlobalData: Entering.\n")));
  137. if (GlobalDataInitialized) {
  138. if(SACEvent != NULL){
  139. ZwClose(SACEventHandle);
  140. SACEvent = NULL;
  141. }
  142. TearDownGlobalMessageTable();
  143. RtlInitUnicodeString(&DosName, SAC_DOSDEVICE_NAME);
  144. IoDeleteSymbolicLink(&DosName);
  145. FreeMemoryManagement();
  146. GlobalDataInitialized = FALSE;
  147. }
  148. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeGlobalData: Exiting.\n")));
  149. } // FreeGlobalData
  150. BOOLEAN
  151. InitializeDeviceData(
  152. PDEVICE_OBJECT DeviceObject
  153. )
  154. /*++
  155. Routine Description:
  156. This routine initializes all the parts specific for each device.
  157. Arguments:
  158. DeviceObject - pointer to device object to be initialized.
  159. Return Value:
  160. TRUE if successful, else FALSE
  161. --*/
  162. {
  163. NTSTATUS Status;
  164. LARGE_INTEGER Time;
  165. LONG Priority;
  166. HEADLESS_CMD_ENABLE_TERMINAL Command;
  167. PSAC_DEVICE_CONTEXT DeviceContext;
  168. PAGED_CODE();
  169. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  170. KdPrint(("SAC InitializeDeviceData: Entering.\n")));
  171. DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  172. if (!DeviceContext->InitializedAndReady) {
  173. DeviceObject->StackSize = DEFAULT_IRP_STACK_SIZE;
  174. DeviceObject->Flags |= DO_DIRECT_IO;
  175. DeviceContext->DeviceObject = DeviceObject;
  176. DeviceContext->PriorityBoost = DEFAULT_PRIORITY_BOOST;
  177. DeviceContext->AdminSecurityDescriptor = NULL;
  178. DeviceContext->UnloadDeferred = FALSE;
  179. DeviceContext->Processing = FALSE;
  180. KeInitializeTimer(&(DeviceContext->Timer));
  181. KeInitializeDpc(&(DeviceContext->Dpc), &TimerDpcRoutine, DeviceContext);
  182. KeInitializeSpinLock(&(DeviceContext->SpinLock));
  183. KeInitializeEvent(&(DeviceContext->ProcessEvent), SynchronizationEvent, FALSE);
  184. //
  185. // Enable the terminal
  186. //
  187. Command.Enable = TRUE;
  188. Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
  189. &Command,
  190. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  191. NULL,
  192. NULL
  193. );
  194. if (!NT_SUCCESS(Status)) {
  195. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  196. KdPrint(("SAC InitializeDeviceData: Exiting (1) with status FALSE\n")));
  197. return FALSE;
  198. }
  199. //
  200. // Remember a pointer to the system process. We'll use this pointer
  201. // for KeAttachProcess() calls so that we can open handles in the
  202. // context of the system process.
  203. //
  204. DeviceContext->SystemProcess = (PKPROCESS)IoGetCurrentProcess();
  205. //
  206. // Create the security descriptor used for raw access checks.
  207. //
  208. Status = CreateAdminSecurityDescriptor(DeviceContext);
  209. if (!NT_SUCCESS(Status)) {
  210. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  211. KdPrint(("SAC InitializeDeviceData: Exiting (2) with status FALSE\n")));
  212. Command.Enable = FALSE;
  213. HeadlessDispatch(HeadlessCmdEnableTerminal,
  214. &Command,
  215. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  216. NULL,
  217. NULL
  218. );
  219. return FALSE;
  220. }
  221. //
  222. // Start a thread to handle requests
  223. //
  224. Status = PsCreateSystemThread(&(DeviceContext->ThreadHandle),
  225. PROCESS_ALL_ACCESS,
  226. NULL,
  227. NULL,
  228. NULL,
  229. WorkerThreadStartUp,
  230. DeviceContext
  231. );
  232. if (!NT_SUCCESS(Status)) {
  233. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  234. KdPrint(("SAC InitializeDeviceData: Exiting (3) with status FALSE\n")));
  235. Command.Enable = FALSE;
  236. HeadlessDispatch(HeadlessCmdEnableTerminal,
  237. &Command,
  238. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  239. NULL,
  240. NULL
  241. );
  242. return FALSE;
  243. }
  244. //
  245. // Set this thread to the real-time highest priority so that it will be
  246. // responsive.
  247. //
  248. Priority = HIGH_PRIORITY;
  249. Status = NtSetInformationThread(DeviceContext->ThreadHandle,
  250. ThreadPriority,
  251. &Priority,
  252. sizeof(Priority)
  253. );
  254. if (!NT_SUCCESS(Status)) {
  255. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  256. KdPrint(("SAC InitializeDeviceData: Exiting (6) with status FALSE\n")));
  257. //
  258. // Tell thread to exit.
  259. //
  260. DeviceContext->UnloadDeferred = TRUE;
  261. KeInitializeEvent(&(DeviceContext->UnloadEvent), SynchronizationEvent, FALSE);
  262. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  263. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->UnloadEvent), Executive, KernelMode, FALSE, NULL);
  264. ASSERT(Status == STATUS_SUCCESS);
  265. Command.Enable = FALSE;
  266. HeadlessDispatch(HeadlessCmdEnableTerminal,
  267. &Command,
  268. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  269. NULL,
  270. NULL
  271. );
  272. return FALSE;
  273. }
  274. //
  275. // Start our timer
  276. //
  277. Time.QuadPart = Int32x32To64((LONG)100, -1000); // 100ms from now.
  278. KeSetTimerEx(&(DeviceContext->Timer), Time, (LONG)100, &(DeviceContext->Dpc)); // every 100ms
  279. //
  280. // Display the prompt
  281. //
  282. SacPutSimpleMessage( SAC_ENTER );
  283. SacPutSimpleMessage( SAC_INITIALIZED );
  284. SacPutSimpleMessage( SAC_ENTER );
  285. SacPutSimpleMessage( SAC_PROMPT );
  286. DeviceContext->InitializedAndReady = TRUE;
  287. }
  288. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  289. KdPrint(("SAC InitializeDeviceData: Exiting with status TRUE\n")));
  290. return TRUE;
  291. } // InitializeDeviceData
  292. VOID
  293. FreeDeviceData(
  294. PDEVICE_OBJECT DeviceObject
  295. )
  296. /*++
  297. Routine Description:
  298. This routine frees all components specific to a device..
  299. Arguments:
  300. DeviceContext - The device to work on.
  301. Return Value:
  302. It will stop and wait, if necessary, for any processing to complete.
  303. --*/
  304. {
  305. KIRQL OldIrql;
  306. NTSTATUS Status;
  307. PVOID MemToFree;
  308. PSAC_DEVICE_CONTEXT DeviceContext;
  309. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Entering.\n")));
  310. DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  311. if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) {
  312. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Exiting.\n")));
  313. return;
  314. }
  315. //
  316. // Wait for all processing to complete
  317. //
  318. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  319. DeviceContext->UnloadDeferred = TRUE;
  320. while (DeviceContext->Processing) {
  321. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Waiting....\n")));
  322. KeInitializeEvent(&(DeviceContext->UnloadEvent), SynchronizationEvent, FALSE);
  323. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  324. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->UnloadEvent), Executive, KernelMode, FALSE, NULL);
  325. ASSERT(Status == STATUS_SUCCESS);
  326. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  327. }
  328. DeviceContext->Processing = TRUE;
  329. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  330. KeCancelTimer(&(DeviceContext->Timer));
  331. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  332. DeviceContext->Processing = FALSE;
  333. MemToFree = (PVOID)DeviceContext->AdminSecurityDescriptor;
  334. DeviceContext->AdminSecurityDescriptor = NULL;
  335. //
  336. // Signal the thread to exit
  337. //
  338. KeInitializeEvent(&(DeviceContext->UnloadEvent), SynchronizationEvent, FALSE);
  339. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  340. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  341. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->UnloadEvent), Executive, KernelMode, FALSE, NULL);
  342. ASSERT(Status == STATUS_SUCCESS);
  343. //
  344. // Finish up cleaning up.
  345. //
  346. IoUnregisterShutdownNotification(DeviceObject);
  347. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  348. DeviceContext->InitializedAndReady = FALSE;
  349. DeviceContext->UnloadDeferred = FALSE;
  350. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  351. if (MemToFree != NULL) {
  352. ExFreePool(MemToFree);
  353. }
  354. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC FreeDeviceData: Exiting.\n")));
  355. } // FreeDeviceData
  356. NTSTATUS
  357. BuildDeviceAcl(
  358. OUT PACL *DeviceAcl
  359. )
  360. /*++
  361. Routine Description:
  362. This routine builds an ACL which gives Administrators and LocalSystem
  363. principals full access. All other principals have no access.
  364. Arguments:
  365. DeviceAcl - Output pointer to the new ACL.
  366. Return Value:
  367. STATUS_SUCCESS or an appropriate error code.
  368. --*/
  369. {
  370. PGENERIC_MAPPING GenericMapping;
  371. PSID AdminsSid;
  372. PSID SystemSid;
  373. ULONG AclLength;
  374. NTSTATUS Status;
  375. ACCESS_MASK AccessMask = GENERIC_ALL;
  376. PACL NewAcl;
  377. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC BuildDeviceAcl: Entering.\n")));
  378. //
  379. // Enable access to all the globally defined SIDs
  380. //
  381. GenericMapping = IoGetFileObjectGenericMapping();
  382. RtlMapGenericMask(&AccessMask, GenericMapping);
  383. //SeEnableAccessToExports();
  384. AdminsSid = SeExports->SeAliasAdminsSid;
  385. SystemSid = SeExports->SeLocalSystemSid;
  386. AclLength = sizeof(ACL) + (2 * sizeof(ACCESS_ALLOWED_ACE)) +
  387. RtlLengthSid(AdminsSid) + RtlLengthSid(SystemSid) -
  388. (2 * sizeof(ULONG));
  389. NewAcl = ALLOCATE_POOL(AclLength, SECURITY_POOL_TAG);
  390. if (NewAcl == NULL) {
  391. return(STATUS_INSUFFICIENT_RESOURCES);
  392. }
  393. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
  394. if (!NT_SUCCESS(Status)) {
  395. FREE_POOL(&NewAcl);
  396. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  397. KdPrint(("SAC BuildDeviceAcl: Exiting with status 0x%x\n", Status)));
  398. return(Status);
  399. }
  400. Status = RtlAddAccessAllowedAce(NewAcl,
  401. ACL_REVISION2,
  402. AccessMask,
  403. AdminsSid
  404. );
  405. ASSERT(NT_SUCCESS(Status));
  406. Status = RtlAddAccessAllowedAce(NewAcl,
  407. ACL_REVISION2,
  408. AccessMask,
  409. SystemSid
  410. );
  411. ASSERT(NT_SUCCESS(Status));
  412. *DeviceAcl = NewAcl;
  413. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  414. KdPrint(("SAC BuildDeviceAcl: Exiting with status 0x%x\n", STATUS_SUCCESS)));
  415. return(STATUS_SUCCESS);
  416. } // BuildDeviceAcl
  417. NTSTATUS
  418. CreateAdminSecurityDescriptor(
  419. PSAC_DEVICE_CONTEXT DeviceContext
  420. )
  421. /*++
  422. Routine Description:
  423. This routine creates a security descriptor which gives access
  424. only to Administrtors and LocalSystem. This descriptor is used
  425. to access check raw endpoint opens and exclisive access to transport
  426. addresses.
  427. Arguments:
  428. DeviceContext - A pointer to the device to work on.
  429. Return Value:
  430. STATUS_SUCCESS or an appropriate error code.
  431. --*/
  432. {
  433. PACL RawAcl = NULL;
  434. NTSTATUS Status;
  435. BOOLEAN MemoryAllocated = FALSE;
  436. PSECURITY_DESCRIPTOR SecurityDescriptor;
  437. ULONG SecurityDescriptorLength;
  438. CHAR Buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  439. PSECURITY_DESCRIPTOR LocalSecurityDescriptor = (PSECURITY_DESCRIPTOR) &Buffer;
  440. PSECURITY_DESCRIPTOR LocalAdminSecurityDescriptor;
  441. SECURITY_INFORMATION SecurityInformation = DACL_SECURITY_INFORMATION;
  442. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  443. KdPrint(("SAC CreateAdminSecDesc: Entering.\n")));
  444. //
  445. // Get a pointer to the security descriptor from the device object.
  446. //
  447. Status = ObGetObjectSecurity(DeviceContext->DeviceObject,
  448. &SecurityDescriptor,
  449. &MemoryAllocated
  450. );
  451. if (!NT_SUCCESS(Status)) {
  452. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  453. KdPrint(("SAC: Unable to get security descriptor, error: %x\n", Status)));
  454. ASSERT(MemoryAllocated == FALSE);
  455. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  456. KdPrint(("SAC CreateAdminSecDesc: Exiting with status 0x%x\n", Status)));
  457. return(Status);
  458. }
  459. //
  460. // Build a local security descriptor with an ACL giving only
  461. // administrators and system access.
  462. //
  463. Status = BuildDeviceAcl(&RawAcl);
  464. if (!NT_SUCCESS(Status)) {
  465. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  466. KdPrint(("SAC CreateAdminSecDesc: Unable to create Raw ACL, error: %x\n", Status)));
  467. goto ErrorExit;
  468. }
  469. (VOID)RtlCreateSecurityDescriptor(LocalSecurityDescriptor,
  470. SECURITY_DESCRIPTOR_REVISION
  471. );
  472. (VOID)RtlSetDaclSecurityDescriptor(LocalSecurityDescriptor,
  473. TRUE,
  474. RawAcl,
  475. FALSE
  476. );
  477. //
  478. // Make a copy of the security descriptor. This copy will be the raw descriptor.
  479. //
  480. SecurityDescriptorLength = RtlLengthSecurityDescriptor(SecurityDescriptor);
  481. LocalAdminSecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
  482. SecurityDescriptorLength,
  483. SECURITY_POOL_TAG
  484. );
  485. if (LocalAdminSecurityDescriptor == NULL) {
  486. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  487. KdPrint(("SAC CreateAdminSecDesc: couldn't allocate security descriptor\n")));
  488. goto ErrorExit;
  489. }
  490. RtlMoveMemory(LocalAdminSecurityDescriptor,
  491. SecurityDescriptor,
  492. SecurityDescriptorLength
  493. );
  494. DeviceContext->AdminSecurityDescriptor = LocalAdminSecurityDescriptor;
  495. //
  496. // Now apply the local descriptor to the raw descriptor.
  497. //
  498. Status = SeSetSecurityDescriptorInfo(NULL,
  499. &SecurityInformation,
  500. LocalSecurityDescriptor,
  501. &(DeviceContext->AdminSecurityDescriptor),
  502. NonPagedPool,
  503. IoGetFileObjectGenericMapping()
  504. );
  505. if (!NT_SUCCESS(Status)) {
  506. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  507. KdPrint(("SAC CreateAdminSecDesc: SeSetSecurity failed, %lx\n", Status)));
  508. ASSERT(DeviceContext->AdminSecurityDescriptor == LocalAdminSecurityDescriptor);
  509. ExFreePool(DeviceContext->AdminSecurityDescriptor);
  510. DeviceContext->AdminSecurityDescriptor = NULL;
  511. goto ErrorExit;
  512. }
  513. if (DeviceContext->AdminSecurityDescriptor != LocalAdminSecurityDescriptor) {
  514. ExFreePool(LocalAdminSecurityDescriptor);
  515. }
  516. Status = STATUS_SUCCESS;
  517. ErrorExit:
  518. ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);
  519. if (RawAcl != NULL) {
  520. FREE_POOL(&RawAcl);
  521. }
  522. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  523. KdPrint(("SAC CreateAdminSecDesc: Exiting with status 0x%x\n", Status)));
  524. return(Status);
  525. }
  526. VOID
  527. WorkerThreadStartUp(
  528. IN PVOID StartContext
  529. )
  530. /*++
  531. Routine Description:
  532. This routine is the start up routine for the worker thread. It justn
  533. sends the worker thread to the processing routine.
  534. Arguments:
  535. StartContext - A pointer to the device to work on.
  536. Return Value:
  537. None.
  538. --*/
  539. {
  540. WorkerProcessEvents((PSAC_DEVICE_CONTEXT)StartContext);
  541. }