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.

2377 lines
63 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: FILE.C
  7. //
  8. // Contents: Unit test for file propagation, issues
  9. //
  10. // History: 14-Sep-96 MacM Created
  11. //
  12. // Notes:
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <aclapi.h>
  22. #include <seopaque.h>
  23. #include <ntrtl.h>
  24. #define FLAG_ON(flags,bit) ((flags) & (bit))
  25. #define DEFAULT_ACCESS ACTRL_STD_RIGHTS_ALL | ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST
  26. //
  27. // The following is the list of the directory tree to possibly be created
  28. //
  29. PWSTR gpwszTreeList[] = {L"\\dir1", L"\\dir1\\dir2",L"\\dir1\\dir3",
  30. L"\\dir1\\dir2\\dir4", L"\\dir1\\dir3\\dir5",
  31. L"\\dir1\\dir3\\dir6", L"\\dir1\\dir2\\dir4\\dir7",
  32. L"\\dir1\\dir2\\dir4\\dir7\\dir8",
  33. L"\\dir1\\dir2\\dir4\\dir7\\dir9"};
  34. PWSTR gpwszFileList[] = {L"\\dir1\\file1", L"\\dir1\\dir3\\dir6\\file2",
  35. L"\\dir1\\dir2\\dir4\\dir7\\dir9\\file3"};
  36. ULONG cTree = sizeof(gpwszTreeList) / sizeof(PWSTR);
  37. ULONG cFile = sizeof(gpwszFileList) / sizeof(PWSTR);
  38. //
  39. // Flags for tests
  40. //
  41. #define FTEST_READ 0x00000001
  42. #define FTEST_TREE 0x00000002
  43. #define FTEST_INTERRUPT 0x00000004
  44. #define FTEST_COMPRESS 0x00000008
  45. #define FTEST_NOACCESS 0x00000010
  46. #define FTEST_OPENDIR 0x00000020
  47. #define FTEST_COMPRESS2 0x00000040
  48. #define FTEST_PROTECT 0x00000080
  49. #define FTEST_GET3 0x00000100
  50. #define FTEST_GETOWNER 0x00000200
  51. #define RandomIndex(Max) (rand() % (Max))
  52. #define RandomIndexNotRoot(Max) (rand() % (Max - 1) + 1)
  53. #define HANDLE_CLOSE(h) if((h) != NULL) { CloseHandle(h); (h) = NULL;}
  54. DWORD
  55. AddAE (
  56. IN PWSTR pwszUser,
  57. IN ACCESS_RIGHTS AccessRights,
  58. IN INHERIT_FLAGS Inherit,
  59. IN ULONG fAccess,
  60. IN PACTRL_ACCESS pExistingAccess,
  61. OUT PACTRL_ACCESS *ppNewAccess
  62. )
  63. /*++
  64. Routine Description:
  65. Initialize an access entry
  66. Arguments:
  67. pwszUser - User to set
  68. AccessRights - Access rights to set
  69. Inherit - Any inheritance flags
  70. fAccess - Allowed or denied node?
  71. pExistingAccess - Access Entry to add to
  72. ppNewAccess - Where the new access is returned
  73. Return Value:
  74. ERROR_SUCCESS - Success
  75. --*/
  76. {
  77. DWORD dwErr = ERROR_SUCCESS;
  78. ACTRL_ACCESS_ENTRY AAE;
  79. BuildTrusteeWithNameW(&(AAE.Trustee),
  80. pwszUser);
  81. AAE.fAccessFlags = fAccess;
  82. AAE.Access = AccessRights;
  83. AAE.ProvSpecificAccess = 0;
  84. AAE.Inheritance = Inherit;
  85. AAE.lpInheritProperty = NULL;
  86. dwErr = SetEntriesInAccessListW(1,
  87. &AAE,
  88. GRANT_ACCESS,
  89. NULL,
  90. pExistingAccess,
  91. ppNewAccess);
  92. if(dwErr != ERROR_SUCCESS)
  93. {
  94. printf(" FAILED to add new access entry: %lu\n", dwErr);
  95. }
  96. return(dwErr);
  97. }
  98. DWORD
  99. BuildTree (
  100. IN PWSTR pwszRoot
  101. )
  102. /*++
  103. Routine Description:
  104. Builds the test tree
  105. Arguments:
  106. pwszRoot - Root directory under which to create the tree
  107. Return Value:
  108. ERROR_SUCCESS - Success
  109. --*/
  110. {
  111. DWORD dwErr = ERROR_SUCCESS;
  112. ULONG i;
  113. WCHAR wszPath[MAX_PATH + 1];
  114. HANDLE hFile;
  115. for(i = 0; i < cTree; i++)
  116. {
  117. swprintf(wszPath,
  118. L"%ws%ws",
  119. pwszRoot,
  120. gpwszTreeList[i]);
  121. //
  122. // Now, create the directory...
  123. //
  124. if(CreateDirectory(wszPath, NULL) == FALSE)
  125. {
  126. dwErr = GetLastError();
  127. break;
  128. }
  129. }
  130. //
  131. // If all of that worked, we'll create the files
  132. //
  133. for(i = 0; i < cFile && dwErr == ERROR_SUCCESS; i++)
  134. {
  135. swprintf(wszPath,
  136. L"%ws%ws",
  137. pwszRoot,
  138. gpwszFileList[i]);
  139. hFile = CreateFile(wszPath,
  140. GENERIC_WRITE,
  141. 0,
  142. NULL,
  143. CREATE_ALWAYS,
  144. FILE_ATTRIBUTE_NORMAL,
  145. NULL);
  146. if(hFile == INVALID_HANDLE_VALUE)
  147. {
  148. dwErr = GetLastError();
  149. }
  150. else
  151. {
  152. CloseHandle(hFile);
  153. }
  154. }
  155. if(dwErr != ERROR_SUCCESS)
  156. {
  157. printf("FAILED to create %ws: %lu\n",
  158. wszPath,
  159. dwErr);
  160. }
  161. return(dwErr);
  162. }
  163. DWORD
  164. DeleteTree (
  165. IN PWSTR pwszRoot
  166. )
  167. /*++
  168. Routine Description:
  169. Removes the test tree
  170. Arguments:
  171. pwszRoot - Root directory under which the tree was created
  172. Return Value:
  173. VOID
  174. --*/
  175. {
  176. ULONG i;
  177. WCHAR wszPath[MAX_PATH + 1];
  178. DWORD dwErr = ERROR_SUCCESS;
  179. for(i = cFile; i != 0 && dwErr == ERROR_SUCCESS; i--)
  180. {
  181. swprintf(wszPath,
  182. L"%ws%ws",
  183. pwszRoot,
  184. gpwszFileList[i - 1]);
  185. if(DeleteFile(wszPath) == FALSE)
  186. {
  187. dwErr = GetLastError();
  188. printf("FAILED to delete %ws: 0x%lx\n",
  189. wszPath,
  190. dwErr);
  191. break;
  192. }
  193. }
  194. for(i = cTree; i != 0 && dwErr == ERROR_SUCCESS; i--)
  195. {
  196. swprintf(wszPath,
  197. L"%ws%ws",
  198. pwszRoot,
  199. gpwszTreeList[i - 1]);
  200. if(RemoveDirectory(wszPath) == FALSE)
  201. {
  202. dwErr = GetLastError();
  203. if(dwErr == ERROR_PATH_NOT_FOUND || dwErr == ERROR_FILE_NOT_FOUND)
  204. {
  205. dwErr = ERROR_SUCCESS;
  206. }
  207. else
  208. {
  209. printf("FAILED to remove %ws: 0x%lx\n",
  210. wszPath,
  211. GetLastError());
  212. }
  213. }
  214. }
  215. return(dwErr);
  216. }
  217. VOID
  218. Usage (
  219. IN PSTR pszExe
  220. )
  221. /*++
  222. Routine Description:
  223. Displays the usage
  224. Arguments:
  225. pszExe - Name of the exe
  226. Return Value:
  227. VOID
  228. --*/
  229. {
  230. printf("%s path user [/C] [/O] [/I] [/P] [/test] [/H]\n", pszExe);
  231. printf(" where path is the root path to use\n");
  232. printf(" user is the name of a user to set access for\n");
  233. printf(" /test indicates which test to run:\n");
  234. printf(" /READ (Simple read/write)\n");
  235. printf(" /TREE (Propagation of entries through tree)\n");
  236. printf(" /INTERRUPT (Propagation interruptus and continuation)\n");
  237. printf(" /COMPRESS (Compression of access entries)\n");
  238. printf(" /NOACCESS (Propagation across a directory w/ no traverse access)\n");
  239. printf(" /OPENDIR (Propagation with the directory already open\n");
  240. printf(" /COMPRESS2 (Compression of big list of access entries)\n");
  241. printf(" /PROTECT (Protected child acls)\n");
  242. printf(" /GET3 (Get Dacl/Owner/Group)\n");
  243. printf(" /GETOWNER (Get Owner test)\n");
  244. printf(" if test is not specified, all variations are run\n");
  245. printf(" /H indicates to use the handle version of the APIs\n");
  246. printf(" /C is Container Inherit\n");
  247. printf(" /O is Object Inherit\n");
  248. printf(" /I is InheritOnly\n");
  249. printf(" /P is Inherit No Propagate\n");
  250. return;
  251. }
  252. //
  253. // Conceptually, this is a companion function for GetSecurityForPath
  254. //
  255. #define SetSecurityForPath(path,usehandle,handle,access) \
  256. (usehandle == TRUE ? \
  257. SetSecurityInfoExW(handle, \
  258. SE_FILE_OBJECT, \
  259. DACL_SECURITY_INFORMATION, \
  260. NULL, \
  261. access, \
  262. NULL, \
  263. NULL, \
  264. NULL, \
  265. NULL) : \
  266. SetNamedSecurityInfoExW(path, \
  267. SE_FILE_OBJECT, \
  268. DACL_SECURITY_INFORMATION, \
  269. NULL, \
  270. access, \
  271. NULL, \
  272. NULL, \
  273. NULL, \
  274. NULL))
  275. DWORD
  276. GetSecurityForPath (
  277. IN PWSTR pwszPath,
  278. IN BOOL fUseHandle,
  279. IN ULONG OpenFlags,
  280. OUT HANDLE *phObj,
  281. OUT PACTRL_ACCESSW *ppAccess
  282. )
  283. /*++
  284. Routine Description:
  285. Reads the dacl off the specified path
  286. Arguments:
  287. pwszPath -- Path to read
  288. fUseHandle -- Use handle or path based API
  289. OpenFlags -- Flags to use if opening the object
  290. phObj -- Handle to object
  291. ppAccess -- Where the access is returned
  292. Return Value:
  293. ERROR_SUCCESS -- Success
  294. --*/
  295. {
  296. DWORD dwErr = ERROR_SUCCESS;
  297. if(fUseHandle == TRUE)
  298. {
  299. //
  300. // Open the object
  301. //
  302. if(*phObj == NULL)
  303. {
  304. *phObj = CreateFile(pwszPath,
  305. GENERIC_READ | GENERIC_WRITE,
  306. FILE_SHARE_READ | FILE_SHARE_WRITE,
  307. NULL,
  308. OPEN_EXISTING,
  309. OpenFlags | READ_CONTROL | WRITE_DAC,
  310. NULL);
  311. if(*phObj == INVALID_HANDLE_VALUE)
  312. {
  313. dwErr = GetLastError();
  314. *phObj = NULL;
  315. }
  316. }
  317. if(dwErr == ERROR_SUCCESS)
  318. {
  319. dwErr = GetSecurityInfoExW(*phObj,
  320. SE_FILE_OBJECT,
  321. DACL_SECURITY_INFORMATION,
  322. NULL,
  323. NULL,
  324. ppAccess,
  325. NULL,
  326. NULL,
  327. NULL);
  328. if(dwErr != ERROR_SUCCESS)
  329. {
  330. HANDLE_CLOSE(*phObj);
  331. }
  332. }
  333. }
  334. else
  335. {
  336. dwErr = GetNamedSecurityInfoExW(pwszPath,
  337. SE_FILE_OBJECT,
  338. DACL_SECURITY_INFORMATION,
  339. NULL,
  340. NULL,
  341. ppAccess,
  342. NULL,
  343. NULL,
  344. NULL);
  345. if(phObj != NULL)
  346. {
  347. *phObj = NULL;
  348. }
  349. }
  350. return(dwErr);
  351. }
  352. DWORD
  353. VerifyTreeSet (
  354. IN PWSTR pwszPath,
  355. IN PWSTR pwszUser,
  356. IN INHERIT_FLAGS Inherit
  357. )
  358. /*++
  359. Routine Description:
  360. Reads the dacl off the specified path
  361. Arguments:
  362. pwszPath -- Root path to verify
  363. pwszUser -- User to verify
  364. Inherit -- Expected inheritance
  365. Return Value:
  366. ERROR_SUCCESS -- Success
  367. --*/
  368. {
  369. DWORD dwErr = ERROR_SUCCESS;
  370. WCHAR rgwszPaths[3][MAX_PATH];
  371. INT i,j;
  372. PACTRL_ACCESSW pAccess;
  373. PACTRL_ACCESS_ENTRYW pAE;
  374. BOOL fInNoP = FALSE;
  375. if(FLAG_ON(Inherit, INHERIT_NO_PROPAGATE))
  376. {
  377. fInNoP = TRUE;
  378. }
  379. //
  380. // Now, verify it...
  381. //
  382. if(fInNoP == TRUE)
  383. {
  384. i = rand() % 2 + 1;
  385. }
  386. else
  387. {
  388. i = RandomIndexNotRoot(cTree);
  389. }
  390. swprintf(rgwszPaths[0],
  391. L"%ws%ws",
  392. pwszPath,
  393. gpwszTreeList[i]);
  394. if(fInNoP == TRUE)
  395. {
  396. i = 0;
  397. }
  398. else
  399. {
  400. i = RandomIndex(cFile);
  401. }
  402. swprintf(rgwszPaths[1],
  403. L"%ws%ws",
  404. pwszPath,
  405. gpwszFileList[i]);
  406. //
  407. // Finally, if this is an inherit, no propagate, check one of the
  408. // leaf entries for non-compliance
  409. //
  410. if(fInNoP == TRUE)
  411. {
  412. i = rand() % 6 + 3;
  413. swprintf(rgwszPaths[2],
  414. L"%ws%ws",
  415. pwszPath,
  416. gpwszTreeList[i]);
  417. Inherit &= ~(SUB_CONTAINERS_AND_OBJECTS_INHERIT);
  418. }
  419. for(i = 0; i < (fInNoP == TRUE ? 3 : 2) && dwErr == ERROR_SUCCESS; i++)
  420. {
  421. //
  422. // Get the security off the node, find the entry we added, and verify
  423. // that the entry is correct
  424. //
  425. dwErr = GetSecurityForPath(rgwszPaths[i],
  426. FALSE,
  427. FILE_FLAG_BACKUP_SEMANTICS,
  428. NULL,
  429. &pAccess);
  430. if(dwErr != ERROR_SUCCESS)
  431. {
  432. printf(" FAILED to get the security for %ws: %lu\n",
  433. rgwszPaths[i], dwErr);
  434. break;
  435. }
  436. pAE = NULL;
  437. for(j = 0;
  438. j < (INT)pAccess->pPropertyAccessList[0].pAccessEntryList->cEntries;
  439. j++)
  440. {
  441. if(_wcsicmp(pwszUser,
  442. pAccess->pPropertyAccessList[0].pAccessEntryList->
  443. pAccessList[j].Trustee.ptstrName) == 0)
  444. {
  445. pAE = &(pAccess->pPropertyAccessList[0].pAccessEntryList->
  446. pAccessList[j]);
  447. break;
  448. }
  449. }
  450. if(pAE == NULL)
  451. {
  452. if((i == 0 && FLAG_ON(Inherit,SUB_CONTAINERS_ONLY_INHERIT)) ||
  453. (i == 1 && FLAG_ON(Inherit,SUB_OBJECTS_ONLY_INHERIT)))
  454. {
  455. printf(" FAILED to find entry for %ws on path %ws\n",
  456. pwszUser, rgwszPaths[i]);
  457. dwErr = ERROR_INVALID_FUNCTION;
  458. }
  459. }
  460. else
  461. {
  462. //
  463. // Verify that the info is correct
  464. //
  465. if(!FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY))
  466. {
  467. printf(" Access entry on %ws is not inherited!\n",
  468. rgwszPaths[i]);
  469. dwErr = ERROR_INVALID_FUNCTION;
  470. }
  471. if(i == 0)
  472. {
  473. if(FLAG_ON(Inherit, SUB_CONTAINERS_ONLY_INHERIT) &&
  474. !FLAG_ON(pAE->Inheritance, SUB_CONTAINERS_ONLY_INHERIT))
  475. {
  476. printf(" No container inherit on %ws!\n",
  477. rgwszPaths[i]);
  478. dwErr = ERROR_INVALID_FUNCTION;
  479. }
  480. }
  481. else if(i == 1)
  482. {
  483. if(FLAG_ON(Inherit, SUB_OBJECTS_ONLY_INHERIT) &&
  484. FLAG_ON(pAE->Inheritance, SUB_OBJECTS_ONLY_INHERIT))
  485. {
  486. printf(" Object inherit bit on object on %ws!\n",
  487. rgwszPaths[i]);
  488. dwErr = ERROR_INVALID_FUNCTION;
  489. }
  490. }
  491. else
  492. {
  493. printf(" Inherit No Propagate node found on child %ws\n",
  494. rgwszPaths[i]);
  495. dwErr = ERROR_INVALID_FUNCTION;
  496. }
  497. }
  498. if(dwErr == ERROR_SUCCESS)
  499. {
  500. printf(" Successfully verified %ws\n", rgwszPaths[i]);
  501. }
  502. LocalFree(pAccess);
  503. }
  504. return(dwErr);
  505. }
  506. DWORD
  507. DoReadTest (
  508. IN PWSTR pwszPath,
  509. IN PWSTR pwszUser,
  510. IN BOOL fDoHandle
  511. )
  512. /*++
  513. Routine Description:
  514. Does the simple read test
  515. Arguments:
  516. pwszPath -- Root path
  517. pwszUser -- User to run with
  518. fDoHandle -- If true, use the handle based APIs
  519. Return Value:
  520. ERROR_SUCCESS -- Success
  521. --*/
  522. {
  523. DWORD dwErr = ERROR_SUCCESS;
  524. WCHAR rgwszPaths[2][MAX_PATH];
  525. INT i;
  526. PACTRL_ACCESS pCurrent;
  527. PACTRL_ACCESS pNew;
  528. HANDLE hObj;
  529. ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
  530. printf("Simple read/write test\n");
  531. swprintf(rgwszPaths[0],
  532. L"%ws%ws",
  533. pwszPath,
  534. gpwszTreeList[RandomIndex(cTree)]);
  535. swprintf(rgwszPaths[1],
  536. L"%ws%ws",
  537. pwszPath,
  538. gpwszFileList[RandomIndex(cFile)]);
  539. for(i = 0; i < 2; i++)
  540. {
  541. printf(" Processing path %ws\n", rgwszPaths[i]);
  542. hObj = NULL;
  543. dwErr = GetSecurityForPath(rgwszPaths[i],
  544. fDoHandle,
  545. OpenFlags[i],
  546. &hObj,
  547. &pCurrent);
  548. if(dwErr != ERROR_SUCCESS)
  549. {
  550. printf(" FAILED to read the DACL off %ws: %lu\n",
  551. rgwszPaths[i], dwErr);
  552. }
  553. else
  554. {
  555. //
  556. // Ok, now add the entry for our user
  557. //
  558. dwErr = AddAE(pwszUser,
  559. DEFAULT_ACCESS,
  560. 0,
  561. ACTRL_ACCESS_ALLOWED,
  562. pCurrent,
  563. &pNew);
  564. if(dwErr == ERROR_SUCCESS)
  565. {
  566. //
  567. // Set it
  568. //
  569. dwErr = SetSecurityForPath(rgwszPaths[i],
  570. fDoHandle,
  571. hObj,pNew);
  572. if(dwErr != ERROR_SUCCESS)
  573. {
  574. printf(" Set FAILED: %lu\n", dwErr);
  575. }
  576. LocalFree(pNew);
  577. }
  578. //
  579. // If that worked, reread the new security, and see if it's correct
  580. //
  581. if(dwErr == ERROR_SUCCESS)
  582. {
  583. HANDLE_CLOSE(hObj);
  584. dwErr = GetSecurityForPath(rgwszPaths[i],
  585. fDoHandle,
  586. OpenFlags[i],
  587. &hObj,
  588. &pNew);
  589. if(dwErr != ERROR_SUCCESS)
  590. {
  591. printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
  592. rgwszPaths[i], dwErr);
  593. }
  594. else
  595. {
  596. //
  597. // We should only have one property, so cheat...
  598. //
  599. ULONG cExpected = 1 + pCurrent->pPropertyAccessList[0].
  600. pAccessEntryList->cEntries;
  601. ULONG cGot = pNew->pPropertyAccessList[0].
  602. pAccessEntryList->cEntries;
  603. if(cExpected != cGot)
  604. {
  605. printf(" Expected %lu entries, got %lu\n",
  606. cExpected, cGot);
  607. dwErr = ERROR_INVALID_FUNCTION;
  608. }
  609. LocalFree(pNew);
  610. }
  611. //
  612. // Restore the current security
  613. //
  614. SetNamedSecurityInfoExW(rgwszPaths[i],
  615. SE_FILE_OBJECT,
  616. DACL_SECURITY_INFORMATION,
  617. NULL,
  618. pCurrent,
  619. NULL,
  620. NULL,
  621. NULL,
  622. NULL);
  623. }
  624. LocalFree(pCurrent);
  625. }
  626. HANDLE_CLOSE(hObj);
  627. if(dwErr != ERROR_SUCCESS)
  628. {
  629. break;
  630. }
  631. }
  632. return(dwErr);
  633. }
  634. DWORD
  635. DoTreeTest (
  636. IN PWSTR pwszPath,
  637. IN PWSTR pwszUser,
  638. IN INHERIT_FLAGS Inherit,
  639. IN BOOL fDoHandle
  640. )
  641. /*++
  642. Routine Description:
  643. Does the simple tree test
  644. Arguments:
  645. pwszPath -- Root path
  646. pwszUser -- User to run with
  647. Inherit -- Inheritance flags
  648. fDoHandle -- If true, use the handle based APIs
  649. Return Value:
  650. ERROR_SUCCESS -- Success
  651. --*/
  652. {
  653. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  654. INT i,j;
  655. PACTRL_ACCESS pCurrent;
  656. PACTRL_ACCESS pNew;
  657. HANDLE hObj = NULL;
  658. WCHAR wszPath[MAX_PATH + 1];
  659. WCHAR rgwszPaths[2][MAX_PATH];
  660. PACTRL_ACCESS_ENTRYW pAE;
  661. printf("Tree propagation test\n");
  662. swprintf(wszPath,
  663. L"%ws%ws",
  664. pwszPath,
  665. gpwszTreeList[0]);
  666. //
  667. // Set the access on the root, and then we'll read the child and look for
  668. // the appropratie access
  669. //
  670. dwErr = GetSecurityForPath(wszPath,
  671. fDoHandle,
  672. FILE_FLAG_BACKUP_SEMANTICS,
  673. &hObj,
  674. &pCurrent);
  675. if(dwErr != ERROR_SUCCESS)
  676. {
  677. printf(" FAILED to get the security for %ws: %lu\n",
  678. wszPath, dwErr);
  679. return(dwErr);
  680. }
  681. //
  682. // Ok, add the access
  683. //
  684. dwErr = AddAE(pwszUser,
  685. DEFAULT_ACCESS,
  686. Inherit,
  687. ACTRL_ACCESS_ALLOWED,
  688. pCurrent,
  689. &pNew);
  690. if(dwErr == ERROR_SUCCESS)
  691. {
  692. //
  693. // Set it
  694. //
  695. dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
  696. if(dwErr != ERROR_SUCCESS)
  697. {
  698. printf("Set FAILED: %lu\n", dwErr);
  699. }
  700. LocalFree(pNew);
  701. }
  702. dwErr = VerifyTreeSet(pwszPath,
  703. pwszUser,
  704. Inherit);
  705. if(dwErr != ERROR_SUCCESS)
  706. {
  707. printf(" VerifyTreeSet FAILED with %lu\n", dwErr);
  708. }
  709. //
  710. // Restore the current security
  711. //
  712. dwErr2 = SetNamedSecurityInfoExW(wszPath,
  713. SE_FILE_OBJECT,
  714. DACL_SECURITY_INFORMATION,
  715. NULL,
  716. pCurrent,
  717. NULL,
  718. NULL,
  719. NULL,
  720. NULL);
  721. if(dwErr2 != ERROR_SUCCESS)
  722. {
  723. if(dwErr == ERROR_SUCCESS)
  724. {
  725. dwErr = dwErr2;
  726. }
  727. printf("FAILED to restore the security for %ws: %lu\n",
  728. wszPath, dwErr2);
  729. }
  730. LocalFree(pCurrent);
  731. HANDLE_CLOSE(hObj);
  732. return(dwErr);
  733. }
  734. DWORD
  735. DoInterruptTest (
  736. IN PWSTR pwszPath,
  737. IN PWSTR pwszUser,
  738. IN INHERIT_FLAGS Inherit,
  739. IN BOOL fDoHandle
  740. )
  741. /*++
  742. Routine Description:
  743. Does the interrupt tree/repeat tree test
  744. Arguments:
  745. pwszPath -- Root path
  746. pwszUser -- User to run with
  747. Inherit -- Inheritance flags
  748. fDoHandle -- If true, use the handle based APIs
  749. Return Value:
  750. ERROR_SUCCESS -- Success
  751. --*/
  752. {
  753. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  754. PACTRL_ACCESS pCurrent;
  755. PACTRL_ACCESS pNew;
  756. HANDLE hObj = NULL;
  757. WCHAR wszPath[MAX_PATH + 1];
  758. ACTRL_OVERLAPPED Overlapped;
  759. printf("Tree propagation with interruption\n");
  760. swprintf(wszPath,
  761. L"%ws%ws",
  762. pwszPath,
  763. gpwszTreeList[0]);
  764. //
  765. // Set the access on the root, and then we'll read the child and look for
  766. // the appropratie access
  767. //
  768. dwErr = GetSecurityForPath(wszPath,
  769. fDoHandle,
  770. FILE_FLAG_BACKUP_SEMANTICS,
  771. &hObj,
  772. &pCurrent);
  773. if(dwErr != ERROR_SUCCESS)
  774. {
  775. printf(" FAILED to get the security for %ws: %lu\n",
  776. wszPath, dwErr);
  777. return(dwErr);
  778. }
  779. //
  780. // Ok, add the access
  781. //
  782. dwErr = AddAE(pwszUser,
  783. DEFAULT_ACCESS,
  784. Inherit,
  785. ACTRL_ACCESS_ALLOWED,
  786. pCurrent,
  787. &pNew);
  788. if(dwErr == ERROR_SUCCESS)
  789. {
  790. //
  791. // Set it, interrupt it, and set it again
  792. //
  793. if(fDoHandle == TRUE)
  794. {
  795. dwErr = SetSecurityInfoExW(hObj,
  796. SE_FILE_OBJECT,
  797. DACL_SECURITY_INFORMATION,
  798. NULL,
  799. pNew,
  800. NULL,
  801. NULL,
  802. NULL,
  803. &Overlapped);
  804. }
  805. else
  806. {
  807. dwErr = SetNamedSecurityInfoExW(wszPath,
  808. SE_FILE_OBJECT,
  809. DACL_SECURITY_INFORMATION,
  810. NULL,
  811. pNew,
  812. NULL,
  813. NULL,
  814. NULL,
  815. &Overlapped);
  816. }
  817. //
  818. // Immeadiately cancel it...
  819. //
  820. if(dwErr == ERROR_SUCCESS)
  821. {
  822. WaitForSingleObject(Overlapped.hEvent,
  823. 100);
  824. dwErr = CancelOverlappedAccess(&Overlapped);
  825. if(dwErr != ERROR_SUCCESS)
  826. {
  827. printf("Cancel FAILED with %lu\n", dwErr);
  828. }
  829. }
  830. //
  831. // Now, reset it and verify it
  832. //
  833. if(dwErr == ERROR_SUCCESS)
  834. {
  835. dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
  836. if(dwErr != ERROR_SUCCESS)
  837. {
  838. printf("Set FAILED: %lu\n", dwErr);
  839. }
  840. }
  841. LocalFree(pNew);
  842. }
  843. dwErr = VerifyTreeSet(pwszPath,
  844. pwszUser,
  845. Inherit);
  846. if(dwErr != ERROR_SUCCESS)
  847. {
  848. printf(" VerifyTreeSet FAILED with %lu\n", dwErr);
  849. }
  850. //
  851. // Restore the current security
  852. //
  853. dwErr2 = SetNamedSecurityInfoExW(wszPath,
  854. SE_FILE_OBJECT,
  855. DACL_SECURITY_INFORMATION,
  856. NULL,
  857. pCurrent,
  858. NULL,
  859. NULL,
  860. NULL,
  861. NULL);
  862. if(dwErr2 != ERROR_SUCCESS)
  863. {
  864. if(dwErr == ERROR_SUCCESS)
  865. {
  866. dwErr = dwErr2;
  867. }
  868. printf("FAILED to restore the security for %ws: %lu\n",
  869. wszPath, dwErr2);
  870. }
  871. LocalFree(pCurrent);
  872. HANDLE_CLOSE(hObj);
  873. return(dwErr);
  874. }
  875. DWORD
  876. DoCompressTest (
  877. IN PWSTR pwszPath,
  878. IN PWSTR pwszUser,
  879. IN BOOL fDoHandle
  880. )
  881. /*++
  882. Routine Description:
  883. Does the entry compression test
  884. Arguments:
  885. pwszPath -- Root path
  886. pwszUser -- User to run with
  887. fDoHandle -- Do the handle based API
  888. Return Value:
  889. ERROR_SUCCESS -- Success
  890. --*/
  891. {
  892. DWORD dwErr = ERROR_SUCCESS;
  893. WCHAR rgwszPaths[2][MAX_PATH];
  894. INT i,j;
  895. ULONG cOrigCnt;
  896. PACTRL_ACCESS pCurrent;
  897. PACTRL_ACCESS pNew;
  898. HANDLE hObj;
  899. ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
  900. ACCESS_RIGHTS Rights[] = {ACTRL_DELETE,
  901. ACTRL_READ_CONTROL,
  902. ACTRL_CHANGE_ACCESS,
  903. ACTRL_CHANGE_OWNER,
  904. ACTRL_SYNCHRONIZE,
  905. ACTRL_STD_RIGHTS_ALL};
  906. printf("Entry compression test\n");
  907. swprintf(rgwszPaths[0],
  908. L"%ws%ws",
  909. pwszPath,
  910. gpwszTreeList[RandomIndex(cTree)]);
  911. swprintf(rgwszPaths[1],
  912. L"%ws%ws",
  913. pwszPath,
  914. gpwszFileList[RandomIndex(cFile)]);
  915. for(i = 0; i < 2; i++)
  916. {
  917. cOrigCnt = 0;
  918. printf(" Processing path %ws\n", rgwszPaths[i]);
  919. for(j = 0; j < sizeof(Rights) / sizeof(ACCESS_RIGHTS); j++)
  920. {
  921. hObj = NULL;
  922. printf(" Processing right 0x%lx\n", Rights[j]);
  923. dwErr = GetSecurityForPath(rgwszPaths[i],
  924. fDoHandle,
  925. OpenFlags[i],
  926. &hObj,
  927. &pCurrent);
  928. if(dwErr != ERROR_SUCCESS)
  929. {
  930. printf(" FAILED to read the DACL off %ws: %lu\n",
  931. rgwszPaths[i], dwErr);
  932. }
  933. else
  934. {
  935. if(cOrigCnt == 0)
  936. {
  937. cOrigCnt = pCurrent->pPropertyAccessList[0].
  938. pAccessEntryList->cEntries;
  939. }
  940. //
  941. // Ok, now add the entry for our user
  942. //
  943. dwErr = AddAE(pwszUser,
  944. Rights[0] | ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST,
  945. 0,
  946. ACTRL_ACCESS_ALLOWED,
  947. pCurrent,
  948. &pNew);
  949. if(dwErr == ERROR_SUCCESS)
  950. {
  951. //
  952. // Set it
  953. //
  954. dwErr = SetSecurityForPath(rgwszPaths[i], fDoHandle,
  955. hObj, pNew);
  956. if(dwErr != ERROR_SUCCESS)
  957. {
  958. printf("Set FAILED: %lu\n", dwErr);
  959. }
  960. LocalFree(pNew);
  961. }
  962. //
  963. // If that worked, reread the new security, and see if it's
  964. // correct
  965. //
  966. if(dwErr == ERROR_SUCCESS)
  967. {
  968. HANDLE_CLOSE(hObj);
  969. dwErr = GetSecurityForPath(rgwszPaths[i],
  970. fDoHandle,
  971. OpenFlags[i],
  972. &hObj,
  973. &pNew);
  974. if(dwErr != ERROR_SUCCESS)
  975. {
  976. printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
  977. rgwszPaths[i], dwErr);
  978. }
  979. else
  980. {
  981. //
  982. // We should only have one property, so cheat...
  983. //
  984. ULONG cGot = pNew->pPropertyAccessList[0].
  985. pAccessEntryList->cEntries;
  986. if(cOrigCnt + 1 != cGot)
  987. {
  988. printf(" Expected %lu entries, got %lu\n",
  989. cOrigCnt + 1, cGot);
  990. dwErr = ERROR_INVALID_FUNCTION;
  991. }
  992. LocalFree(pNew);
  993. }
  994. //
  995. // Restore the current security
  996. //
  997. SetNamedSecurityInfoExW(rgwszPaths[i],
  998. SE_FILE_OBJECT,
  999. DACL_SECURITY_INFORMATION,
  1000. NULL,
  1001. pCurrent,
  1002. NULL,
  1003. NULL,
  1004. NULL,
  1005. NULL);
  1006. }
  1007. LocalFree(pCurrent);
  1008. }
  1009. HANDLE_CLOSE(hObj);
  1010. if(dwErr != ERROR_SUCCESS)
  1011. {
  1012. break;
  1013. }
  1014. }
  1015. }
  1016. return(dwErr);
  1017. }
  1018. DWORD
  1019. DoCompress2Test (
  1020. IN PWSTR pwszPath,
  1021. IN PWSTR pwszUser,
  1022. IN BOOL fDoHandle
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. Does the big list entry compression test
  1027. Arguments:
  1028. pwszPath -- Root path
  1029. pwszUser -- User to run with
  1030. fDoHandle -- Do the handle based API
  1031. Return Value:
  1032. ERROR_SUCCESS -- Success
  1033. --*/
  1034. {
  1035. DWORD dwErr = ERROR_SUCCESS;
  1036. WCHAR rgwszPaths[2][MAX_PATH];
  1037. INT i,j;
  1038. ULONG cOrigCnt;
  1039. PACTRL_ACCESS pCurrent;
  1040. PACTRL_ACCESS pNew;
  1041. HANDLE hObj;
  1042. ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
  1043. ACCESS_RIGHTS Rights[] = {ACTRL_DELETE,
  1044. ACTRL_READ_CONTROL,
  1045. ACTRL_CHANGE_ACCESS,
  1046. ACTRL_CHANGE_OWNER,
  1047. ACTRL_SYNCHRONIZE,
  1048. ACTRL_STD_RIGHTS_ALL,
  1049. ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST};
  1050. INT cItems = sizeof(Rights) / sizeof(ACCESS_RIGHTS);
  1051. ACTRL_ACCESS_ENTRY AAEList[sizeof(Rights) / sizeof(ACCESS_RIGHTS)];
  1052. PACTRL_ACCESS_ENTRY pAE;
  1053. printf("Entry compression test\n");
  1054. swprintf(rgwszPaths[0],
  1055. L"%ws%ws",
  1056. pwszPath,
  1057. gpwszTreeList[RandomIndex(cTree)]);
  1058. swprintf(rgwszPaths[1],
  1059. L"%ws%ws",
  1060. pwszPath,
  1061. gpwszFileList[RandomIndex(cFile)]);
  1062. for(i = 0; i < 2; i++)
  1063. {
  1064. printf(" Processing path %ws\n", rgwszPaths[i]);
  1065. cOrigCnt = 0;
  1066. hObj = NULL;
  1067. dwErr = GetSecurityForPath(rgwszPaths[i],
  1068. fDoHandle,
  1069. OpenFlags[i],
  1070. &hObj,
  1071. &pCurrent);
  1072. if(dwErr != ERROR_SUCCESS)
  1073. {
  1074. printf(" FAILED to read the DACL off %ws: %lu\n",
  1075. rgwszPaths[i], dwErr);
  1076. }
  1077. else
  1078. {
  1079. if(cOrigCnt == 0)
  1080. {
  1081. cOrigCnt = pCurrent->pPropertyAccessList[0].
  1082. pAccessEntryList->cEntries;
  1083. }
  1084. //
  1085. // Ok, now add the entries for our user
  1086. //
  1087. for(j = 0; j < sizeof(Rights) / sizeof(ACCESS_RIGHTS); j++)
  1088. {
  1089. printf(" Processing right 0x%lx\n", Rights[j]);
  1090. BuildTrusteeWithNameW(&(AAEList[j].Trustee),
  1091. pwszUser);
  1092. AAEList[j].fAccessFlags = ACTRL_ACCESS_ALLOWED;
  1093. AAEList[j].Access = Rights[j];
  1094. AAEList[j].ProvSpecificAccess = 0;
  1095. AAEList[j].Inheritance = 0;
  1096. AAEList[j].lpInheritProperty = NULL;
  1097. }
  1098. //
  1099. // Now, add 'em
  1100. //
  1101. dwErr = SetEntriesInAccessListW(cItems,
  1102. AAEList,
  1103. GRANT_ACCESS,
  1104. NULL,
  1105. pCurrent,
  1106. &pNew);
  1107. if(dwErr == ERROR_SUCCESS)
  1108. {
  1109. //
  1110. // Set it
  1111. //
  1112. dwErr = SetSecurityForPath(rgwszPaths[i], fDoHandle,
  1113. hObj, pNew);
  1114. if(dwErr != ERROR_SUCCESS)
  1115. {
  1116. printf("Set FAILED: %lu\n", dwErr);
  1117. }
  1118. LocalFree(pNew);
  1119. }
  1120. //
  1121. // If that worked, reread the new security, and see if it's
  1122. // correct
  1123. //
  1124. if(dwErr == ERROR_SUCCESS)
  1125. {
  1126. HANDLE_CLOSE(hObj);
  1127. dwErr = GetSecurityForPath(rgwszPaths[i],
  1128. fDoHandle,
  1129. OpenFlags[i],
  1130. &hObj,
  1131. &pNew);
  1132. if(dwErr != ERROR_SUCCESS)
  1133. {
  1134. printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
  1135. rgwszPaths[i], dwErr);
  1136. }
  1137. else
  1138. {
  1139. //
  1140. // We should only have one property, so cheat...
  1141. //
  1142. ULONG cGot = pNew->pPropertyAccessList[0].
  1143. pAccessEntryList->cEntries;
  1144. if(cOrigCnt + 1 != cGot)
  1145. {
  1146. printf(" Expected %lu entries, got %lu\n",
  1147. cOrigCnt + 1, cGot);
  1148. dwErr = ERROR_INVALID_FUNCTION;
  1149. }
  1150. else
  1151. {
  1152. //
  1153. // Find the added entry...
  1154. //
  1155. pAE = NULL;
  1156. for(j = 0;
  1157. j < (INT)pNew->pPropertyAccessList[0].
  1158. pAccessEntryList->cEntries;
  1159. j++)
  1160. {
  1161. if(_wcsicmp(pwszUser,
  1162. pNew->pPropertyAccessList[0].
  1163. pAccessEntryList->pAccessList[j].
  1164. Trustee.ptstrName) == 0)
  1165. {
  1166. pAE = &(pNew->pPropertyAccessList[0].
  1167. pAccessEntryList->pAccessList[j]);
  1168. break;
  1169. }
  1170. }
  1171. if(pAE == NULL)
  1172. {
  1173. printf(" Couldn't find entry for %ws\n", pwszUser);
  1174. dwErr = ERROR_INVALID_FUNCTION;
  1175. }
  1176. else
  1177. {
  1178. ACCESS_RIGHTS ExpectedAR = 0;
  1179. for(j = 0; j < cItems; j++)
  1180. {
  1181. ExpectedAR |= Rights[j];
  1182. }
  1183. if(pAE->Access != ExpectedAR)
  1184. {
  1185. printf(" Expected compressed rights of 0x%lx, not 0x%lx\n",
  1186. ExpectedAR, pAE->Access);
  1187. dwErr = ERROR_INVALID_FUNCTION;
  1188. }
  1189. }
  1190. }
  1191. LocalFree(pNew);
  1192. }
  1193. //
  1194. // Restore the current security
  1195. //
  1196. SetNamedSecurityInfoExW(rgwszPaths[i],
  1197. SE_FILE_OBJECT,
  1198. DACL_SECURITY_INFORMATION,
  1199. NULL,
  1200. pCurrent,
  1201. NULL,
  1202. NULL,
  1203. NULL,
  1204. NULL);
  1205. }
  1206. LocalFree(pCurrent);
  1207. }
  1208. HANDLE_CLOSE(hObj);
  1209. if(dwErr != ERROR_SUCCESS)
  1210. {
  1211. break;
  1212. }
  1213. }
  1214. return(dwErr);
  1215. }
  1216. DWORD
  1217. DoNoAccessTest (
  1218. IN PWSTR pwszPath,
  1219. IN PWSTR pwszUser,
  1220. IN INHERIT_FLAGS Inherit,
  1221. IN BOOL fDoHandle
  1222. )
  1223. /*++
  1224. Routine Description:
  1225. Does the NoAccess tree test, where some child node does not have access
  1226. to its children
  1227. Arguments:
  1228. pwszPath -- Root path
  1229. pwszUser -- User to run with
  1230. Inherit -- Inheritance flags
  1231. fDoHandle -- If true, use the handle based APIs
  1232. Return Value:
  1233. ERROR_SUCCESS -- Success
  1234. --*/
  1235. {
  1236. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  1237. INT i,j, iChild;
  1238. PACTRL_ACCESS pCurrent;
  1239. PACTRL_ACCESS pCurrentChild;
  1240. PACTRL_ACCESS pNew;
  1241. PACTRL_ACCESS pNewChild;
  1242. HANDLE hObj = NULL;
  1243. HANDLE hChildObj = NULL;
  1244. WCHAR wszPath[MAX_PATH + 1];
  1245. WCHAR wszChildPath[MAX_PATH + 1];
  1246. WCHAR rgwszPaths[2][MAX_PATH];
  1247. PACTRL_ACCESS_ENTRYW pAE;
  1248. PSECURITY_DESCRIPTOR pSD;
  1249. printf("NoAccess Tree test\n");
  1250. swprintf(wszPath,
  1251. L"%ws%ws",
  1252. pwszPath,
  1253. gpwszTreeList[0]);
  1254. iChild = RandomIndexNotRoot(cTree);
  1255. if(iChild == (INT)(cTree - 1))
  1256. {
  1257. iChild--;
  1258. }
  1259. //
  1260. // Set the access on the root, and then we'll read the child and look for
  1261. // the appropratie access
  1262. //
  1263. dwErr = GetSecurityForPath(wszPath,
  1264. fDoHandle,
  1265. FILE_FLAG_BACKUP_SEMANTICS,
  1266. &hObj,
  1267. &pCurrent);
  1268. if(dwErr != ERROR_SUCCESS)
  1269. {
  1270. printf(" FAILED to get the security for %ws: %lu\n",
  1271. wszPath, dwErr);
  1272. return(dwErr);
  1273. }
  1274. else
  1275. {
  1276. swprintf(wszChildPath,
  1277. L"%ws%ws",
  1278. pwszPath,
  1279. gpwszTreeList[iChild]);
  1280. dwErr = GetSecurityForPath(wszChildPath,
  1281. fDoHandle,
  1282. FILE_FLAG_BACKUP_SEMANTICS,
  1283. &hChildObj,
  1284. &pCurrentChild);
  1285. if(dwErr != ERROR_SUCCESS)
  1286. {
  1287. printf(" FAILED to get the security for %ws: %lu\n",
  1288. wszPath, dwErr);
  1289. HANDLE_CLOSE(hObj);
  1290. LocalFree(pCurrent);
  1291. return(dwErr);
  1292. }
  1293. }
  1294. //
  1295. // Ok, add the access to the child
  1296. //
  1297. dwErr = AddAE(L"Everyone",
  1298. ACTRL_DIR_LIST | ACTRL_DIR_TRAVERSE,
  1299. 0,
  1300. ACTRL_ACCESS_DENIED,
  1301. pCurrentChild,
  1302. &pNewChild);
  1303. if(dwErr == ERROR_SUCCESS)
  1304. {
  1305. //
  1306. // Set it
  1307. //
  1308. dwErr = SetSecurityForPath(wszChildPath,fDoHandle,hChildObj,pNewChild);
  1309. if(dwErr != ERROR_SUCCESS)
  1310. {
  1311. printf("Child set FAILED: %lu\n", dwErr);
  1312. }
  1313. LocalFree(pNewChild);
  1314. }
  1315. if(dwErr == ERROR_SUCCESS)
  1316. {
  1317. dwErr = AddAE(pwszUser,
  1318. DEFAULT_ACCESS,
  1319. Inherit,
  1320. ACTRL_ACCESS_ALLOWED,
  1321. pCurrent,
  1322. &pNew);
  1323. //
  1324. // Set it
  1325. //
  1326. if(dwErr == ERROR_SUCCESS)
  1327. {
  1328. dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
  1329. if(dwErr != ERROR_SUCCESS)
  1330. {
  1331. printf("Set returned %lu as expected\n", dwErr);
  1332. if(dwErr == ERROR_ACCESS_DENIED)
  1333. {
  1334. dwErr = ERROR_SUCCESS;
  1335. }
  1336. }
  1337. else
  1338. {
  1339. printf("Set succeeded when it should have FAILED!\n");
  1340. dwErr = ERROR_INVALID_FUNCTION;
  1341. }
  1342. }
  1343. LocalFree(pNew);
  1344. }
  1345. //
  1346. // Restore the current child security. Use the old APIs so we don't
  1347. // end up trying to do propagation
  1348. //
  1349. dwErr2 = ConvertAccessToSecurityDescriptor(pCurrentChild,
  1350. NULL,
  1351. NULL,
  1352. NULL,
  1353. &pSD);
  1354. if(dwErr2 == ERROR_SUCCESS)
  1355. {
  1356. if(SetFileSecurity(wszChildPath,
  1357. DACL_SECURITY_INFORMATION,
  1358. pSD) == FALSE)
  1359. {
  1360. dwErr2 = GetLastError();
  1361. printf("SetFileSecurity on %ws FAILED with %lu\n",
  1362. wszChildPath, dwErr2);
  1363. }
  1364. LocalFree(pSD);
  1365. }
  1366. else
  1367. {
  1368. printf("ConvertAccessToSecurityDescriptor FAILED with %lu\n",
  1369. dwErr2);
  1370. }
  1371. if(dwErr2 != ERROR_SUCCESS)
  1372. {
  1373. if(dwErr == ERROR_SUCCESS)
  1374. {
  1375. dwErr = dwErr2;
  1376. }
  1377. printf("FAILED to restore the security for %ws: %lu\n",
  1378. wszChildPath, dwErr2);
  1379. }
  1380. LocalFree(pCurrentChild);
  1381. //
  1382. // Restore the current security
  1383. //
  1384. dwErr2 = SetNamedSecurityInfoExW(wszPath,
  1385. SE_FILE_OBJECT,
  1386. DACL_SECURITY_INFORMATION,
  1387. NULL,
  1388. pCurrent,
  1389. NULL,
  1390. NULL,
  1391. NULL,
  1392. NULL);
  1393. if(dwErr2 != ERROR_SUCCESS)
  1394. {
  1395. if(dwErr == ERROR_SUCCESS)
  1396. {
  1397. dwErr = dwErr2;
  1398. }
  1399. printf("FAILED to restore the security for %ws: %lu\n",
  1400. wszPath, dwErr2);
  1401. }
  1402. LocalFree(pCurrent);
  1403. HANDLE_CLOSE(hObj);
  1404. HANDLE_CLOSE(hChildObj);
  1405. return(dwErr);
  1406. }
  1407. DWORD
  1408. DoOpenDirTest (
  1409. IN PWSTR pwszPath,
  1410. IN PWSTR pwszUser,
  1411. IN INHERIT_FLAGS Inherit,
  1412. IN BOOL fDoHandle
  1413. )
  1414. /*++
  1415. Routine Description:
  1416. Does the OpenDir tree test, where some child node has been opened
  1417. Arguments:
  1418. pwszPath -- Root path
  1419. pwszUser -- User to run with
  1420. Inherit -- Inheritance flags
  1421. fDoHandle -- If true, use the handle based APIs
  1422. Return Value:
  1423. ERROR_SUCCESS -- Success
  1424. --*/
  1425. {
  1426. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  1427. INT i,iChild;
  1428. PACTRL_ACCESS pCurrent;
  1429. PACTRL_ACCESS pNew;
  1430. HANDLE hObj = NULL;
  1431. HANDLE hChild = NULL;
  1432. WCHAR wszPath[MAX_PATH + 1];
  1433. WCHAR wszChildPath[MAX_PATH + 1];
  1434. ULONG ShareFlags[] = {0, FILE_SHARE_WRITE, FILE_SHARE_READ};
  1435. PSTR rgszShareFlags[] = {"None", "Write", "Read"};
  1436. ULONG ExpectedReturn[] = {ERROR_SHARING_VIOLATION,
  1437. ERROR_SHARING_VIOLATION,
  1438. ERROR_SUCCESS};
  1439. printf("Open Directory test\n");
  1440. swprintf(wszPath,
  1441. L"%ws%ws",
  1442. pwszPath,
  1443. gpwszTreeList[0]);
  1444. iChild = RandomIndex(cTree);
  1445. //
  1446. // Set the access on the root, and then we'll read the child and look for
  1447. // the appropratie access
  1448. //
  1449. dwErr = GetSecurityForPath(wszPath,
  1450. fDoHandle,
  1451. FILE_FLAG_BACKUP_SEMANTICS,
  1452. &hObj,
  1453. &pCurrent);
  1454. if(dwErr != ERROR_SUCCESS)
  1455. {
  1456. printf(" FAILED to get the security for %ws: %lu\n",
  1457. wszPath, dwErr);
  1458. return(dwErr);
  1459. }
  1460. else
  1461. {
  1462. swprintf(wszChildPath,
  1463. L"%ws%ws",
  1464. pwszPath,
  1465. gpwszTreeList[iChild]);
  1466. }
  1467. //
  1468. // Do this through all our flags
  1469. //
  1470. for(i = 0;
  1471. i < sizeof(ShareFlags) / sizeof(ULONG) && dwErr == ERROR_SUCCESS;
  1472. i++)
  1473. {
  1474. printf(" Opening %ws with share flags %s\n",
  1475. wszChildPath, rgszShareFlags[i]);
  1476. //
  1477. // Open the child
  1478. //
  1479. hChild = CreateFile(wszChildPath,
  1480. GENERIC_READ | GENERIC_WRITE,
  1481. ShareFlags[i],
  1482. NULL,
  1483. OPEN_EXISTING,
  1484. FILE_FLAG_BACKUP_SEMANTICS,
  1485. NULL);
  1486. if(hChild == INVALID_HANDLE_VALUE)
  1487. {
  1488. dwErr = GetLastError();
  1489. }
  1490. //
  1491. // Create the new entry
  1492. //
  1493. if(dwErr == ERROR_SUCCESS)
  1494. {
  1495. dwErr = AddAE(pwszUser,
  1496. DEFAULT_ACCESS,
  1497. Inherit,
  1498. ACTRL_ACCESS_ALLOWED,
  1499. pCurrent,
  1500. &pNew);
  1501. //
  1502. // Set it
  1503. //
  1504. if(dwErr == ERROR_SUCCESS)
  1505. {
  1506. dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
  1507. if(dwErr == ExpectedReturn[i])
  1508. {
  1509. printf(" Set returned %lu as expected\n", dwErr);
  1510. dwErr = ERROR_SUCCESS;
  1511. }
  1512. else
  1513. {
  1514. printf(" Set returned an unexpected %lu instead of %lu!\n",
  1515. dwErr, ExpectedReturn[i]);
  1516. if(dwErr == ERROR_SUCCESS)
  1517. {
  1518. dwErr = ERROR_INVALID_FUNCTION;
  1519. }
  1520. }
  1521. }
  1522. LocalFree(pNew);
  1523. }
  1524. HANDLE_CLOSE(hChild);
  1525. }
  1526. //
  1527. // Restore the current security
  1528. //
  1529. dwErr2 = SetNamedSecurityInfoExW(wszPath,
  1530. SE_FILE_OBJECT,
  1531. DACL_SECURITY_INFORMATION,
  1532. NULL,
  1533. pCurrent,
  1534. NULL,
  1535. NULL,
  1536. NULL,
  1537. NULL);
  1538. if(dwErr2 != ERROR_SUCCESS)
  1539. {
  1540. if(dwErr == ERROR_SUCCESS)
  1541. {
  1542. dwErr = dwErr2;
  1543. }
  1544. printf("FAILED to restore the security for %ws: %lu\n",
  1545. wszPath, dwErr2);
  1546. }
  1547. LocalFree(pCurrent);
  1548. HANDLE_CLOSE(hObj);
  1549. return(dwErr);
  1550. }
  1551. DWORD
  1552. DoProtectedTest (
  1553. IN PWSTR pwszPath,
  1554. IN PWSTR pwszUser,
  1555. IN INHERIT_FLAGS Inherit,
  1556. IN BOOL fDoHandle
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. Does the protected child test.
  1561. Arguments:
  1562. pwszPath -- Root path
  1563. pwszUser -- User to run with
  1564. Inherit -- Inheritance flags
  1565. fDoHandle -- If true, use the handle based APIs
  1566. Return Value:
  1567. ERROR_SUCCESS -- Success
  1568. --*/
  1569. {
  1570. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  1571. WCHAR wszPath[MAX_PATH + 1];
  1572. WCHAR wszChildPath[MAX_PATH + 1];
  1573. PACTRL_ACCESS pCurrent, pCurrentChild, pNew;
  1574. HANDLE hObj = NULL;
  1575. printf("Propagation with protected child test\n");
  1576. //
  1577. // Pick a file
  1578. //
  1579. swprintf(wszChildPath,
  1580. L"%ws%ws",
  1581. pwszPath,
  1582. gpwszFileList[RandomIndex(cFile)]);
  1583. //
  1584. // Build the parent
  1585. //
  1586. wcscpy(wszPath, wszChildPath);
  1587. *(wcsrchr(wszPath, L'\\')) = L'\0';
  1588. //
  1589. // Get the current security off of both
  1590. //
  1591. dwErr = GetSecurityForPath(wszPath, fDoHandle, FILE_FLAG_BACKUP_SEMANTICS, &hObj, &pCurrent);
  1592. if(dwErr == ERROR_SUCCESS)
  1593. {
  1594. dwErr = GetSecurityForPath(wszChildPath, FALSE, 0, NULL, &pCurrentChild);
  1595. if(dwErr != ERROR_SUCCESS)
  1596. {
  1597. LocalFree(pCurrent);
  1598. }
  1599. }
  1600. if(dwErr == ERROR_SUCCESS)
  1601. {
  1602. //
  1603. // Set a NULL security descriptor on child
  1604. //
  1605. SECURITY_DESCRIPTOR SD;
  1606. InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
  1607. SetSecurityDescriptorDacl(&SD, TRUE, NULL, FALSE);
  1608. //
  1609. // Stamp it on the object directly
  1610. //
  1611. if(SetFileSecurity(wszChildPath, DACL_SECURITY_INFORMATION, &SD) == FALSE)
  1612. {
  1613. dwErr = GetLastError();
  1614. printf(" Setting NULL DACL on %ws FAILED with %lu\n", wszChildPath, dwErr);
  1615. }
  1616. }
  1617. else
  1618. {
  1619. printf(" FAILED to read the security: %lu\n", dwErr);
  1620. return(dwErr);
  1621. }
  1622. //
  1623. // Ok, now we'll set on the parent, and then look at the child
  1624. //
  1625. if(dwErr == ERROR_SUCCESS)
  1626. {
  1627. dwErr = AddAE(pwszUser,
  1628. DEFAULT_ACCESS,
  1629. Inherit,
  1630. ACTRL_ACCESS_ALLOWED,
  1631. pCurrent,
  1632. &pNew);
  1633. //
  1634. // Set it
  1635. //
  1636. if(dwErr == ERROR_SUCCESS)
  1637. {
  1638. dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
  1639. if(dwErr != ERROR_SUCCESS)
  1640. {
  1641. printf(" Setting security on %ws FAILED with %lu\n", wszPath, dwErr);
  1642. }
  1643. LocalFree(pNew);
  1644. }
  1645. }
  1646. //
  1647. // Now, if all of that worked, we'll read the security off the child, and make sure that
  1648. // it is correct
  1649. //
  1650. if(dwErr == ERROR_SUCCESS)
  1651. {
  1652. dwErr = GetSecurityForPath(wszChildPath, FALSE, 0, NULL, &pNew);
  1653. if(dwErr != ERROR_SUCCESS)
  1654. {
  1655. printf(" GetSecurity on child %ws FAILED with %lu\n", wszChildPath, dwErr);
  1656. }
  1657. else
  1658. {
  1659. //
  1660. // We should have a protected acl and an empty list
  1661. //
  1662. ASSERT(pNew->pPropertyAccessList != NULL);
  1663. if(!FLAG_ON(pNew->pPropertyAccessList[0].fListFlags, ACTRL_ACCESS_PROTECTED))
  1664. {
  1665. printf(" Child list not protected\n");
  1666. dwErr = ERROR_INVALID_FUNCTION;
  1667. }
  1668. if(pNew->pPropertyAccessList[0].pAccessEntryList != NULL)
  1669. {
  1670. printf(" Child list not NULL\n");
  1671. dwErr = ERROR_INVALID_FUNCTION;
  1672. }
  1673. }
  1674. }
  1675. //
  1676. // Restore the current security, child first
  1677. //
  1678. dwErr2 = SetNamedSecurityInfoExW(wszChildPath,
  1679. SE_FILE_OBJECT,
  1680. DACL_SECURITY_INFORMATION,
  1681. NULL,
  1682. pCurrentChild,
  1683. NULL,
  1684. NULL,
  1685. NULL,
  1686. NULL);
  1687. if(dwErr2 != ERROR_SUCCESS)
  1688. {
  1689. if(dwErr == ERROR_SUCCESS)
  1690. {
  1691. dwErr = dwErr2;
  1692. }
  1693. printf("FAILED to restore the security for %ws: %lu\n",
  1694. wszChildPath, dwErr2);
  1695. }
  1696. dwErr2 = SetNamedSecurityInfoExW(wszPath,
  1697. SE_FILE_OBJECT,
  1698. DACL_SECURITY_INFORMATION,
  1699. NULL,
  1700. pCurrent,
  1701. NULL,
  1702. NULL,
  1703. NULL,
  1704. NULL);
  1705. if(dwErr2 != ERROR_SUCCESS)
  1706. {
  1707. if(dwErr == ERROR_SUCCESS)
  1708. {
  1709. dwErr = dwErr2;
  1710. }
  1711. printf("FAILED to restore the security for %ws: %lu\n",
  1712. wszPath, dwErr2);
  1713. }
  1714. LocalFree(pCurrent);
  1715. LocalFree(pCurrentChild);
  1716. HANDLE_CLOSE(hObj);
  1717. return(dwErr);
  1718. }
  1719. DWORD
  1720. DoGet3Test (
  1721. IN PWSTR pwszPath,
  1722. IN PWSTR pwszUser,
  1723. IN BOOL fDoHandle
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. Does the simple read test
  1728. Arguments:
  1729. pwszPath -- Root path
  1730. pwszUser -- User to run with
  1731. fDoHandle -- If true, use the handle based APIs
  1732. Return Value:
  1733. ERROR_SUCCESS -- Success
  1734. --*/
  1735. {
  1736. DWORD dwErr = ERROR_SUCCESS;
  1737. WCHAR rgwszPaths[MAX_PATH];
  1738. PACTRL_ACCESS pAccessList = NULL, pAuditList = NULL;
  1739. LPWSTR lpOwner = NULL, lpGroup = NULL;
  1740. ULONG SeInfo = DACL_SECURITY_INFORMATION;
  1741. printf("Get3 Test\n");
  1742. swprintf(rgwszPaths,
  1743. L"%ws%ws",
  1744. pwszPath,
  1745. gpwszTreeList[RandomIndex(cTree)]);
  1746. printf(" Processing path %ws\n", rgwszPaths);
  1747. if(rand() % 2 == 1)
  1748. {
  1749. SeInfo |= OWNER_SECURITY_INFORMATION;
  1750. }
  1751. if(rand() % 2 == 1 || SeInfo == DACL_SECURITY_INFORMATION)
  1752. {
  1753. SeInfo |= GROUP_SECURITY_INFORMATION;
  1754. }
  1755. dwErr = GetNamedSecurityInfoEx( rgwszPaths, SE_FILE_OBJECT,
  1756. SeInfo,
  1757. NULL,NULL,&pAccessList,&pAuditList,
  1758. &lpOwner,&lpGroup);
  1759. if(dwErr != ERROR_SUCCESS)
  1760. {
  1761. printf(" FAILED: %lu\n", dwErr);
  1762. }
  1763. else
  1764. {
  1765. printf(" SeInfo: %lu\n", SeInfo);
  1766. if ((SeInfo & OWNER_SECURITY_INFORMATION) != 0) {
  1767. printf(" Owner: %ws\n", lpOwner);
  1768. LocalFree(lpOwner);
  1769. }
  1770. if ((SeInfo & GROUP_SECURITY_INFORMATION) != 0) {
  1771. printf(" Group: %ws\n", lpGroup);
  1772. LocalFree(lpGroup);
  1773. }
  1774. LocalFree(pAccessList);
  1775. LocalFree(pAuditList);
  1776. }
  1777. return(dwErr);
  1778. }
  1779. DWORD
  1780. DoGetOwnerTest (
  1781. IN PWSTR pwszPath,
  1782. IN PWSTR pwszUser,
  1783. IN BOOL fDoHandle
  1784. )
  1785. /*++
  1786. Routine Description:
  1787. Gets the owner from a file
  1788. Arguments:
  1789. pwszPath -- Root path
  1790. pwszUser -- User to run with
  1791. fDoHandle -- If true, use the handle based APIs
  1792. Return Value:
  1793. ERROR_SUCCESS -- Success
  1794. --*/
  1795. {
  1796. DWORD dwErr = ERROR_SUCCESS;
  1797. WCHAR rgwszPaths[MAX_PATH];
  1798. PACTRL_ACCESS pAccessList = NULL, pAuditList = NULL;
  1799. LPWSTR lpOwner = NULL, lpGroup = NULL;
  1800. ULONG SeInfo = DACL_SECURITY_INFORMATION;
  1801. printf("GetOwner Test\n");
  1802. swprintf(rgwszPaths,
  1803. L"%ws%ws",
  1804. pwszPath,
  1805. gpwszTreeList[RandomIndex(cTree)]);
  1806. printf(" Processing path %ws\n", rgwszPaths);
  1807. dwErr = GetNamedSecurityInfoEx( rgwszPaths, SE_FILE_OBJECT,
  1808. OWNER_SECURITY_INFORMATION,
  1809. NULL,NULL,&pAccessList,&pAuditList,
  1810. &lpOwner,&lpGroup);
  1811. if(dwErr != ERROR_SUCCESS)
  1812. {
  1813. printf(" FAILED: %lu\n", dwErr);
  1814. }
  1815. else
  1816. {
  1817. printf(" Owner: %ws\n", lpOwner);
  1818. LocalFree(lpOwner);
  1819. }
  1820. return(dwErr);
  1821. }
  1822. __cdecl main (
  1823. IN INT argc,
  1824. IN CHAR *argv[])
  1825. /*++
  1826. Routine Description:
  1827. The main
  1828. Arguments:
  1829. argc -- Count of arguments
  1830. argv -- List of arguments
  1831. Return Value:
  1832. 0 -- Success
  1833. non-0 -- Failure
  1834. --*/
  1835. {
  1836. DWORD dwErr = ERROR_SUCCESS, dwErr2;
  1837. WCHAR wszPath[MAX_PATH + 1];
  1838. WCHAR wszUser[MAX_PATH + 1];
  1839. INHERIT_FLAGS Inherit = 0;
  1840. ULONG Tests = 0;
  1841. INT i;
  1842. BOOL fHandle = FALSE;
  1843. srand((ULONG)(GetTickCount() * GetCurrentThreadId()));
  1844. if(argc < 3)
  1845. {
  1846. Usage(argv[0]);
  1847. exit(1);
  1848. }
  1849. mbstowcs(wszPath, argv[1], strlen(argv[1]) + 1);
  1850. mbstowcs(wszUser, argv[2], strlen(argv[2]) + 1);
  1851. //
  1852. // process the command line
  1853. //
  1854. for(i = 3; i < argc; i++)
  1855. {
  1856. if(_stricmp(argv[i], "/h") == 0)
  1857. {
  1858. fHandle = TRUE;
  1859. }
  1860. else if(_stricmp(argv[i],"/C") == 0)
  1861. {
  1862. Inherit |= SUB_CONTAINERS_ONLY_INHERIT;
  1863. }
  1864. else if(_stricmp(argv[i],"/O") == 0)
  1865. {
  1866. Inherit |= SUB_OBJECTS_ONLY_INHERIT;
  1867. }
  1868. else if(_stricmp(argv[i],"/I") == 0)
  1869. {
  1870. Inherit |= INHERIT_ONLY;
  1871. }
  1872. else if(_stricmp(argv[i],"/P") == 0)
  1873. {
  1874. Inherit |= INHERIT_NO_PROPAGATE;
  1875. }
  1876. else if(_stricmp(argv[i],"/READ") == 0)
  1877. {
  1878. Tests |= FTEST_READ;
  1879. }
  1880. else if(_stricmp(argv[i],"/TREE") == 0)
  1881. {
  1882. Tests |= FTEST_TREE;
  1883. }
  1884. else if(_stricmp(argv[i],"/INTERRUPT") == 0)
  1885. {
  1886. Tests |= FTEST_INTERRUPT;
  1887. }
  1888. else if(_stricmp(argv[i],"/COMPRESS") == 0)
  1889. {
  1890. Tests |= FTEST_COMPRESS;
  1891. }
  1892. else if(_stricmp(argv[i],"/NOACCESS") == 0)
  1893. {
  1894. Tests |= FTEST_NOACCESS;
  1895. }
  1896. else if(_stricmp(argv[i],"/OPENDIR") == 0)
  1897. {
  1898. Tests |= FTEST_OPENDIR;
  1899. }
  1900. else if(_stricmp(argv[i],"/COMPRESS2") == 0)
  1901. {
  1902. Tests |= FTEST_COMPRESS2;
  1903. }
  1904. else if(_stricmp(argv[i],"/PROTECT") == 0)
  1905. {
  1906. Tests |= FTEST_PROTECT;
  1907. }
  1908. else if(_stricmp(argv[i],"/GET3") == 0)
  1909. {
  1910. Tests |= FTEST_GET3;
  1911. }
  1912. else if(_stricmp(argv[i],"/GETOWNER") == 0)
  1913. {
  1914. Tests |= FTEST_GETOWNER;
  1915. }
  1916. else
  1917. {
  1918. Usage(argv[0]);
  1919. exit(1);
  1920. break;
  1921. }
  1922. }
  1923. if(Tests == 0)
  1924. {
  1925. Tests = FTEST_READ |
  1926. FTEST_TREE |
  1927. FTEST_INTERRUPT |
  1928. FTEST_COMPRESS |
  1929. FTEST_NOACCESS |
  1930. FTEST_OPENDIR |
  1931. FTEST_COMPRESS2 |
  1932. FTEST_PROTECT |
  1933. FTEST_GET3 |
  1934. FTEST_GETOWNER;
  1935. }
  1936. //
  1937. // Build the tree
  1938. //
  1939. dwErr = BuildTree(wszPath);
  1940. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_READ))
  1941. {
  1942. dwErr = DoReadTest(wszPath, wszUser, fHandle);
  1943. }
  1944. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_TREE))
  1945. {
  1946. dwErr = DoTreeTest(wszPath, wszUser, Inherit, fHandle);
  1947. }
  1948. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_INTERRUPT))
  1949. {
  1950. dwErr = DoInterruptTest(wszPath, wszUser, Inherit, fHandle);
  1951. }
  1952. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_COMPRESS))
  1953. {
  1954. dwErr = DoCompressTest(wszPath, wszUser, fHandle);
  1955. }
  1956. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_NOACCESS))
  1957. {
  1958. dwErr = DoNoAccessTest(wszPath, wszUser, Inherit, fHandle);
  1959. }
  1960. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_OPENDIR))
  1961. {
  1962. dwErr = DoOpenDirTest(wszPath, wszUser, Inherit, fHandle);
  1963. }
  1964. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_COMPRESS2))
  1965. {
  1966. dwErr = DoCompress2Test(wszPath, wszUser, fHandle);
  1967. }
  1968. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_PROTECT))
  1969. {
  1970. dwErr = DoProtectedTest(wszPath, wszUser, Inherit, fHandle);
  1971. }
  1972. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_GET3))
  1973. {
  1974. dwErr = DoGet3Test(wszPath, wszUser, fHandle);
  1975. }
  1976. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_GETOWNER))
  1977. {
  1978. dwErr = DoGetOwnerTest(wszPath, wszUser, fHandle);
  1979. }
  1980. dwErr2 = DeleteTree(wszPath);
  1981. if(dwErr2 != ERROR_SUCCESS)
  1982. {
  1983. printf("FAILED to delete the tree: %lu\n", dwErr);
  1984. if(dwErr == ERROR_SUCCESS)
  1985. {
  1986. dwErr = dwErr2;
  1987. }
  1988. }
  1989. printf("%s\n", dwErr == ERROR_SUCCESS ?
  1990. "success" :
  1991. "failed");
  1992. return(dwErr);
  1993. }