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.

1102 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1996.
  5. //
  6. // File: kernel.cxx
  7. //
  8. // Contents: Kernel support functions
  9. //
  10. // History: 8/94 davemont Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. #include <seopaque.h>
  16. #include <sertlp.h>
  17. #pragma warning(disable: 4200)
  18. #include <wmistr.h>
  19. #include <wmiumkm.h>
  20. #define BASED_NAMED_OBJECTS_DIR L"\\BaseNamedObjects"
  21. //
  22. // Function prototypes
  23. //
  24. ULONG WmipOpenKernelGuid(
  25. CONST GUID *Guid,
  26. ACCESS_MASK DesiredAccess,
  27. PHANDLE Handle
  28. );
  29. HANDLE WmiGuidHandle = NULL;
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Function: OpenKernelObject
  33. //
  34. // Synopsis: Gets a handle to the specified kernel object
  35. //
  36. // Arguments: [IN pwszObject] -- Object to open
  37. // [IN AccessMask] -- Type of open to do
  38. // [OUT pHandle] -- Where the handle to the object
  39. // is returned
  40. // [OUT KernelType] -- Type of the kernel object
  41. //
  42. // Returns: ERROR_SUCCESS -- Success
  43. //
  44. //----------------------------------------------------------------------------
  45. DWORD
  46. OpenKernelObject(IN LPWSTR pwszObject,
  47. IN ACCESS_MASK AccessMask,
  48. OUT PHANDLE pHandle,
  49. OUT PMARTA_KERNEL_TYPE KernelType)
  50. {
  51. #define BUFFERSIZE 1024
  52. HANDLE hRootDir;
  53. NTSTATUS Status;
  54. UNICODE_STRING UnicodeString;
  55. OBJECT_ATTRIBUTES Attributes;
  56. UCHAR Buffer[BUFFERSIZE];
  57. BOOL fFound = FALSE;
  58. ULONG Context = 0;
  59. DWORD dwErr = ERROR_SUCCESS;
  60. POBJECT_DIRECTORY_INFORMATION DirInfo = NULL;
  61. //
  62. // Get a handle to the base named and iterate through that directory
  63. // to find the object name.
  64. //
  65. RtlInitUnicodeString(&UnicodeString,
  66. BASED_NAMED_OBJECTS_DIR);
  67. InitializeObjectAttributes(&Attributes,
  68. &UnicodeString,
  69. OBJ_CASE_INSENSITIVE,
  70. NULL,
  71. NULL);
  72. Status = NtOpenDirectoryObject(&hRootDir,
  73. DIRECTORY_QUERY,
  74. &Attributes);
  75. if (!NT_SUCCESS(Status))
  76. {
  77. return(RtlNtStatusToDosError(Status));
  78. }
  79. //
  80. // Get the entries in batches that will fit in a buffer of size
  81. // BUFFERSIZE until we find the entry that we want
  82. //
  83. while (NT_SUCCESS(Status) && !fFound )
  84. {
  85. RtlZeroMemory(Buffer,
  86. BUFFERSIZE);
  87. Status = NtQueryDirectoryObject(hRootDir,
  88. (PVOID)&Buffer,
  89. BUFFERSIZE,
  90. FALSE,
  91. FALSE,
  92. &Context,
  93. NULL);
  94. if(NT_SUCCESS(Status))
  95. {
  96. //
  97. // Keep looking until we've examined all the entries in this
  98. // batch or we find what we're looking for.
  99. //
  100. DirInfo = (POBJECT_DIRECTORY_INFORMATION)&Buffer[0];
  101. while(!fFound && DirInfo->Name.Length != 0)
  102. {
  103. ULONG cChar;
  104. cChar = DirInfo->Name.Length/sizeof(WCHAR);
  105. if((cChar == wcslen(pwszObject)) &&
  106. (!wcsncmp(pwszObject,
  107. DirInfo->Name.Buffer,
  108. cChar )) )
  109. {
  110. fFound = TRUE;
  111. }
  112. else
  113. {
  114. DirInfo++;
  115. }
  116. }
  117. }
  118. }
  119. if (!fFound)
  120. {
  121. if(Status != STATUS_NO_MORE_ENTRIES)
  122. {
  123. dwErr = RtlNtStatusToDosError(Status);
  124. }
  125. else
  126. {
  127. dwErr = ERROR_RESOURCE_NAME_NOT_FOUND;
  128. }
  129. }
  130. else
  131. {
  132. ASSERT( DirInfo != NULL );
  133. ASSERT( DirInfo->Name.Length != 0 );
  134. ASSERT( DirInfo->TypeName.Length != 0 );
  135. RtlInitUnicodeString(&UnicodeString,
  136. pwszObject);
  137. InitializeObjectAttributes(&Attributes,
  138. &UnicodeString,
  139. OBJ_CASE_INSENSITIVE,
  140. hRootDir,
  141. NULL);
  142. //
  143. // Open the object to get its handle based on its type
  144. //
  145. if (wcsncmp(L"Event",
  146. DirInfo->TypeName.Buffer,
  147. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  148. {
  149. Status = NtOpenEvent(pHandle,
  150. AccessMask,
  151. &Attributes);
  152. *KernelType = MARTA_EVENT;
  153. }
  154. else if (wcsncmp( L"EventPair",
  155. DirInfo->TypeName.Buffer,
  156. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  157. {
  158. Status = NtOpenEventPair(pHandle,
  159. AccessMask,
  160. &Attributes);
  161. *KernelType = MARTA_EVENT_PAIR;
  162. }
  163. else if (wcsncmp(L"Mutant",
  164. DirInfo->TypeName.Buffer,
  165. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  166. {
  167. Status = NtOpenMutant(pHandle,
  168. AccessMask,
  169. &Attributes);
  170. *KernelType = MARTA_MUTANT;
  171. }
  172. else if (wcsncmp(L"Process",
  173. DirInfo->TypeName.Buffer,
  174. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  175. {
  176. Status = NtOpenProcess(pHandle,
  177. AccessMask,
  178. &Attributes,
  179. NULL);
  180. *KernelType = MARTA_PROCESS;
  181. }
  182. else if (wcsncmp( L"Section",
  183. DirInfo->TypeName.Buffer,
  184. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  185. {
  186. Status = NtOpenSection(pHandle,
  187. AccessMask,
  188. &Attributes);
  189. *KernelType = MARTA_SECTION;
  190. }
  191. else if (wcsncmp(L"Semaphore",
  192. DirInfo->TypeName.Buffer,
  193. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  194. {
  195. Status = NtOpenSemaphore(pHandle,
  196. AccessMask,
  197. &Attributes);
  198. *KernelType = MARTA_SEMAPHORE;
  199. }
  200. else if (wcsncmp(L"SymbolicLink",
  201. DirInfo->TypeName.Buffer,
  202. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  203. {
  204. Status = NtOpenSymbolicLinkObject(pHandle,
  205. AccessMask,
  206. &Attributes);
  207. *KernelType = MARTA_SYMBOLIC_LINK;
  208. }
  209. else if (wcsncmp(L"Thread",
  210. DirInfo->TypeName.Buffer,
  211. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  212. {
  213. Status = NtOpenThread(pHandle,
  214. AccessMask,
  215. &Attributes,
  216. NULL);
  217. *KernelType = MARTA_THREAD;
  218. }
  219. else if (wcsncmp(L"Timer",
  220. DirInfo->TypeName.Buffer,
  221. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  222. {
  223. Status = NtOpenTimer(pHandle,
  224. AccessMask,
  225. &Attributes);
  226. *KernelType = MARTA_TIMER;
  227. }
  228. else if (wcsncmp(L"Job",
  229. DirInfo->TypeName.Buffer,
  230. DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
  231. {
  232. Status = NtOpenJobObject(pHandle,
  233. AccessMask,
  234. &Attributes);
  235. *KernelType = MARTA_JOB;
  236. }
  237. else
  238. {
  239. Status = STATUS_OBJECT_NAME_INVALID;
  240. }
  241. if(!NT_SUCCESS(Status))
  242. {
  243. dwErr = RtlNtStatusToDosError(Status);
  244. }
  245. }
  246. NtClose(hRootDir);
  247. return (dwErr);
  248. }
  249. //+---------------------------------------------------------------------------
  250. //
  251. // Function: ReadKernelPropertyRights
  252. //
  253. // Synopsis: Gets the specified rights from the kernel object
  254. //
  255. // Arguments: [IN pwszObject] -- The object to get the rights
  256. // for
  257. // [IN pRightsList] -- SecurityInfo to read based
  258. // on properties
  259. // [IN cRights] -- Number of items in rights list
  260. // [IN AccessList] -- Access List to fill in
  261. //
  262. // Returns: ERROR_SUCCESS -- Success
  263. // ERROR_INVALID_PARAMETER -- A bad property was encountered
  264. //
  265. // Note: Kernel objects are assumed to be created through the
  266. // Win32 APIs so they all reside in the \basenamedobjects
  267. // directory.
  268. //
  269. //----------------------------------------------------------------------------
  270. DWORD
  271. ReadKernelPropertyRights(IN LPWSTR pwszObject,
  272. IN PACTRL_RIGHTS_INFO pRightsList,
  273. IN ULONG cRights,
  274. IN CAccessList& AccessList)
  275. {
  276. acDebugOut((DEB_TRACE, "in ReadKernelPropertyRights\n"));
  277. DWORD dwErr = ERROR_SUCCESS;
  278. HANDLE hObject = NULL;
  279. MARTA_KERNEL_TYPE KernelType;
  280. //
  281. // Kernel objects don't have parents from whom they can inherit
  282. //
  283. ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
  284. if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
  285. {
  286. return(ERROR_INVALID_PARAMETER);
  287. }
  288. dwErr = OpenKernelObject(pwszObject,
  289. GetDesiredAccess(READ_ACCESS_RIGHTS,
  290. pRightsList[0].SeInfo),
  291. &hObject,
  292. &KernelType);
  293. if(dwErr == ERROR_SUCCESS)
  294. {
  295. dwErr = GetKernelSecurityInfo(hObject,
  296. pRightsList,
  297. cRights,
  298. AccessList);
  299. NtClose(hObject);
  300. }
  301. acDebugOut((DEB_TRACE, "Out ReadKernelPropertyRights: %lu\n", dwErr));
  302. return (dwErr);
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Function: GetKernelSecurityInfo
  307. //
  308. // Arguments: [IN hObject] -- The handle to the object to
  309. // get the rights for
  310. // [IN pRightsList] -- SecurityInfo to read based
  311. // on properties
  312. // [IN cRights] -- Number of items in rights list
  313. // [IN AccessList] -- Access List to fill in
  314. //
  315. // Returns: ERROR_SUCCESS -- Success
  316. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  317. //
  318. //----------------------------------------------------------------------------
  319. DWORD
  320. GetKernelSecurityInfo(IN HANDLE hObject,
  321. IN PACTRL_RIGHTS_INFO pRightsList,
  322. IN ULONG cRights,
  323. IN CAccessList& AccessList)
  324. {
  325. acDebugOut((DEB_TRACE, "in GetKernelSecurityInfo\n"));
  326. UCHAR pSDBuff[PSD_BASE_LENGTH];
  327. PISECURITY_DESCRIPTOR pSD;
  328. DWORD dwErr = ERROR_SUCCESS;
  329. NTSTATUS Status;
  330. ULONG cNeeded = 0;
  331. for(ULONG iIndex = 0; iIndex < cRights && dwErr == ERROR_SUCCESS; iIndex++)
  332. {
  333. pSD = (PISECURITY_DESCRIPTOR)pSDBuff;
  334. Status = NtQuerySecurityObject(hObject,
  335. pRightsList[iIndex].SeInfo,
  336. pSD,
  337. PSD_BASE_LENGTH,
  338. &cNeeded);
  339. if(!NT_SUCCESS(Status))
  340. {
  341. if(Status == STATUS_BUFFER_TOO_SMALL)
  342. {
  343. //
  344. // Fine.. Allocate a big enough buffer
  345. //
  346. pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
  347. if(pSD == NULL)
  348. {
  349. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  350. break;
  351. }
  352. Status = NtQuerySecurityObject(hObject,
  353. pRightsList[iIndex].SeInfo,
  354. pSD,
  355. cNeeded,
  356. &cNeeded);
  357. }
  358. }
  359. //
  360. // Now, we've either got a failure or a valid SD...
  361. //
  362. if(NT_SUCCESS(Status))
  363. {
  364. dwErr = AccessList.AddSD(pSD,
  365. pRightsList[iIndex].SeInfo,
  366. pRightsList[iIndex].pwszProperty);
  367. }
  368. else
  369. {
  370. dwErr = RtlNtStatusToDosError(Status);
  371. }
  372. if(pSD != (PISECURITY_DESCRIPTOR)pSDBuff)
  373. {
  374. AccFree(pSD);
  375. }
  376. }
  377. acDebugOut((DEB_TRACE, "Out GetKernelSecurityInfo: %lu\n", dwErr));
  378. return(dwErr);
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // Function: GetKernelParentRights
  383. //
  384. // Synopsis: Determines who the parent is, and gets the access rights
  385. // for it. It is used to aid in determining what the approriate
  386. // inheritance bits are.
  387. //
  388. // This operation does not make sense for kernel objects
  389. //
  390. // Arguments: [IN pwszObject] -- The object to get the parent
  391. // for
  392. // [IN pRightsList] -- The properties to get the
  393. // rights for
  394. // [IN cRights] -- Number of items in rights list
  395. // [OUT ppDAcl] -- Where the DACL is returned
  396. // [OUT ppSAcl] -- Where the SACL is returned
  397. // [OUT ppSD] -- Where the Security Descriptor
  398. // is returned
  399. //
  400. // Returns: ERROR_INVALID_FUNCTION -- Call doesn't make sense here
  401. //
  402. //----------------------------------------------------------------------------
  403. DWORD
  404. GetKernelParentRights(IN LPWSTR pwszObject,
  405. IN PACTRL_RIGHTS_INFO pRightsList,
  406. IN ULONG cRights,
  407. OUT PACL *ppDAcl,
  408. OUT PACL *ppSAcl,
  409. OUT PSECURITY_DESCRIPTOR *ppSD)
  410. {
  411. //
  412. // This doesn't currently make sense for kernel objects, so simply
  413. // return an error
  414. //
  415. return(ERROR_INVALID_FUNCTION);
  416. }
  417. //+---------------------------------------------------------------------------
  418. //
  419. // Function: SetKernelSecurityInfo
  420. //
  421. // Synopsis: Sets the specified security info for the handle's
  422. // kernel object
  423. //
  424. // Arguments: [IN hKernel] -- The handle of the object
  425. // [IN SeInfo] -- Flag indicating what security
  426. // info to set
  427. // [IN pwszProperty] -- The property on the object to
  428. // set
  429. // For kernel objects, this MBZ
  430. // [IN pSD] -- The security descriptor to set
  431. //
  432. // Returns: ERROR_SUCCESS -- Success
  433. // ERROR_INVALID_PARAMETER -- A bad property was given
  434. //
  435. //----------------------------------------------------------------------------
  436. DWORD
  437. SetKernelSecurityInfo(IN HANDLE hKernel,
  438. IN SECURITY_INFORMATION SeInfo,
  439. IN PWSTR pwszProperty,
  440. IN PSECURITY_DESCRIPTOR pSecurityDescriptor)
  441. {
  442. acDebugOut((DEB_TRACE, "in SetNamedKernelSecurityInfo\n"));
  443. DWORD dwErr = ERROR_SUCCESS;
  444. if(pwszProperty != NULL)
  445. {
  446. dwErr = ERROR_INVALID_PARAMETER;
  447. }
  448. else
  449. {
  450. NTSTATUS Status = NtSetSecurityObject(hKernel,
  451. SeInfo,
  452. pSecurityDescriptor);
  453. dwErr = RtlNtStatusToDosError(Status);
  454. }
  455. acDebugOut((DEB_TRACE, "Out SetKernelSecurityInfo %lu\n", dwErr));
  456. return (dwErr);
  457. }
  458. //+---------------------------------------------------------------------------
  459. //
  460. // Function: GetKernelSecurityInfo
  461. //
  462. // Arguments: [IN hObject] -- The handle to the object to
  463. // get the rights for
  464. // [IN SeInfo] -- SecurityInfo to read based
  465. // on properties
  466. // [IN cRights] -- Number of items in rights list
  467. // [IN AccessList] -- Access List to fill in
  468. //
  469. // Returns: ERROR_SUCCESS -- Success
  470. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  471. //
  472. //----------------------------------------------------------------------------
  473. DWORD
  474. GetKernelSecurityInfo(IN HANDLE hObject,
  475. IN SECURITY_INFORMATION SeInfo,
  476. OUT PACL *ppDAcl,
  477. OUT PACL *ppSAcl,
  478. OUT PSECURITY_DESCRIPTOR *ppSD)
  479. {
  480. acDebugOut((DEB_TRACE, "in GetKernelSecurityInfo\n"));
  481. PISECURITY_DESCRIPTOR pSD = NULL;
  482. DWORD dwErr = ERROR_SUCCESS;
  483. NTSTATUS Status;
  484. ULONG cNeeded = 0;
  485. Status = NtQuerySecurityObject(hObject,
  486. SeInfo,
  487. pSD,
  488. 0,
  489. &cNeeded);
  490. if(!NT_SUCCESS(Status))
  491. {
  492. if(Status == STATUS_BUFFER_TOO_SMALL)
  493. {
  494. //
  495. // Fine.. Allocate a big enough buffer
  496. //
  497. pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
  498. if(pSD == NULL)
  499. {
  500. Status = STATUS_NO_MEMORY;
  501. }
  502. else
  503. {
  504. Status = NtQuerySecurityObject(hObject,
  505. SeInfo,
  506. pSD,
  507. cNeeded,
  508. &cNeeded);
  509. }
  510. }
  511. }
  512. //
  513. // Now, we've either got a failure or a valid SD...
  514. //
  515. if(NT_SUCCESS(Status))
  516. {
  517. if (pSD != NULL)
  518. {
  519. if(ppDAcl != NULL)
  520. {
  521. *ppDAcl = RtlpDaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
  522. }
  523. if(ppSAcl != NULL)
  524. {
  525. *ppSAcl = RtlpSaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
  526. }
  527. *ppSD = pSD;
  528. }
  529. else
  530. {
  531. dwErr = ERROR_ACCESS_DENIED;
  532. }
  533. }
  534. else
  535. {
  536. dwErr = RtlNtStatusToDosError(Status);
  537. }
  538. acDebugOut((DEB_TRACE, "Out GetKernelSecurityInfo: %lu\n", dwErr));
  539. return(dwErr);
  540. }
  541. //
  542. // Routines provided by AlanWar for accessind WmiGuid objects
  543. //
  544. _inline HANDLE WmipAllocEvent(
  545. VOID
  546. )
  547. {
  548. HANDLE EventHandle;
  549. EventHandle = (HANDLE)InterlockedExchangePointer(( PVOID *)&WmiGuidHandle, NULL );
  550. if ( EventHandle == NULL ) {
  551. EventHandle = CreateEvent( NULL, FALSE, FALSE, NULL );
  552. }
  553. return( EventHandle );
  554. }
  555. _inline void WmipFreeEvent(
  556. HANDLE EventHandle
  557. )
  558. {
  559. if ( InterlockedCompareExchangePointer( &WmiGuidHandle,
  560. EventHandle,
  561. NULL) != NULL ) {
  562. CloseHandle( EventHandle );
  563. }
  564. }
  565. ULONG WmipSendWmiKMRequest(
  566. ULONG Ioctl,
  567. PVOID Buffer,
  568. ULONG InBufferSize,
  569. ULONG MaxBufferSize,
  570. ULONG *ReturnSize
  571. )
  572. /*+++
  573. Routine Description:
  574. This routine does the work of sending WMI requests to the WMI kernel
  575. mode device. Any retry errors returned by the WMI device are handled
  576. in this routine.
  577. Arguments:
  578. Ioctl is the IOCTL code to send to the WMI device
  579. Buffer is the input and output buffer for the call to the WMI device
  580. InBufferSize is the size of the buffer passed to the device
  581. MaxBufferSize is the maximum number of bytes that can be written
  582. into the buffer
  583. *ReturnSize on return has the actual number of bytes written in buffer
  584. Return Value:
  585. ERROR_SUCCESS or an error code
  586. ---*/
  587. {
  588. OVERLAPPED Overlapped;
  589. ULONG Status;
  590. BOOL IoctlSuccess;
  591. HANDLE WmipKMHandle = NULL;
  592. //
  593. // If device is not open for then open it now. The
  594. // handle is closed in the process detach dll callout (DlllMain)
  595. WmipKMHandle = CreateFile(WMIDataDeviceName,
  596. GENERIC_READ | GENERIC_WRITE,
  597. 0,
  598. NULL,
  599. OPEN_EXISTING,
  600. FILE_ATTRIBUTE_NORMAL |
  601. FILE_FLAG_OVERLAPPED,
  602. NULL);
  603. if (WmipKMHandle == (HANDLE)-1)
  604. {
  605. WmipKMHandle = NULL;
  606. return(GetLastError());
  607. }
  608. Overlapped.hEvent = WmipAllocEvent();
  609. if (Overlapped.hEvent == NULL)
  610. {
  611. return(ERROR_NOT_ENOUGH_MEMORY);
  612. }
  613. do
  614. {
  615. IoctlSuccess = DeviceIoControl(WmipKMHandle,
  616. Ioctl,
  617. Buffer,
  618. InBufferSize,
  619. Buffer,
  620. MaxBufferSize,
  621. ReturnSize,
  622. &Overlapped);
  623. if (GetLastError() == ERROR_IO_PENDING)
  624. {
  625. IoctlSuccess = GetOverlappedResult(WmipKMHandle,
  626. &Overlapped,
  627. ReturnSize,
  628. TRUE);
  629. }
  630. if (! IoctlSuccess)
  631. {
  632. Status = GetLastError();
  633. } else {
  634. Status = ERROR_SUCCESS;
  635. }
  636. } while (Status == ERROR_WMI_TRY_AGAIN);
  637. NtClose( WmipKMHandle );
  638. WmipFreeEvent(Overlapped.hEvent);
  639. return(Status);
  640. }
  641. //+---------------------------------------------------------------------------
  642. //
  643. // Function: OpenWmiGuidObject
  644. //
  645. // Synopsis: Gets a handle to the specified WmiGuid object
  646. //
  647. // Arguments: [IN pwszObject] -- Object to open
  648. // [IN AccessMask] -- Type of open to do
  649. // [OUT pHandle] -- Where the handle to the object
  650. // is returned
  651. // [OUT KernelType] -- Type of the kernel object
  652. //
  653. // Returns: ERROR_SUCCESS -- Success
  654. //
  655. //----------------------------------------------------------------------------
  656. DWORD
  657. OpenWmiGuidObject(IN LPWSTR pwszObject,
  658. IN ACCESS_MASK AccessMask,
  659. OUT PHANDLE pHandle,
  660. OUT PMARTA_KERNEL_TYPE KernelType)
  661. {
  662. DWORD dwErr;
  663. UNICODE_STRING GuidString;
  664. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  665. WCHAR GuidObjectNameBuffer[WmiGuidObjectNameLength+1];
  666. PWCHAR GuidObjectName = GuidObjectNameBuffer;
  667. ULONG ReturnSize;
  668. OBJECT_ATTRIBUTES ObjectAttributes;
  669. ULONG Length;
  670. acDebugOut((DEB_TRACE, "In OpenWmiGuidObject\n"));
  671. Length = (wcslen(WmiGuidObjectDirectory) + wcslen(pwszObject) + 1) * sizeof(WCHAR);
  672. if ( Length > sizeof(GuidObjectNameBuffer) )
  673. {
  674. GuidObjectName = (PWCHAR)LocalAlloc( LPTR, Length );
  675. if ( GuidObjectName == NULL )
  676. {
  677. return ERROR_NOT_ENOUGH_MEMORY;
  678. }
  679. }
  680. wcscpy(GuidObjectName, WmiGuidObjectDirectory);
  681. wcscat(GuidObjectName, pwszObject);
  682. RtlInitUnicodeString(&GuidString, GuidObjectName);
  683. memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  684. ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
  685. ObjectAttributes.ObjectName = &GuidString;
  686. WmiOpenGuidBlock.ObjectAttributes = &ObjectAttributes;
  687. WmiOpenGuidBlock.DesiredAccess = AccessMask;
  688. dwErr = WmipSendWmiKMRequest(IOCTL_WMI_OPEN_GUID,
  689. (PVOID)&WmiOpenGuidBlock,
  690. sizeof(WMIOPENGUIDBLOCK),
  691. sizeof(WMIOPENGUIDBLOCK),
  692. &ReturnSize);
  693. if (dwErr == ERROR_SUCCESS)
  694. {
  695. *pHandle = WmiOpenGuidBlock.Handle.Handle;
  696. *KernelType = MARTA_WMI_GUID;
  697. }
  698. else
  699. {
  700. *pHandle = NULL;
  701. }
  702. if ( GuidObjectName != GuidObjectNameBuffer )
  703. {
  704. LocalFree( GuidObjectName );
  705. }
  706. acDebugOut((DEB_TRACE, "Out OpenWmiGuidObject: %lu\n", dwErr));
  707. return(dwErr);
  708. }
  709. //+---------------------------------------------------------------------------
  710. //
  711. // Function: ReadWmiGuidPropertyRights
  712. //
  713. // Synopsis: Gets the specified rights from the WmiGuids object
  714. //
  715. // Arguments: [IN pwszObject] -- The object to get the rights
  716. // for
  717. // [IN pRightsList] -- SecurityInfo to read based
  718. // on properties
  719. // [IN cRights] -- Number of items in rights list
  720. // [IN AccessList] -- Access List to fill in
  721. //
  722. // Returns: ERROR_SUCCESS -- Success
  723. // ERROR_INVALID_PARAMETER -- A bad property was encountered
  724. //
  725. // Note: Kernel objects are assumed to be created through the
  726. // Win32 APIs so they all reside in the \basenamedobjects
  727. // directory.
  728. //
  729. //----------------------------------------------------------------------------
  730. DWORD
  731. ReadWmiGuidPropertyRights(IN LPWSTR pwszObject,
  732. IN PACTRL_RIGHTS_INFO pRightsList,
  733. IN ULONG cRights,
  734. IN CAccessList& AccessList)
  735. {
  736. acDebugOut((DEB_TRACE, "in ReadKernelPropertyRights\n"));
  737. DWORD dwErr = ERROR_SUCCESS;
  738. HANDLE hObject;
  739. MARTA_KERNEL_TYPE KernelType;
  740. //
  741. // Kernel objects don't have parents from whom they can inherit
  742. //
  743. ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
  744. if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
  745. {
  746. return(ERROR_INVALID_PARAMETER);
  747. }
  748. dwErr = OpenWmiGuidObject(pwszObject,
  749. GetDesiredAccess(READ_ACCESS_RIGHTS,
  750. pRightsList[0].SeInfo),
  751. &hObject,
  752. &KernelType);
  753. if(dwErr == ERROR_SUCCESS)
  754. {
  755. dwErr = GetWmiGuidSecurityInfo(hObject,
  756. pRightsList,
  757. cRights,
  758. AccessList);
  759. CloseWmiGuidObject(hObject);
  760. }
  761. acDebugOut((DEB_TRACE, "Out ReadKernelPropertyRights: %lu\n", dwErr));
  762. return (dwErr);
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // Function: GetKernelSecurityInfo
  767. //
  768. // Arguments: [IN hObject] -- The handle to the object to
  769. // get the rights for
  770. // [IN SeInfo] -- SecurityInfo to read based
  771. // on properties
  772. // [IN cRights] -- Number of items in rights list
  773. // [IN AccessList] -- Access List to fill in
  774. //
  775. // Returns: ERROR_SUCCESS -- Success
  776. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  777. //
  778. //----------------------------------------------------------------------------
  779. DWORD
  780. GetWmiGuidSecurityInfo(IN HANDLE hObject,
  781. IN PACTRL_RIGHTS_INFO pRightsList,
  782. IN ULONG cRights,
  783. IN CAccessList& AccessList)
  784. {
  785. acDebugOut((DEB_TRACE, "in GetWmiGuidSecurityInfo\n"));
  786. UCHAR pSDBuff[PSD_BASE_LENGTH];
  787. PISECURITY_DESCRIPTOR pSD;
  788. DWORD dwErr = ERROR_SUCCESS;
  789. NTSTATUS Status;
  790. ULONG cNeeded = 0;
  791. for(ULONG iIndex = 0; iIndex < cRights && dwErr == ERROR_SUCCESS; iIndex++)
  792. {
  793. pSD = (PISECURITY_DESCRIPTOR)pSDBuff;
  794. Status = NtQuerySecurityObject(hObject,
  795. pRightsList[iIndex].SeInfo,
  796. pSD,
  797. PSD_BASE_LENGTH,
  798. &cNeeded);
  799. if(!NT_SUCCESS(Status))
  800. {
  801. if(Status == STATUS_BUFFER_TOO_SMALL)
  802. {
  803. //
  804. // Fine.. Allocate a big enough buffer
  805. //
  806. pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
  807. if(pSD == NULL)
  808. {
  809. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  810. break;
  811. }
  812. Status = NtQuerySecurityObject(hObject,
  813. pRightsList[iIndex].SeInfo,
  814. pSD,
  815. cNeeded,
  816. &cNeeded);
  817. }
  818. }
  819. //
  820. // Now, we've either got a failure or a valid SD...
  821. //
  822. if(NT_SUCCESS(Status))
  823. {
  824. dwErr = AccessList.AddSD(pSD,
  825. pRightsList[iIndex].SeInfo,
  826. pRightsList[iIndex].pwszProperty);
  827. }
  828. else
  829. {
  830. dwErr = RtlNtStatusToDosError(Status);
  831. }
  832. if(pSD != (PISECURITY_DESCRIPTOR)pSDBuff)
  833. {
  834. AccFree(pSD);
  835. }
  836. }
  837. acDebugOut((DEB_TRACE, "Out GetWmiGuidSecurityInfo: %lu\n", dwErr));
  838. return(dwErr);
  839. }
  840. //+---------------------------------------------------------------------------
  841. //
  842. // Function: SetWmiGuidSecurityInfo
  843. //
  844. // Synopsis: Sets the specified security info for the handle's
  845. // WmiGuid object
  846. //
  847. // Arguments: [IN hKernel] -- The handle of the object
  848. // [IN SeInfo] -- Flag indicating what security
  849. // info to set
  850. // [IN pwszProperty] -- The property on the object to
  851. // set
  852. // For kernel objects, this MBZ
  853. // [IN pSD] -- The security descriptor to set
  854. //
  855. // Returns: ERROR_SUCCESS -- Success
  856. // ERROR_INVALID_PARAMETER -- A bad property was given
  857. //
  858. //----------------------------------------------------------------------------
  859. DWORD
  860. SetWmiGuidSecurityInfo(IN HANDLE hWmiGuid,
  861. IN SECURITY_INFORMATION SeInfo,
  862. IN PWSTR pwszProperty,
  863. IN PSECURITY_DESCRIPTOR pSD)
  864. {
  865. acDebugOut((DEB_TRACE, "in SetWmiGuidSecurityInfo\n"));
  866. DWORD dwErr = ERROR_SUCCESS;
  867. if(pwszProperty != NULL)
  868. {
  869. dwErr = ERROR_INVALID_PARAMETER;
  870. }
  871. else
  872. {
  873. NTSTATUS Status = NtSetSecurityObject(hWmiGuid,
  874. SeInfo,
  875. pSD);
  876. dwErr = RtlNtStatusToDosError(Status);
  877. }
  878. acDebugOut((DEB_TRACE, "Out SetWmiGuidSecurityInfo %lu\n", dwErr));
  879. return (dwErr);
  880. }
  881. //+---------------------------------------------------------------------------
  882. //
  883. // Function: GetKernelSecurityInfo
  884. //
  885. // Arguments: [IN hObject] -- The handle to the object to
  886. // get the rights for
  887. // [IN pRightsList] -- SecurityInfo to read based
  888. // on properties
  889. // [IN cRights] -- Number of items in rights list
  890. // [IN AccessList] -- Access List to fill in
  891. //
  892. // Returns: ERROR_SUCCESS -- Success
  893. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  894. //
  895. //----------------------------------------------------------------------------
  896. DWORD
  897. GetWmiGuidSecurityInfo(IN HANDLE hObject,
  898. IN SECURITY_INFORMATION SeInfo,
  899. OUT PACL *ppDAcl,
  900. OUT PACL *ppSAcl,
  901. OUT PSECURITY_DESCRIPTOR *ppSD)
  902. {
  903. acDebugOut((DEB_TRACE, "in GetWmiGuidSecurityInfo\n"));
  904. PISECURITY_DESCRIPTOR pSD = NULL;
  905. DWORD dwErr = ERROR_SUCCESS;
  906. NTSTATUS Status;
  907. ULONG cNeeded = 0;
  908. Status = NtQuerySecurityObject(hObject,
  909. SeInfo,
  910. pSD,
  911. 0,
  912. &cNeeded);
  913. if(!NT_SUCCESS(Status))
  914. {
  915. if(Status == STATUS_BUFFER_TOO_SMALL)
  916. {
  917. //
  918. // Fine.. Allocate a big enough buffer
  919. //
  920. pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
  921. if(pSD == NULL)
  922. {
  923. Status = STATUS_NO_MEMORY;
  924. }
  925. else
  926. {
  927. Status = NtQuerySecurityObject(hObject,
  928. SeInfo,
  929. pSD,
  930. cNeeded,
  931. &cNeeded);
  932. }
  933. }
  934. }
  935. //
  936. // Now, we've either got a failure or a valid SD...
  937. //
  938. if(NT_SUCCESS(Status))
  939. {
  940. if (pSD != NULL)
  941. {
  942. if(ppDAcl != NULL)
  943. {
  944. *ppDAcl = RtlpDaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
  945. }
  946. if(ppSAcl != NULL)
  947. {
  948. *ppSAcl = RtlpSaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
  949. }
  950. *ppSD = pSD;
  951. }
  952. else
  953. {
  954. dwErr = ERROR_ACCESS_DENIED;
  955. }
  956. }
  957. else
  958. {
  959. dwErr = RtlNtStatusToDosError(Status);
  960. }
  961. acDebugOut((DEB_TRACE, "Out GetWmiGuidSecurityInfo: %lu\n", dwErr));
  962. return(dwErr);
  963. }