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.

1385 lines
45 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 hWorker = CreateThread(NULL,
  622. 0,
  623. NtProvSetAccessRightsWorkerThread,
  624. (LPVOID)pSetWrkrInfo,
  625. CREATE_SUSPENDED,
  626. &dwThreadId);
  627. if(hWorker == NULL)
  628. {
  629. dwErr = GetLastError();
  630. }
  631. else
  632. {
  633. pWrkrInfo->hWorker = hWorker;
  634. //
  635. // Now, insert the new node in the list. Note the use of the
  636. // resource, since the list is not multi-thread safe. Note the
  637. // scoping, since we need to protect the list until the thread
  638. // actually gets started
  639. //
  640. dwErr = InsertAndContinueWorkerThread(pWrkrInfo);
  641. }
  642. }
  643. if(dwErr != ERROR_SUCCESS)
  644. {
  645. //
  646. // Clean up the allocated memory
  647. //
  648. if(pSetWrkrInfo != NULL)
  649. {
  650. AccFree(pSetWrkrInfo->ppwszObjectList);
  651. }
  652. AccFree(pSetWrkrInfo);
  653. if(pWrkrInfo != NULL)
  654. {
  655. AccFree(pWrkrInfo);
  656. }
  657. }
  658. return(dwErr);
  659. }
  660. //+---------------------------------------------------------------------------
  661. //
  662. // Function: NtProvDoHandleSet
  663. //
  664. // Synopsis: Sets up the worker thread to do the SetAccessRights for the
  665. // handle based APIs
  666. //
  667. // Arguments: [IN hObject] -- Handle to the object
  668. // [IN ObjectType] -- Type of the object
  669. // [IN pSetInfo] -- List of rights infos
  670. // [IN cRightsInfos] -- Number of items in list
  671. // [IN pAccessList] -- Ptr to a CAccessList class
  672. // [IN pOwner] -- Optional. Owner to set
  673. // [IN pGroup] -- Optional. Group to set
  674. // [IN pOverlapped] -- Overlapped structure to use for
  675. // asynchronous control
  676. // [IN fSetFlags] -- Flags governing the control of
  677. // the worker thread
  678. //
  679. // Returns: ERROR_SUCCESS -- Success
  680. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  681. //
  682. // Notes:
  683. //
  684. //----------------------------------------------------------------------------
  685. DWORD
  686. NtProvDoHandleSet(IN HANDLE hObject,
  687. IN SE_OBJECT_TYPE ObjectType,
  688. IN CAccessList *pAccessList,
  689. IN PACTRL_OVERLAPPED pOverlapped,
  690. IN DWORD fSetFlags)
  691. {
  692. DWORD dwErr = ERROR_SUCCESS;
  693. //
  694. // Ok, we'll create the relevant information structures, create
  695. // the thread, and then let it go.
  696. //
  697. PNTMARTA_WRKR_INFO pWrkrInfo = NULL;
  698. PNTMARTA_SET_WRKR_INFO pSetWrkrInfo =
  699. (PNTMARTA_SET_WRKR_INFO)AccAlloc(sizeof(NTMARTA_SET_WRKR_INFO));
  700. if(pSetWrkrInfo == NULL)
  701. {
  702. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  703. }
  704. else
  705. {
  706. pSetWrkrInfo->ppwszObjectList = NULL;
  707. //
  708. // Initialize the rest of the items
  709. //
  710. pSetWrkrInfo->ObjectType = ObjectType;
  711. pSetWrkrInfo->pAccessList= pAccessList;
  712. pSetWrkrInfo->fFlags = fSetFlags |
  713. NTMARTA_DELETE_ARGS |
  714. NTMARTA_HANDLE_VALID;
  715. pSetWrkrInfo->hObject = hObject;
  716. }
  717. //
  718. // If that worked, create the new worker info struct
  719. //
  720. if(dwErr == ERROR_SUCCESS)
  721. {
  722. //
  723. // First, create a new structure
  724. //
  725. pWrkrInfo = (PNTMARTA_WRKR_INFO)AccAlloc(sizeof(NTMARTA_WRKR_INFO));
  726. if(pWrkrInfo == NULL)
  727. {
  728. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  729. }
  730. else
  731. {
  732. //
  733. // Initialize the structure members
  734. //
  735. pWrkrInfo->pOverlapped = pOverlapped;
  736. pWrkrInfo->fState = 0;
  737. pSetWrkrInfo->pWrkrInfo = pWrkrInfo;
  738. }
  739. }
  740. //
  741. // Then, create the thread, SUSPENDED. The insertion routine will send
  742. // if off.
  743. //
  744. if(dwErr == ERROR_SUCCESS)
  745. {
  746. DWORD dwThreadId;
  747. HANDLE hWorker = CreateThread(NULL,
  748. 0,
  749. NtProvSetAccessRightsWorkerThread,
  750. (LPVOID)pSetWrkrInfo,
  751. CREATE_SUSPENDED,
  752. &dwThreadId);
  753. if(hWorker == NULL)
  754. {
  755. dwErr = GetLastError();
  756. }
  757. else
  758. {
  759. pWrkrInfo->hWorker = hWorker;
  760. //
  761. // Now, insert the new node in the list. Note the use of the
  762. // resource, since the list is not multi-thread safe. Note the
  763. // scoping, since we need to protect the list until the thread
  764. // actually gets started
  765. //
  766. dwErr = InsertAndContinueWorkerThread(pWrkrInfo);
  767. }
  768. }
  769. if(dwErr != ERROR_SUCCESS)
  770. {
  771. //
  772. // Clean up the allocated memory
  773. //
  774. if(pSetWrkrInfo != NULL)
  775. {
  776. AccFree(pSetWrkrInfo->ppwszObjectList);
  777. }
  778. AccFree(pSetWrkrInfo);
  779. if(pWrkrInfo != NULL)
  780. {
  781. AccFree(pWrkrInfo);
  782. }
  783. }
  784. return(dwErr);
  785. }
  786. //+---------------------------------------------------------------------------
  787. //
  788. // Function: NtProvGetAccessListForObject
  789. //
  790. // Synopsis:
  791. //
  792. // Arguments: [IN pObjectName] -- Path to the object in question
  793. // [IN ObjectType] -- Type of the object
  794. // [IN SecurityInfo] -- What information is be obtained
  795. // [IN pwszProperty] -- Optional. The name of the
  796. // property on the object to revoke
  797. // for
  798. // [IN OUT AccList] -- The CAccessList reference to fill
  799. // [OUT ppOwner] -- Number of trustees in list
  800. // [OUT ppGroup] -- List of trustees to revoke
  801. //
  802. // Returns: ERROR_SUCCESS -- The operation succeeded
  803. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  804. //
  805. // Notes:
  806. //
  807. //----------------------------------------------------------------------------
  808. DWORD
  809. NtProvGetAccessListForObject(IN PWSTR pwszObject,
  810. IN SE_OBJECT_TYPE ObjectType,
  811. IN PACTRL_RIGHTS_INFO pRightsInfo,
  812. IN ULONG cProps,
  813. OUT CAccessList **ppAccessList)
  814. {
  815. DWORD dwErr = ERROR_SUCCESS;
  816. //
  817. // First, allocate a new class pointer
  818. //
  819. *ppAccessList = new CAccessList;
  820. if(*ppAccessList == NULL)
  821. {
  822. return(ERROR_NOT_ENOUGH_MEMORY);
  823. }
  824. dwErr = (*ppAccessList)->SetObjectType(ObjectType);
  825. for(ULONG iIndex = 0; iIndex < cProps && dwErr == ERROR_SUCCESS; iIndex++)
  826. {
  827. //
  828. // Now, do the read
  829. //
  830. switch (ObjectType)
  831. {
  832. case SE_KERNEL_OBJECT:
  833. dwErr = ReadKernelPropertyRights(pwszObject,
  834. pRightsInfo,
  835. cProps,
  836. **ppAccessList);
  837. break;
  838. case SE_WMIGUID_OBJECT:
  839. dwErr = ReadWmiGuidPropertyRights(pwszObject,
  840. pRightsInfo,
  841. cProps,
  842. **ppAccessList);
  843. break;
  844. case SE_FILE_OBJECT:
  845. dwErr = ReadFilePropertyRights(pwszObject,
  846. pRightsInfo,
  847. cProps,
  848. **ppAccessList);
  849. break;
  850. case SE_SERVICE:
  851. dwErr = ReadServicePropertyRights(pwszObject,
  852. pRightsInfo,
  853. cProps,
  854. **ppAccessList);
  855. break;
  856. case SE_PRINTER:
  857. dwErr = ReadPrinterPropertyRights(pwszObject,
  858. pRightsInfo,
  859. cProps,
  860. **ppAccessList);
  861. break;
  862. case SE_REGISTRY_KEY:
  863. dwErr = ReadRegistryPropertyRights(pwszObject,
  864. pRightsInfo,
  865. cProps,
  866. **ppAccessList);
  867. break;
  868. case SE_LMSHARE:
  869. dwErr = ReadSharePropertyRights(pwszObject,
  870. pRightsInfo,
  871. cProps,
  872. **ppAccessList);
  873. break;
  874. case SE_DS_OBJECT:
  875. #ifdef ACTRL_NEED_SET_PRIVS
  876. dwErr = SetPriv();
  877. if(dwErr == ERROR_SUCCESS)
  878. {
  879. #endif
  880. dwErr = ReadDSObjPropertyRights(pwszObject,
  881. pRightsInfo,
  882. cProps,
  883. **ppAccessList);
  884. #ifdef ACTRL_NEED_SET_PRIVS
  885. }
  886. #endif
  887. break;
  888. case SE_DS_OBJECT_ALL:
  889. #ifdef ACTRL_NEED_SET_PRIVS
  890. dwErr = SetPriv();
  891. if(dwErr == ERROR_SUCCESS)
  892. {
  893. #endif
  894. (**ppAccessList).SetDsPathInfo(NULL,
  895. (PWSTR)pwszObject);
  896. dwErr = ReadAllDSObjPropertyRights(pwszObject,
  897. pRightsInfo,
  898. cProps,
  899. **ppAccessList);
  900. #ifdef ACTRL_NEED_SET_PRIVS
  901. }
  902. #endif
  903. break;
  904. default:
  905. dwErr = ERROR_INVALID_PARAMETER;
  906. break;
  907. }
  908. }
  909. if (dwErr != ERROR_SUCCESS) {
  910. delete (*ppAccessList);
  911. *ppAccessList = 0;
  912. }
  913. return(dwErr);
  914. }
  915. //+---------------------------------------------------------------------------
  916. //
  917. // Function: NtProvGetAccessListForHandle
  918. //
  919. // Synopsis:
  920. //
  921. // Arguments: [IN hObject] -- Handle to the object
  922. // [IN ObjectType] -- Type of the object
  923. // [IN SecurityInfo] -- What information is be obtained
  924. // [IN pwszProperty] -- Optional. The name of the
  925. // property on the object to revoke
  926. // for
  927. // [IN OUT AccList] -- The CAccessList reference to fill
  928. // [OUT ppOwner] -- Number of trustees in list
  929. // [OUT ppGroup] -- List of trustees to revoke
  930. //
  931. // Returns: ERROR_SUCCESS -- The operation succeeded
  932. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  933. //
  934. // Notes:
  935. //
  936. //----------------------------------------------------------------------------
  937. DWORD
  938. NtProvGetAccessListForHandle(IN HANDLE hObject,
  939. IN SE_OBJECT_TYPE ObjectType,
  940. IN PACTRL_RIGHTS_INFO pRightsInfo,
  941. IN ULONG cProps,
  942. OUT CAccessList **ppAccessList)
  943. {
  944. DWORD dwErr = ERROR_SUCCESS;
  945. //
  946. // First, allocate a new class pointer
  947. //
  948. *ppAccessList = new CAccessList;
  949. if(*ppAccessList == NULL)
  950. {
  951. return(ERROR_NOT_ENOUGH_MEMORY);
  952. }
  953. dwErr = (*ppAccessList)->SetObjectType(ObjectType);
  954. for(ULONG iIndex = 0; iIndex < cProps && dwErr == ERROR_SUCCESS; iIndex++)
  955. {
  956. //
  957. // Now, do the read
  958. //
  959. switch (ObjectType)
  960. {
  961. case SE_KERNEL_OBJECT:
  962. dwErr = GetKernelSecurityInfo(hObject,
  963. pRightsInfo,
  964. cProps,
  965. **ppAccessList);
  966. break;
  967. case SE_WMIGUID_OBJECT:
  968. dwErr = GetWmiGuidSecurityInfo(hObject,
  969. pRightsInfo,
  970. cProps,
  971. **ppAccessList);
  972. break;
  973. case SE_FILE_OBJECT:
  974. dwErr = ReadFileRights(hObject,
  975. pRightsInfo,
  976. cProps,
  977. **ppAccessList);
  978. break;
  979. case SE_SERVICE:
  980. dwErr = ReadServiceRights((SC_HANDLE)hObject,
  981. pRightsInfo,
  982. cProps,
  983. **ppAccessList);
  984. break;
  985. case SE_PRINTER:
  986. dwErr = ReadPrinterRights(hObject,
  987. pRightsInfo,
  988. cProps,
  989. **ppAccessList);
  990. break;
  991. case SE_REGISTRY_KEY:
  992. dwErr = ReadRegistryRights(hObject,
  993. pRightsInfo,
  994. cProps,
  995. **ppAccessList);
  996. break;
  997. case SE_WINDOW_OBJECT:
  998. dwErr = ReadWindowPropertyRights(hObject,
  999. pRightsInfo,
  1000. cProps,
  1001. **ppAccessList);
  1002. break;
  1003. case SE_LMSHARE: // FALL THROUGH
  1004. case SE_DS_OBJECT: // FALL THROUGH
  1005. case SE_DS_OBJECT_ALL: // FALL THROUGH
  1006. dwErr = ERROR_INVALID_PARAMETER;
  1007. break;
  1008. default:
  1009. dwErr = ERROR_INVALID_PARAMETER;
  1010. break;
  1011. }
  1012. }
  1013. if (dwErr != ERROR_SUCCESS) {
  1014. delete (*ppAccessList);
  1015. *ppAccessList = 0;
  1016. }
  1017. return(dwErr);
  1018. }
  1019. //+---------------------------------------------------------------------------
  1020. //
  1021. // Function: NtProSetRightsList
  1022. //
  1023. // Synopsis: Goes through an optional access and audit list, and builds
  1024. // the required RIGHTS_INFO list
  1025. //
  1026. // Arguments: [IN pAccessList] -- Optional access list to scan
  1027. // [IN pAuditList] -- Optional audit list to scan
  1028. // [OUT pcItems] -- Where the count of items in the
  1029. // rights info list is returned
  1030. // [OUT ppRightsList] -- Where the rights list is returned
  1031. //
  1032. // Returns: ERROR_SUCCESS -- Success
  1033. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  1034. //
  1035. // Notes:
  1036. //
  1037. //----------------------------------------------------------------------------
  1038. DWORD
  1039. NtProvSetRightsList(IN OPTIONAL PACTRL_ACCESS pAccessList,
  1040. IN OPTIONAL PACTRL_AUDIT pAuditList,
  1041. OUT PULONG pcItems,
  1042. OUT PACTRL_RIGHTS_INFO *ppRightsList)
  1043. {
  1044. DWORD dwErr = ERROR_SUCCESS;
  1045. //
  1046. // Simple. We'll go through and count the number of entries we need
  1047. //
  1048. ULONG cItems = 0;
  1049. if(pAccessList == NULL)
  1050. {
  1051. if(pAuditList != NULL)
  1052. {
  1053. cItems = pAuditList->cEntries;
  1054. }
  1055. }
  1056. else
  1057. {
  1058. cItems = pAccessList->cEntries;
  1059. if(pAuditList != NULL)
  1060. {
  1061. //
  1062. // We'll make the assumption that they are all different. In that
  1063. // way, at worst, we'll allocate a few more pointers than we need
  1064. // to.
  1065. //
  1066. cItems += pAuditList->cEntries;
  1067. }
  1068. }
  1069. //
  1070. // Now, do the allocation
  1071. //
  1072. *ppRightsList = (PACTRL_RIGHTS_INFO)AccAlloc(
  1073. cItems * sizeof(ACTRL_RIGHTS_INFO));
  1074. if(*ppRightsList == NULL)
  1075. {
  1076. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1077. }
  1078. else
  1079. {
  1080. //
  1081. // Ok, now we'll copy over only the unique lists
  1082. //
  1083. *pcItems = 0;
  1084. //
  1085. // Start with the access list
  1086. //
  1087. ULONG cAccess = 0;
  1088. if(pAccessList != NULL)
  1089. {
  1090. for(ULONG iIndex = 0; iIndex < pAccessList->cEntries; iIndex++)
  1091. {
  1092. (*ppRightsList)[iIndex].pwszProperty = (PWSTR)
  1093. (pAccessList->pPropertyAccessList[iIndex].lpProperty);
  1094. (*ppRightsList)[iIndex].SeInfo = DACL_SECURITY_INFORMATION;
  1095. }
  1096. *pcItems = pAccessList->cEntries;
  1097. cAccess = pAccessList->cEntries;
  1098. }
  1099. //
  1100. // Ok, now process the audit list
  1101. //
  1102. if(pAuditList != NULL)
  1103. {
  1104. for(ULONG iIndex = 0; iIndex < pAuditList->cEntries; iIndex++)
  1105. {
  1106. //
  1107. // See if this is a new entry or not...
  1108. //
  1109. for(ULONG iChk = 0; iChk < cAccess; iChk++)
  1110. {
  1111. if(_wcsicmp((PWSTR)(pAuditList->
  1112. pPropertyAccessList[iIndex].lpProperty),
  1113. (*ppRightsList)[iChk].pwszProperty) == 0)
  1114. {
  1115. (*ppRightsList)[iIndex].SeInfo |=
  1116. SACL_SECURITY_INFORMATION;
  1117. break;
  1118. }
  1119. }
  1120. //
  1121. // Ok, if we got and didn't find the entry, add it
  1122. //
  1123. if(iChk >= cAccess)
  1124. {
  1125. (*ppRightsList)[*pcItems].pwszProperty = (PWSTR)
  1126. (pAuditList->pPropertyAccessList[iIndex].lpProperty);
  1127. (*ppRightsList)[*pcItems].SeInfo =
  1128. SACL_SECURITY_INFORMATION;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. return(dwErr);
  1134. }
  1135. //+---------------------------------------------------------------------------
  1136. //
  1137. // Function: InsertAndContinueWorkerThread
  1138. //
  1139. // Synopsis: Inserts a new worker thread info into the list, and resumes
  1140. // the worker thread
  1141. //
  1142. // Arguments: [IN pWrkrInfo] -- Worker info to insert
  1143. //
  1144. // Returns: ERROR_SUCCESS -- Success
  1145. //
  1146. // Notes:
  1147. //
  1148. //----------------------------------------------------------------------------
  1149. DWORD
  1150. InsertAndContinueWorkerThread(PNTMARTA_WRKR_INFO pWrkrInfo)
  1151. {
  1152. DWORD dwErr = ERROR_SUCCESS;
  1153. HANDLE Token = NULL;
  1154. //
  1155. // If there is a thread token, make sure we set it as our current thread token before
  1156. // we continue execution
  1157. //
  1158. if(!OpenThreadToken(GetCurrentThread(),
  1159. MAXIMUM_ALLOWED,
  1160. TRUE,
  1161. &Token))
  1162. {
  1163. dwErr = GetLastError();
  1164. //
  1165. // if not, use the process token
  1166. //
  1167. if(dwErr == ERROR_NO_TOKEN)
  1168. {
  1169. dwErr = ERROR_SUCCESS;
  1170. }
  1171. }
  1172. else
  1173. {
  1174. if(SetThreadToken(&(pWrkrInfo->hWorker),
  1175. Token) == FALSE )
  1176. {
  1177. dwErr = GetLastError();
  1178. }
  1179. }
  1180. if (dwErr == ERROR_SUCCESS)
  1181. {
  1182. RtlAcquireResourceExclusive(&gWrkrLock, TRUE);
  1183. dwErr = gWrkrList.Insert((PVOID)pWrkrInfo);
  1184. if(dwErr == ERROR_SUCCESS)
  1185. {
  1186. if(ResumeThread(pWrkrInfo->hWorker) == 0xFFFFFFFF)
  1187. {
  1188. dwErr = GetLastError();
  1189. }
  1190. }
  1191. RtlReleaseResource(&gWrkrLock);
  1192. //
  1193. // If we failed to insert or resume the thread, make sure to
  1194. // kill it
  1195. //
  1196. if(dwErr != ERROR_SUCCESS)
  1197. {
  1198. TerminateThread(pWrkrInfo->hWorker,
  1199. dwErr);
  1200. }
  1201. }
  1202. return(dwErr);
  1203. }