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.

1418 lines
44 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: NTMARTA.CXX
  7. //
  8. // Contents: Implementation of the private provider functions and
  9. // worker threads
  10. //
  11. // History: 22-Jul-96 MacM Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <aclpch.hxx>
  15. #pragma hdrstop
  16. #include <ntprov.hxx>
  17. //
  18. // This macro montiors the worker thread interrupt flag, and goes to to the
  19. // CleanUp label when it discovers it has been set.
  20. //
  21. #define CLEANUP_ON_INTERRUPT(info) \
  22. if(info->pWrkrInfo->fState != 0) \
  23. { \
  24. goto CleanUp; \
  25. }
  26. DWORD
  27. InsertAndContinueWorkerThread(IN PNTMARTA_WRKR_INFO pWrkrInfo);
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Function: NtProvFreeWorkerItem
  31. //
  32. // Synopsis: Used by the linked list class that maintains the list of
  33. // active worker threads. This is used to delete an item
  34. // in the worker list. If the thread is still active, it
  35. // will be given some amount of time to finish. If it hasn't
  36. // finished in that amount of time, it will be killed. Note
  37. // that this means that a memory leak could occur.
  38. //
  39. // Arguments: [IN pv] -- Item to be freed
  40. //
  41. // Returns: void
  42. //
  43. // Notes:
  44. //
  45. //----------------------------------------------------------------------------
  46. VOID
  47. NtProvFreeWorkerItem(PVOID pv)
  48. {
  49. PNTMARTA_WRKR_INFO pWI = (PNTMARTA_WRKR_INFO)pv;
  50. if(pWI != NULL && pWI->hWorker != NULL)
  51. {
  52. pWI->fState++;
  53. DWORD dwPop = WaitForSingleObject(pWI->hWorker,
  54. THREAD_KILL_WAIT);
  55. if(dwPop == WAIT_ABANDONED)
  56. {
  57. //
  58. // The wait timed out, so kill it. Note also that the rules
  59. // state that anytime the thread stops, we need to set the
  60. // event as well.
  61. //
  62. TerminateThread(pWI->hWorker,
  63. ERROR_OPERATION_ABORTED);
  64. SetEvent(pWI->pOverlapped->hEvent);
  65. //
  66. // The memory passed in to the thread as an argument was just
  67. // leaked. this is fixable.
  68. //
  69. }
  70. }
  71. //
  72. // Deallocate our memory
  73. //
  74. AccFree(pv);
  75. }
  76. //+---------------------------------------------------------------------------
  77. //
  78. // Function: NtProvFindWorkerItem
  79. //
  80. // Synopsis: Used by the linked list class that maintains the list of
  81. // active worker threads. This is used locate a particular
  82. // worker item in the list
  83. //
  84. // Arguments: [IN pv1] -- Item to be found. In this
  85. // case, a pOverlapped struct
  86. // [IN pv2] -- Item in the list. In this case,
  87. // a PNTMARTA_WRKR_INFO struct.
  88. //
  89. // Returns: TRUE -- They match
  90. // FALSE -- They don't match
  91. //
  92. // Notes:
  93. //
  94. //----------------------------------------------------------------------------
  95. BOOL
  96. NtProvFindWorkerItem(PVOID pv1,
  97. PVOID pv2)
  98. {
  99. PNTMARTA_WRKR_INFO pWI = (PNTMARTA_WRKR_INFO)pv2;
  100. PACTRL_OVERLAPPED pOL = (PACTRL_OVERLAPPED)pv1;
  101. if(pWI->pOverlapped->hEvent == pOL->hEvent)
  102. {
  103. return(TRUE);
  104. }
  105. return(FALSE);
  106. }
  107. //+---------------------------------------------------------------------------
  108. //
  109. // Function: NtProvGetBasePathForFilePath
  110. //
  111. // Synopsis: Gets the base path for this item as necessary. For
  112. // a FILE type object, it will check to see if it is a DFS path,
  113. // and if so, will retrieve the list of machine paths that
  114. // support this DFS path. For a non-File object, the path is
  115. // simply copied.
  116. //
  117. // Arguments: [IN pwszObject] -- Object path
  118. // [IN ObjectType] -- The type of the object
  119. // [OUT pcPaths] -- Where the count of paths
  120. // is to be returned
  121. // [OUT pppwszBasePaths] -- The list of paths.
  122. //
  123. // Returns: VOID
  124. //
  125. // Notes: The returned list must be free via a call to AccFree
  126. //
  127. //----------------------------------------------------------------------------
  128. DWORD
  129. NtProvGetBasePathsForFilePath(PWSTR pwszObject,
  130. SE_OBJECT_TYPE ObjectType,
  131. PULONG pcPaths,
  132. PWSTR **pppwszBasePaths)
  133. {
  134. DWORD dwErr = ERROR_SUCCESS;
  135. *pcPaths = 0;
  136. //
  137. // First, we'll see if it's a relative path. If so, we'll have to
  138. // build a full path...
  139. //
  140. PWSTR pwszFullPath = pwszObject;
  141. DWORD dwSize;
  142. if(ObjectType == SE_FILE_OBJECT)
  143. {
  144. if(wcslen(pwszObject) < 2 ||
  145. (pwszObject[1] != L':' && pwszObject[1] != L'\\'))
  146. {
  147. //
  148. // It's a relative path...
  149. //
  150. dwSize = GetFullPathName(pwszObject,
  151. 0,
  152. NULL,
  153. NULL);
  154. if(dwSize == 0)
  155. {
  156. dwErr = GetLastError();
  157. }
  158. else
  159. {
  160. pwszFullPath = (PWSTR)AccAlloc((dwSize + 1) * sizeof(WCHAR));
  161. if(pwszFullPath == NULL)
  162. {
  163. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  164. }
  165. else
  166. {
  167. PWSTR pwszFilePart;
  168. if(GetFullPathName(pwszObject,
  169. dwSize,
  170. pwszFullPath,
  171. &pwszFilePart) == 0)
  172. {
  173. dwErr = GetLastError();
  174. }
  175. }
  176. }
  177. }
  178. //
  179. // Ok, now see if it's a DFS path
  180. //
  181. if(dwErr == ERROR_SUCCESS)
  182. {
  183. dwErr = LoadDLLFuncTable();
  184. if(dwErr == ERROR_SUCCESS)
  185. {
  186. /*
  187. if(IsThisADfsPath(pwszFullPath,0) == TRUE)
  188. {
  189. dwErr = GetLMDfsPaths(pwszFullPath,
  190. pcPaths,
  191. pppwszBasePaths);
  192. }
  193. else
  194. {
  195. */
  196. *pppwszBasePaths = (PWSTR *)AccAlloc(sizeof(PWSTR) +
  197. SIZE_PWSTR(pwszObject));
  198. if(*pppwszBasePaths == NULL)
  199. {
  200. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  201. }
  202. else
  203. {
  204. (*pppwszBasePaths)[0] =
  205. (PWSTR)((PBYTE)*pppwszBasePaths + sizeof(PWSTR));
  206. wcscpy((PWSTR)((PBYTE)*pppwszBasePaths + sizeof(PWSTR)),
  207. pwszObject);
  208. *pcPaths = 1;
  209. }
  210. // }
  211. }
  212. }
  213. }
  214. else
  215. {
  216. *pppwszBasePaths = (PWSTR *)AccAlloc(sizeof(PWSTR) +
  217. SIZE_PWSTR(pwszObject));
  218. if(*pppwszBasePaths == NULL)
  219. {
  220. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  221. }
  222. else
  223. {
  224. (*pppwszBasePaths)[0] =
  225. (PWSTR)((PBYTE)*pppwszBasePaths + sizeof(PWSTR));
  226. wcscpy((PWSTR)((PBYTE)*pppwszBasePaths + sizeof(PWSTR)),
  227. pwszObject);
  228. *pcPaths = 1;
  229. }
  230. }
  231. //
  232. // Make sure to deallocate any memory
  233. //
  234. if(pwszFullPath != pwszObject)
  235. {
  236. AccFree(pwszFullPath);
  237. }
  238. return(dwErr);
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Function: NtProvSetAccessRightsWorkerThread
  243. //
  244. // Synopsis: Sets the access rights on the given object. It replaces any
  245. // existing rights.
  246. //
  247. // Arguments: [IN pWorkerArgs] -- Pointer to the structure that
  248. // contains all of the thread
  249. // arguments.
  250. //
  251. // Returns: ERROR_SUCCESS -- Success
  252. // ERROR_OPERATION_ABORTED -- The operation was aborted
  253. //
  254. // Notes:
  255. //
  256. //----------------------------------------------------------------------------
  257. DWORD
  258. NtProvSetAccessRightsWorkerThread(IN PVOID pWorkerArgs)
  259. {
  260. PNTMARTA_SET_WRKR_INFO pSetInfo = (PNTMARTA_SET_WRKR_INFO)pWorkerArgs;
  261. DWORD dwErr = ERROR_SUCCESS;
  262. PSECURITY_DESCRIPTOR pSD = NULL;
  263. MARTA_KERNEL_TYPE KernelType;
  264. {
  265. //
  266. // Now, we'll do this in a loop, so we can handle the DFS case where
  267. // we get a failure on one path, but another path may work
  268. //
  269. pSetInfo->pWrkrInfo->cProcessed = 0;
  270. ULONG iIndex = 0;
  271. do
  272. {
  273. CLEANUP_ON_INTERRUPT(pSetInfo)
  274. //
  275. // If it worked, write them all out...
  276. //
  277. if(dwErr == ERROR_SUCCESS)
  278. {
  279. CLEANUP_ON_INTERRUPT(pSetInfo)
  280. //
  281. // First, get the Security Descriptor
  282. //
  283. SECURITY_INFORMATION SeInfo;
  284. ULONG fSDFlags = ACCLIST_SD_ABSOK;
  285. if(pSetInfo->ObjectType == SE_DS_OBJECT ||
  286. pSetInfo->ObjectType == SE_DS_OBJECT_ALL)
  287. {
  288. pSetInfo->pAccessList->SetDsPathInfo(NULL,
  289. (PWSTR)pSetInfo->ppwszObjectList[iIndex]);
  290. fSDFlags = 0;
  291. }
  292. dwErr = pSetInfo->pAccessList->BuildSDForAccessList(&pSD,
  293. &SeInfo,
  294. fSDFlags);
  295. CLEANUP_ON_INTERRUPT(pSetInfo)
  296. if(dwErr == ERROR_SUCCESS)
  297. {
  298. HANDLE hObject = NULL;
  299. BOOL fHandleLocal = TRUE;
  300. if(FLAG_ON(pSetInfo->fFlags, NTMARTA_HANDLE_VALID))
  301. {
  302. hObject = pSetInfo->hObject;
  303. fHandleLocal = FALSE;
  304. }
  305. switch (pSetInfo->ObjectType)
  306. {
  307. case SE_SERVICE:
  308. if(fHandleLocal == TRUE)
  309. {
  310. dwErr = OpenServiceObject(
  311. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  312. GetDesiredAccess(WRITE_ACCESS_RIGHTS,
  313. SeInfo),
  314. (SC_HANDLE *)&hObject);
  315. }
  316. if(dwErr == ERROR_SUCCESS)
  317. {
  318. if(pSetInfo->pWrkrInfo->fState != 0)
  319. {
  320. CloseServiceObject((SC_HANDLE)hObject);
  321. goto CleanUp;
  322. }
  323. dwErr = SetServiceSecurityInfo((SC_HANDLE)hObject,
  324. SeInfo,
  325. NULL,
  326. pSD);
  327. if(fHandleLocal == TRUE)
  328. {
  329. CloseServiceObject((SC_HANDLE)hObject);
  330. }
  331. }
  332. break;
  333. case SE_PRINTER:
  334. if(fHandleLocal == TRUE)
  335. {
  336. dwErr = OpenPrinterObject(
  337. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  338. GetDesiredAccess(WRITE_ACCESS_RIGHTS,
  339. SeInfo),
  340. &hObject);
  341. }
  342. if(dwErr == ERROR_SUCCESS)
  343. {
  344. if(pSetInfo->pWrkrInfo->fState != 0)
  345. {
  346. ClosePrinterObject(hObject);
  347. goto CleanUp;
  348. }
  349. dwErr = SetPrinterSecurityInfo(hObject,
  350. SeInfo,
  351. NULL,
  352. pSD);
  353. if(fHandleLocal == TRUE)
  354. {
  355. ClosePrinterObject(hObject);
  356. }
  357. }
  358. break;
  359. case SE_LMSHARE:
  360. dwErr = SetShareSecurityInfo(
  361. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  362. SeInfo,
  363. NULL,
  364. pSD);
  365. break;
  366. case SE_KERNEL_OBJECT:
  367. if(fHandleLocal == TRUE)
  368. {
  369. dwErr = OpenKernelObject(
  370. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  371. GetDesiredAccess(WRITE_ACCESS_RIGHTS,
  372. SeInfo),
  373. &hObject,
  374. &KernelType);
  375. if(dwErr == ERROR_SUCCESS)
  376. {
  377. pSetInfo->pAccessList->SetKernelObjectType( KernelType );
  378. }
  379. }
  380. if(dwErr == ERROR_SUCCESS)
  381. {
  382. if(pSetInfo->pWrkrInfo->fState != 0)
  383. {
  384. CloseKernelObject(hObject);
  385. goto CleanUp;
  386. }
  387. dwErr = SetKernelSecurityInfo(hObject,
  388. SeInfo,
  389. NULL,
  390. pSD);
  391. if(fHandleLocal == TRUE)
  392. {
  393. CloseKernelObject(hObject);
  394. }
  395. }
  396. break;
  397. case SE_WMIGUID_OBJECT:
  398. if(fHandleLocal == TRUE)
  399. {
  400. dwErr = OpenWmiGuidObject(
  401. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  402. GetDesiredAccess(WRITE_ACCESS_RIGHTS,
  403. SeInfo),
  404. &hObject,
  405. &KernelType);
  406. if(dwErr == ERROR_SUCCESS)
  407. {
  408. pSetInfo->pAccessList->SetKernelObjectType( KernelType );
  409. }
  410. }
  411. if(dwErr == ERROR_SUCCESS)
  412. {
  413. if(pSetInfo->pWrkrInfo->fState != 0)
  414. {
  415. CloseKernelObject(hObject);
  416. goto CleanUp;
  417. }
  418. dwErr = SetWmiGuidSecurityInfo(hObject,
  419. SeInfo,
  420. NULL,
  421. pSD);
  422. if(fHandleLocal == TRUE)
  423. {
  424. CloseWmiGuidObject(hObject);
  425. }
  426. }
  427. break;
  428. case SE_FILE_OBJECT:
  429. if(fHandleLocal == TRUE)
  430. {
  431. dwErr = SetAndPropagateFilePropertyRights(
  432. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  433. NULL,
  434. *(pSetInfo->pAccessList),
  435. &(pSetInfo->pWrkrInfo->fState),
  436. &(pSetInfo->pWrkrInfo->cProcessed),
  437. NULL);
  438. }
  439. else
  440. {
  441. dwErr = SetAndPropagateFilePropertyRightsByHandle(
  442. hObject,
  443. NULL,
  444. *(pSetInfo->pAccessList),
  445. &(pSetInfo->pWrkrInfo->fState),
  446. &(pSetInfo->pWrkrInfo->cProcessed));
  447. }
  448. break;
  449. case SE_REGISTRY_KEY:
  450. if(fHandleLocal == TRUE)
  451. {
  452. dwErr = SetAndPropagateRegistryPropertyRights(
  453. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  454. NULL,
  455. *(pSetInfo->pAccessList),
  456. &(pSetInfo->pWrkrInfo->fState),
  457. &(pSetInfo->pWrkrInfo->cProcessed));
  458. }
  459. else
  460. {
  461. dwErr = SetAndPropagateRegistryPropertyRightsByHandle(
  462. (HKEY)hObject,
  463. *(pSetInfo->pAccessList),
  464. &(pSetInfo->pWrkrInfo->fState),
  465. &(pSetInfo->pWrkrInfo->cProcessed));
  466. }
  467. break;
  468. case SE_DS_OBJECT:
  469. case SE_DS_OBJECT_ALL:
  470. dwErr = SetDSObjSecurityInfo(
  471. (PWSTR)pSetInfo->ppwszObjectList[iIndex],
  472. SeInfo,
  473. NULL,
  474. pSD,
  475. pSetInfo->pAccessList->QuerySDSize(),
  476. &(pSetInfo->pWrkrInfo->fState),
  477. &(pSetInfo->pWrkrInfo->cProcessed));
  478. break;
  479. case SE_WINDOW_OBJECT:
  480. if(SetUserObjectSecurity(hObject,
  481. &SeInfo,
  482. pSD) == FALSE)
  483. {
  484. dwErr = GetLastError();
  485. }
  486. break;
  487. default:
  488. dwErr = ERROR_INVALID_PARAMETER;
  489. break;
  490. }
  491. }
  492. }
  493. CLEANUP_ON_INTERRUPT(pSetInfo)
  494. iIndex++;
  495. } while(dwErr != ERROR_SUCCESS && iIndex < pSetInfo->cObjects);
  496. }
  497. //
  498. // This is the cleanup section
  499. //
  500. CleanUp:
  501. AccFree(pSetInfo->ppwszObjectList);
  502. //
  503. // See if we need to clean up any allocated memory
  504. //
  505. if(pSetInfo->fFlags & NTMARTA_DELETE_ALIST)
  506. {
  507. delete pSetInfo->pAccessList;
  508. }
  509. if(pSetInfo->pWrkrInfo->fState != 0)
  510. {
  511. dwErr = ERROR_OPERATION_ABORTED;
  512. }
  513. HANDLE hEvent = pSetInfo->pWrkrInfo->pOverlapped->hEvent;
  514. //
  515. // See if we need to delete the arguments themselves
  516. //
  517. if(pSetInfo->fFlags & NTMARTA_DELETE_ARGS)
  518. {
  519. AccFree(pSetInfo);
  520. }
  521. //
  522. // Finally, set our event
  523. //
  524. SetEvent(hEvent);
  525. ExitThread(dwErr);
  526. return(dwErr);
  527. }
  528. //+---------------------------------------------------------------------------
  529. //
  530. // Function: NtProvDoSet
  531. //
  532. // Synopsis: Sets up the worker thread to do the SetAccessRights
  533. //
  534. // Arguments: [IN pwszObjectPath] -- Path to the object in question
  535. // [IN ObjectType] -- Type of the object
  536. // [IN pSetInfo] -- List of rights infos
  537. // [IN cRightsInfos] -- Number of items in list
  538. // [IN pAccessList] -- Ptr to a CAccessList class
  539. // [IN pOwner] -- Optional. Owner to set
  540. // [IN pGroup] -- Optional. Group to set
  541. // [IN pOverlapped] -- Overlapped structure to use for
  542. // asynchronous control
  543. // [IN fSetFlags] -- Flags governing the control of
  544. // the worker thread
  545. //
  546. // Returns: ERROR_SUCCESS -- Success
  547. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  548. //
  549. // Notes:
  550. //
  551. //----------------------------------------------------------------------------
  552. DWORD
  553. NtProvDoSet(IN LPCWSTR pwszObjectPath,
  554. IN SE_OBJECT_TYPE ObjectType,
  555. IN CAccessList *pAccessList,
  556. IN PACTRL_OVERLAPPED pOverlapped,
  557. IN DWORD fSetFlags)
  558. {
  559. DWORD dwErr = ERROR_SUCCESS;
  560. //
  561. // Ok, we'll create the relevant information structures, create
  562. // the thread, and then let it go.
  563. //
  564. PNTMARTA_WRKR_INFO pWrkrInfo = NULL;
  565. PNTMARTA_SET_WRKR_INFO pSetWrkrInfo =
  566. (PNTMARTA_SET_WRKR_INFO)AccAlloc(sizeof(NTMARTA_SET_WRKR_INFO));
  567. if(pSetWrkrInfo == NULL)
  568. {
  569. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  570. }
  571. else
  572. {
  573. pSetWrkrInfo->ppwszObjectList = NULL;
  574. //
  575. // Initialize the rest of the items
  576. //
  577. pSetWrkrInfo->ObjectType = ObjectType;
  578. pSetWrkrInfo->pAccessList= pAccessList;
  579. pSetWrkrInfo->fFlags = fSetFlags | NTMARTA_DELETE_ARGS;
  580. }
  581. //
  582. // If that worked, create the new worker info struct
  583. //
  584. if(dwErr == ERROR_SUCCESS)
  585. {
  586. //
  587. // First, create a new structure
  588. //
  589. pWrkrInfo = (PNTMARTA_WRKR_INFO)AccAlloc(sizeof(NTMARTA_WRKR_INFO));
  590. if(pWrkrInfo == NULL)
  591. {
  592. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  593. }
  594. else
  595. {
  596. //
  597. // Initialize the structure members
  598. //
  599. pWrkrInfo->pOverlapped = pOverlapped;
  600. pWrkrInfo->fState = 0;
  601. pSetWrkrInfo->pWrkrInfo = pWrkrInfo;
  602. }
  603. }
  604. //
  605. // Now, get the path information
  606. //
  607. if(dwErr == ERROR_SUCCESS)
  608. {
  609. dwErr = NtProvGetBasePathsForFilePath((PWSTR)pwszObjectPath,
  610. pSetWrkrInfo->ObjectType,
  611. &(pSetWrkrInfo->cObjects),
  612. &(pSetWrkrInfo->ppwszObjectList));
  613. }
  614. //
  615. // Then, create the thread, SUSPENDED. The insertion routine will send
  616. // if off.
  617. //
  618. if(dwErr == ERROR_SUCCESS)
  619. {
  620. DWORD dwThreadId;
  621. HANDLE hThreadToken;
  622. if (OpenThreadToken(
  623. GetCurrentThread(),
  624. MAXIMUM_ALLOWED,
  625. TRUE, // OpenAsSelf
  626. &hThreadToken
  627. ))
  628. {
  629. //
  630. // We're impersonating, turn it off and remember the handle
  631. //
  632. RevertToSelf();
  633. } else {
  634. hThreadToken = NULL;
  635. }
  636. HANDLE hWorker = CreateThread(NULL,
  637. 0,
  638. NtProvSetAccessRightsWorkerThread,
  639. (LPVOID)pSetWrkrInfo,
  640. CREATE_SUSPENDED,
  641. &dwThreadId);
  642. if (hThreadToken != NULL) {
  643. (VOID) SetThreadToken (
  644. NULL,
  645. hThreadToken
  646. );
  647. CloseHandle( hThreadToken );
  648. hThreadToken = NULL;
  649. }
  650. if(hWorker == NULL)
  651. {
  652. dwErr = GetLastError();
  653. }
  654. else
  655. {
  656. pWrkrInfo->hWorker = hWorker;
  657. //
  658. // Now, insert the new node in the list. Note the use of the
  659. // resource, since the list is not multi-thread safe. Note the
  660. // scoping, since we need to protect the list until the thread
  661. // actually gets started
  662. //
  663. dwErr = InsertAndContinueWorkerThread(pWrkrInfo);
  664. }
  665. }
  666. if(dwErr != ERROR_SUCCESS)
  667. {
  668. //
  669. // Clean up the allocated memory
  670. //
  671. if(pSetWrkrInfo != NULL)
  672. {
  673. AccFree(pSetWrkrInfo->ppwszObjectList);
  674. }
  675. AccFree(pSetWrkrInfo);
  676. if(pWrkrInfo != NULL)
  677. {
  678. AccFree(pWrkrInfo);
  679. }
  680. }
  681. return(dwErr);
  682. }
  683. //+---------------------------------------------------------------------------
  684. //
  685. // Function: NtProvDoHandleSet
  686. //
  687. // Synopsis: Sets up the worker thread to do the SetAccessRights for the
  688. // handle based APIs
  689. //
  690. // Arguments: [IN hObject] -- Handle to the object
  691. // [IN ObjectType] -- Type of the object
  692. // [IN pSetInfo] -- List of rights infos
  693. // [IN cRightsInfos] -- Number of items in list
  694. // [IN pAccessList] -- Ptr to a CAccessList class
  695. // [IN pOwner] -- Optional. Owner to set
  696. // [IN pGroup] -- Optional. Group to set
  697. // [IN pOverlapped] -- Overlapped structure to use for
  698. // asynchronous control
  699. // [IN fSetFlags] -- Flags governing the control of
  700. // the worker thread
  701. //
  702. // Returns: ERROR_SUCCESS -- Success
  703. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  704. //
  705. // Notes:
  706. //
  707. //----------------------------------------------------------------------------
  708. DWORD
  709. NtProvDoHandleSet(IN HANDLE hObject,
  710. IN SE_OBJECT_TYPE ObjectType,
  711. IN CAccessList *pAccessList,
  712. IN PACTRL_OVERLAPPED pOverlapped,
  713. IN DWORD fSetFlags)
  714. {
  715. DWORD dwErr = ERROR_SUCCESS;
  716. //
  717. // Ok, we'll create the relevant information structures, create
  718. // the thread, and then let it go.
  719. //
  720. PNTMARTA_WRKR_INFO pWrkrInfo = NULL;
  721. PNTMARTA_SET_WRKR_INFO pSetWrkrInfo =
  722. (PNTMARTA_SET_WRKR_INFO)AccAlloc(sizeof(NTMARTA_SET_WRKR_INFO));
  723. if(pSetWrkrInfo == NULL)
  724. {
  725. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  726. }
  727. else
  728. {
  729. pSetWrkrInfo->ppwszObjectList = NULL;
  730. //
  731. // Initialize the rest of the items
  732. //
  733. pSetWrkrInfo->ObjectType = ObjectType;
  734. pSetWrkrInfo->pAccessList= pAccessList;
  735. pSetWrkrInfo->fFlags = fSetFlags |
  736. NTMARTA_DELETE_ARGS |
  737. NTMARTA_HANDLE_VALID;
  738. pSetWrkrInfo->hObject = hObject;
  739. }
  740. //
  741. // If that worked, create the new worker info struct
  742. //
  743. if(dwErr == ERROR_SUCCESS)
  744. {
  745. //
  746. // First, create a new structure
  747. //
  748. pWrkrInfo = (PNTMARTA_WRKR_INFO)AccAlloc(sizeof(NTMARTA_WRKR_INFO));
  749. if(pWrkrInfo == NULL)
  750. {
  751. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  752. }
  753. else
  754. {
  755. //
  756. // Initialize the structure members
  757. //
  758. pWrkrInfo->pOverlapped = pOverlapped;
  759. pWrkrInfo->fState = 0;
  760. pSetWrkrInfo->pWrkrInfo = pWrkrInfo;
  761. }
  762. }
  763. //
  764. // Then, create the thread, SUSPENDED. The insertion routine will send
  765. // if off.
  766. //
  767. if(dwErr == ERROR_SUCCESS)
  768. {
  769. DWORD dwThreadId;
  770. HANDLE hWorker = CreateThread(NULL,
  771. 0,
  772. NtProvSetAccessRightsWorkerThread,
  773. (LPVOID)pSetWrkrInfo,
  774. CREATE_SUSPENDED,
  775. &dwThreadId);
  776. if(hWorker == NULL)
  777. {
  778. dwErr = GetLastError();
  779. }
  780. else
  781. {
  782. pWrkrInfo->hWorker = hWorker;
  783. //
  784. // Now, insert the new node in the list. Note the use of the
  785. // resource, since the list is not multi-thread safe. Note the
  786. // scoping, since we need to protect the list until the thread
  787. // actually gets started
  788. //
  789. dwErr = InsertAndContinueWorkerThread(pWrkrInfo);
  790. }
  791. }
  792. if(dwErr != ERROR_SUCCESS)
  793. {
  794. //
  795. // Clean up the allocated memory
  796. //
  797. if(pSetWrkrInfo != NULL)
  798. {
  799. AccFree(pSetWrkrInfo->ppwszObjectList);
  800. }
  801. AccFree(pSetWrkrInfo);
  802. if(pWrkrInfo != NULL)
  803. {
  804. AccFree(pWrkrInfo);
  805. }
  806. }
  807. return(dwErr);
  808. }
  809. //+---------------------------------------------------------------------------
  810. //
  811. // Function: NtProvGetAccessListForObject
  812. //
  813. // Synopsis:
  814. //
  815. // Arguments: [IN pObjectName] -- Path to the object in question
  816. // [IN ObjectType] -- Type of the object
  817. // [IN SecurityInfo] -- What information is be obtained
  818. // [IN pwszProperty] -- Optional. The name of the
  819. // property on the object to revoke
  820. // for
  821. // [IN OUT AccList] -- The CAccessList reference to fill
  822. // [OUT ppOwner] -- Number of trustees in list
  823. // [OUT ppGroup] -- List of trustees to revoke
  824. //
  825. // Returns: ERROR_SUCCESS -- The operation succeeded
  826. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  827. //
  828. // Notes:
  829. //
  830. //----------------------------------------------------------------------------
  831. DWORD
  832. NtProvGetAccessListForObject(IN PWSTR pwszObject,
  833. IN SE_OBJECT_TYPE ObjectType,
  834. IN PACTRL_RIGHTS_INFO pRightsInfo,
  835. IN ULONG cProps,
  836. OUT CAccessList **ppAccessList)
  837. {
  838. DWORD dwErr = ERROR_SUCCESS;
  839. //
  840. // First, allocate a new class pointer
  841. //
  842. *ppAccessList = new CAccessList;
  843. if(*ppAccessList == NULL)
  844. {
  845. return(ERROR_NOT_ENOUGH_MEMORY);
  846. }
  847. dwErr = (*ppAccessList)->SetObjectType(ObjectType);
  848. for(ULONG iIndex = 0; iIndex < cProps && dwErr == ERROR_SUCCESS; iIndex++)
  849. {
  850. //
  851. // Now, do the read
  852. //
  853. switch (ObjectType)
  854. {
  855. case SE_KERNEL_OBJECT:
  856. dwErr = ReadKernelPropertyRights(pwszObject,
  857. pRightsInfo,
  858. cProps,
  859. **ppAccessList);
  860. break;
  861. case SE_WMIGUID_OBJECT:
  862. dwErr = ReadWmiGuidPropertyRights(pwszObject,
  863. pRightsInfo,
  864. cProps,
  865. **ppAccessList);
  866. break;
  867. case SE_FILE_OBJECT:
  868. dwErr = ReadFilePropertyRights(pwszObject,
  869. pRightsInfo,
  870. cProps,
  871. **ppAccessList);
  872. break;
  873. case SE_SERVICE:
  874. dwErr = ReadServicePropertyRights(pwszObject,
  875. pRightsInfo,
  876. cProps,
  877. **ppAccessList);
  878. break;
  879. case SE_PRINTER:
  880. dwErr = ReadPrinterPropertyRights(pwszObject,
  881. pRightsInfo,
  882. cProps,
  883. **ppAccessList);
  884. break;
  885. case SE_REGISTRY_KEY:
  886. dwErr = ReadRegistryPropertyRights(pwszObject,
  887. pRightsInfo,
  888. cProps,
  889. **ppAccessList);
  890. break;
  891. case SE_LMSHARE:
  892. dwErr = ReadSharePropertyRights(pwszObject,
  893. pRightsInfo,
  894. cProps,
  895. **ppAccessList);
  896. break;
  897. case SE_DS_OBJECT:
  898. #ifdef ACTRL_NEED_SET_PRIVS
  899. dwErr = SetPriv();
  900. if(dwErr == ERROR_SUCCESS)
  901. {
  902. #endif
  903. dwErr = ReadDSObjPropertyRights(pwszObject,
  904. pRightsInfo,
  905. cProps,
  906. **ppAccessList);
  907. #ifdef ACTRL_NEED_SET_PRIVS
  908. }
  909. #endif
  910. break;
  911. case SE_DS_OBJECT_ALL:
  912. #ifdef ACTRL_NEED_SET_PRIVS
  913. dwErr = SetPriv();
  914. if(dwErr == ERROR_SUCCESS)
  915. {
  916. #endif
  917. (**ppAccessList).SetDsPathInfo(NULL,
  918. (PWSTR)pwszObject);
  919. dwErr = ReadAllDSObjPropertyRights(pwszObject,
  920. pRightsInfo,
  921. cProps,
  922. **ppAccessList);
  923. #ifdef ACTRL_NEED_SET_PRIVS
  924. }
  925. #endif
  926. break;
  927. default:
  928. dwErr = ERROR_INVALID_PARAMETER;
  929. break;
  930. }
  931. }
  932. if (dwErr != ERROR_SUCCESS) {
  933. delete (*ppAccessList);
  934. *ppAccessList = 0;
  935. }
  936. return(dwErr);
  937. }
  938. //+---------------------------------------------------------------------------
  939. //
  940. // Function: NtProvGetAccessListForHandle
  941. //
  942. // Synopsis:
  943. //
  944. // Arguments: [IN hObject] -- Handle to the object
  945. // [IN ObjectType] -- Type of the object
  946. // [IN SecurityInfo] -- What information is be obtained
  947. // [IN pwszProperty] -- Optional. The name of the
  948. // property on the object to revoke
  949. // for
  950. // [IN OUT AccList] -- The CAccessList reference to fill
  951. // [OUT ppOwner] -- Number of trustees in list
  952. // [OUT ppGroup] -- List of trustees to revoke
  953. //
  954. // Returns: ERROR_SUCCESS -- The operation succeeded
  955. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  956. //
  957. // Notes:
  958. //
  959. //----------------------------------------------------------------------------
  960. DWORD
  961. NtProvGetAccessListForHandle(IN HANDLE hObject,
  962. IN SE_OBJECT_TYPE ObjectType,
  963. IN PACTRL_RIGHTS_INFO pRightsInfo,
  964. IN ULONG cProps,
  965. OUT CAccessList **ppAccessList)
  966. {
  967. DWORD dwErr = ERROR_SUCCESS;
  968. //
  969. // First, allocate a new class pointer
  970. //
  971. *ppAccessList = new CAccessList;
  972. if(*ppAccessList == NULL)
  973. {
  974. return(ERROR_NOT_ENOUGH_MEMORY);
  975. }
  976. dwErr = (*ppAccessList)->SetObjectType(ObjectType);
  977. for(ULONG iIndex = 0; iIndex < cProps && dwErr == ERROR_SUCCESS; iIndex++)
  978. {
  979. //
  980. // Now, do the read
  981. //
  982. switch (ObjectType)
  983. {
  984. case SE_KERNEL_OBJECT:
  985. dwErr = GetKernelSecurityInfo(hObject,
  986. pRightsInfo,
  987. cProps,
  988. **ppAccessList);
  989. break;
  990. case SE_WMIGUID_OBJECT:
  991. dwErr = GetWmiGuidSecurityInfo(hObject,
  992. pRightsInfo,
  993. cProps,
  994. **ppAccessList);
  995. break;
  996. case SE_FILE_OBJECT:
  997. dwErr = ReadFileRights(hObject,
  998. pRightsInfo,
  999. cProps,
  1000. **ppAccessList);
  1001. break;
  1002. case SE_SERVICE:
  1003. dwErr = ReadServiceRights((SC_HANDLE)hObject,
  1004. pRightsInfo,
  1005. cProps,
  1006. **ppAccessList);
  1007. break;
  1008. case SE_PRINTER:
  1009. dwErr = ReadPrinterRights(hObject,
  1010. pRightsInfo,
  1011. cProps,
  1012. **ppAccessList);
  1013. break;
  1014. case SE_REGISTRY_KEY:
  1015. dwErr = ReadRegistryRights(hObject,
  1016. pRightsInfo,
  1017. cProps,
  1018. **ppAccessList);
  1019. break;
  1020. case SE_WINDOW_OBJECT:
  1021. dwErr = ReadWindowPropertyRights(hObject,
  1022. pRightsInfo,
  1023. cProps,
  1024. **ppAccessList);
  1025. break;
  1026. case SE_LMSHARE: // FALL THROUGH
  1027. case SE_DS_OBJECT: // FALL THROUGH
  1028. case SE_DS_OBJECT_ALL: // FALL THROUGH
  1029. dwErr = ERROR_INVALID_PARAMETER;
  1030. break;
  1031. default:
  1032. dwErr = ERROR_INVALID_PARAMETER;
  1033. break;
  1034. }
  1035. }
  1036. if (dwErr != ERROR_SUCCESS) {
  1037. delete (*ppAccessList);
  1038. *ppAccessList = 0;
  1039. }
  1040. return(dwErr);
  1041. }
  1042. //+---------------------------------------------------------------------------
  1043. //
  1044. // Function: NtProSetRightsList
  1045. //
  1046. // Synopsis: Goes through an optional access and audit list, and builds
  1047. // the required RIGHTS_INFO list
  1048. //
  1049. // Arguments: [IN pAccessList] -- Optional access list to scan
  1050. // [IN pAuditList] -- Optional audit list to scan
  1051. // [OUT pcItems] -- Where the count of items in the
  1052. // rights info list is returned
  1053. // [OUT ppRightsList] -- Where the rights list is returned
  1054. //
  1055. // Returns: ERROR_SUCCESS -- Success
  1056. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  1057. //
  1058. // Notes:
  1059. //
  1060. //----------------------------------------------------------------------------
  1061. DWORD
  1062. NtProvSetRightsList(IN OPTIONAL PACTRL_ACCESS pAccessList,
  1063. IN OPTIONAL PACTRL_AUDIT pAuditList,
  1064. OUT PULONG pcItems,
  1065. OUT PACTRL_RIGHTS_INFO *ppRightsList)
  1066. {
  1067. DWORD dwErr = ERROR_SUCCESS;
  1068. //
  1069. // Simple. We'll go through and count the number of entries we need
  1070. //
  1071. ULONG cItems = 0;
  1072. if(pAccessList == NULL)
  1073. {
  1074. if(pAuditList != NULL)
  1075. {
  1076. cItems = pAuditList->cEntries;
  1077. }
  1078. }
  1079. else
  1080. {
  1081. cItems = pAccessList->cEntries;
  1082. if(pAuditList != NULL)
  1083. {
  1084. //
  1085. // We'll make the assumption that they are all different. In that
  1086. // way, at worst, we'll allocate a few more pointers than we need
  1087. // to.
  1088. //
  1089. cItems += pAuditList->cEntries;
  1090. }
  1091. }
  1092. //
  1093. // Now, do the allocation
  1094. //
  1095. *ppRightsList = (PACTRL_RIGHTS_INFO)AccAlloc(
  1096. cItems * sizeof(ACTRL_RIGHTS_INFO));
  1097. if(*ppRightsList == NULL)
  1098. {
  1099. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1100. }
  1101. else
  1102. {
  1103. //
  1104. // Ok, now we'll copy over only the unique lists
  1105. //
  1106. *pcItems = 0;
  1107. //
  1108. // Start with the access list
  1109. //
  1110. ULONG cAccess = 0;
  1111. if(pAccessList != NULL)
  1112. {
  1113. for(ULONG iIndex = 0; iIndex < pAccessList->cEntries; iIndex++)
  1114. {
  1115. (*ppRightsList)[iIndex].pwszProperty = (PWSTR)
  1116. (pAccessList->pPropertyAccessList[iIndex].lpProperty);
  1117. (*ppRightsList)[iIndex].SeInfo = DACL_SECURITY_INFORMATION;
  1118. }
  1119. *pcItems = pAccessList->cEntries;
  1120. cAccess = pAccessList->cEntries;
  1121. }
  1122. //
  1123. // Ok, now process the audit list
  1124. //
  1125. if(pAuditList != NULL)
  1126. {
  1127. for(ULONG iIndex = 0; iIndex < pAuditList->cEntries; iIndex++)
  1128. {
  1129. //
  1130. // See if this is a new entry or not...
  1131. //
  1132. for(ULONG iChk = 0; iChk < cAccess; iChk++)
  1133. {
  1134. if(_wcsicmp((PWSTR)(pAuditList->
  1135. pPropertyAccessList[iIndex].lpProperty),
  1136. (*ppRightsList)[iChk].pwszProperty) == 0)
  1137. {
  1138. (*ppRightsList)[iIndex].SeInfo |=
  1139. SACL_SECURITY_INFORMATION;
  1140. break;
  1141. }
  1142. }
  1143. //
  1144. // Ok, if we got and didn't find the entry, add it
  1145. //
  1146. if(iChk >= cAccess)
  1147. {
  1148. (*ppRightsList)[*pcItems].pwszProperty = (PWSTR)
  1149. (pAuditList->pPropertyAccessList[iIndex].lpProperty);
  1150. (*ppRightsList)[*pcItems].SeInfo =
  1151. SACL_SECURITY_INFORMATION;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. return(dwErr);
  1157. }
  1158. //+---------------------------------------------------------------------------
  1159. //
  1160. // Function: InsertAndContinueWorkerThread
  1161. //
  1162. // Synopsis: Inserts a new worker thread info into the list, and resumes
  1163. // the worker thread
  1164. //
  1165. // Arguments: [IN pWrkrInfo] -- Worker info to insert
  1166. //
  1167. // Returns: ERROR_SUCCESS -- Success
  1168. //
  1169. // Notes:
  1170. //
  1171. //----------------------------------------------------------------------------
  1172. DWORD
  1173. InsertAndContinueWorkerThread(PNTMARTA_WRKR_INFO pWrkrInfo)
  1174. {
  1175. DWORD dwErr = ERROR_SUCCESS;
  1176. HANDLE Token = NULL;
  1177. //
  1178. // If there is a thread token, make sure we set it as our current thread token before
  1179. // we continue execution
  1180. //
  1181. if(!OpenThreadToken(GetCurrentThread(),
  1182. MAXIMUM_ALLOWED,
  1183. TRUE,
  1184. &Token))
  1185. {
  1186. dwErr = GetLastError();
  1187. //
  1188. // if not, use the process token
  1189. //
  1190. if(dwErr == ERROR_NO_TOKEN)
  1191. {
  1192. dwErr = ERROR_SUCCESS;
  1193. }
  1194. }
  1195. else
  1196. {
  1197. if(SetThreadToken(&(pWrkrInfo->hWorker),
  1198. Token) == FALSE )
  1199. {
  1200. dwErr = GetLastError();
  1201. }
  1202. }
  1203. if (dwErr == ERROR_SUCCESS)
  1204. {
  1205. RtlAcquireResourceExclusive(&gWrkrLock, TRUE);
  1206. dwErr = gWrkrList.Insert((PVOID)pWrkrInfo);
  1207. if(dwErr == ERROR_SUCCESS)
  1208. {
  1209. if(ResumeThread(pWrkrInfo->hWorker) == 0xFFFFFFFF)
  1210. {
  1211. dwErr = GetLastError();
  1212. }
  1213. }
  1214. RtlReleaseResource(&gWrkrLock);
  1215. //
  1216. // If we failed to insert or resume the thread, make sure to
  1217. // kill it
  1218. //
  1219. if(dwErr != ERROR_SUCCESS)
  1220. {
  1221. TerminateThread(pWrkrInfo->hWorker,
  1222. dwErr);
  1223. }
  1224. }
  1225. return(dwErr);
  1226. }