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.

2159 lines
67 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: ACLAPI.C
  7. //
  8. // Contents: Implements the drt for MARTA and Win32Ex APIs
  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 <marta.h>
  23. #include <seopaque.h>
  24. #include <ntrtl.h>
  25. #define EVERYONE L"EVERYONE"
  26. #define EVERYONE_A "EVERYONE"
  27. #define GUEST L"GUEST"
  28. #define GUEST_A "GUEST"
  29. #define GUEST_COMPARE L"GUEST"
  30. #define SYSTEM L"SYSTEM"
  31. #define SYSTEM_A "SYSTEM"
  32. #define MAX_LINE 256
  33. //
  34. // Globals
  35. //
  36. BOOL fVerbose = FALSE;
  37. //
  38. // Function prototypes
  39. //
  40. DWORD Nt4BuildW(PACL *ppAcl);
  41. DWORD Nt4BuildA(PACL *ppAcl);
  42. DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess);
  43. DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess);
  44. DWORD Nt4DrtW(PACL pAcl,
  45. PSTR pszObject,
  46. SE_OBJECT_TYPE ObjType);
  47. DWORD Nt4DrtA(PACL pAcl,
  48. PSTR pszObject,
  49. SE_OBJECT_TYPE ObjType);
  50. DWORD Nt5DrtW(PACTRL_ACCESSW pAccess,
  51. PSTR pszObject,
  52. SE_OBJECT_TYPE ObjType);
  53. DWORD Nt5DrtA(PACTRL_ACCESSA pAccess,
  54. PSTR pszObject,
  55. SE_OBJECT_TYPE ObjType);
  56. VOID
  57. ConvertAccessMaskToAccessRight(IN ACCESS_MASK AccessMask,
  58. OUT PACCESS_RIGHTS pAccessRight);
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Function: main
  62. //
  63. // Synopsis: The main
  64. //
  65. // Arguments: [IN argc] -- Count of arguments
  66. // [IN argv] -- List of arguments
  67. //
  68. // Returns: 0 -- Success
  69. // non-0 -- Failure
  70. //
  71. //----------------------------------------------------------------------------
  72. __cdecl main(INT argc, CHAR *argv[])
  73. {
  74. DWORD dwErr = ERROR_SUCCESS;
  75. PACL pNt4AclW = NULL, pNt4AclA = NULL;
  76. PACTRL_ACCESSW pNt5AccessW = NULL;
  77. PACTRL_ACCESSA pNt5AccessA = NULL;
  78. FILE *fp = NULL;
  79. SE_OBJECT_TYPE ObjType;
  80. CHAR szBuff[MAX_LINE];
  81. if (argc < 2 || argc > 3)
  82. {
  83. fprintf(stderr,"USAGE: aclexdrt input_file [verbose]\n");
  84. exit(1);
  85. }
  86. if(argc == 3)
  87. {
  88. fVerbose = TRUE;
  89. }
  90. AccProvInit(dwErr);
  91. //
  92. // Do the Nt4 style build routines
  93. //
  94. if(dwErr == ERROR_SUCCESS)
  95. {
  96. dwErr = Nt4BuildW(&pNt4AclW);
  97. }
  98. if(dwErr == ERROR_SUCCESS)
  99. {
  100. dwErr = Nt4BuildA(&pNt4AclA);
  101. }
  102. if(dwErr == ERROR_SUCCESS)
  103. {
  104. dwErr = Nt5BuildW(&pNt5AccessW);
  105. }
  106. if(dwErr == ERROR_SUCCESS)
  107. {
  108. dwErr = Nt5BuildA(&pNt5AccessA);
  109. }
  110. //
  111. // Now, open the file and process it...
  112. //
  113. if(dwErr == ERROR_SUCCESS)
  114. {
  115. fp = fopen(argv[1], "r");
  116. if(fp == NULL)
  117. {
  118. fprintf(stderr, "File %s not found\n", argv[1]);
  119. dwErr = ERROR_FILE_NOT_FOUND;
  120. }
  121. while(dwErr == ERROR_SUCCESS && fgets(szBuff, MAX_LINE, fp) != NULL)
  122. {
  123. BOOL fIsDSObj = FALSE;
  124. PSTR pszType;
  125. PSTR pszObject = strtok(szBuff, " ");
  126. if(pszObject != NULL)
  127. {
  128. pszType = strtok(NULL," \n\r\0");
  129. }
  130. if(pszObject == NULL && pszType == NULL)
  131. {
  132. continue;
  133. }
  134. else if(pszObject == NULL || pszType == NULL)
  135. {
  136. fprintf(stderr,
  137. "Invalid entry %s in input file %s\n",
  138. szBuff,
  139. argv[1]);
  140. dwErr = ERROR_INVALID_DATA;
  141. }
  142. else
  143. {
  144. if(_stricmp(pszType, "FILE") == 0)
  145. {
  146. ObjType = SE_FILE_OBJECT;
  147. }
  148. else if(_stricmp(pszType, "SERVICE") == 0)
  149. {
  150. ObjType = SE_SERVICE;
  151. }
  152. else if(_stricmp(pszType, "PRINTER") == 0)
  153. {
  154. ObjType = SE_PRINTER;
  155. }
  156. else if (_stricmp(pszType, "REGISTRY_KEY") == 0)
  157. {
  158. ObjType = SE_REGISTRY_KEY;
  159. }
  160. else if(_stricmp(pszType, "SHARE") == 0)
  161. {
  162. ObjType = SE_LMSHARE;
  163. }
  164. else if(_stricmp(pszType, "DSOBJ") == 0)
  165. {
  166. ObjType = SE_DS_OBJECT;
  167. fIsDSObj = TRUE;
  168. }
  169. else if(_stricmp(pszType, "DSOBJALL") == 0)
  170. {
  171. ObjType = SE_DS_OBJECT_ALL;
  172. fIsDSObj = TRUE;
  173. }
  174. else
  175. {
  176. fprintf(stderr, "Invalid object type %s\n", pszType);
  177. dwErr = ERROR_INVALID_DATA;
  178. }
  179. }
  180. //
  181. // If it worked, do the tests...
  182. //
  183. if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE)
  184. {
  185. dwErr = Nt4DrtW(pNt4AclW,
  186. pszObject,
  187. ObjType);
  188. }
  189. if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE)
  190. {
  191. dwErr = Nt4DrtA(pNt4AclA,
  192. pszObject,
  193. ObjType);
  194. }
  195. if(dwErr == ERROR_SUCCESS)
  196. {
  197. dwErr = Nt5DrtW(pNt5AccessW,
  198. pszObject,
  199. ObjType);
  200. }
  201. if(dwErr == ERROR_SUCCESS)
  202. {
  203. dwErr = Nt5DrtA(pNt5AccessA,
  204. pszObject,
  205. ObjType);
  206. }
  207. }
  208. if(fp != NULL)
  209. {
  210. fclose(fp);
  211. }
  212. }
  213. LocalFree(pNt4AclW);
  214. LocalFree(pNt4AclA);
  215. LocalFree(pNt5AccessW);
  216. LocalFree(pNt5AccessA);
  217. if(dwErr == ERROR_SUCCESS)
  218. {
  219. printf("Success\n");
  220. }
  221. else
  222. {
  223. printf("Failure: %lu\n", dwErr);
  224. }
  225. return(dwErr);
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Function: CompareAcls
  230. //
  231. // Synopsis: Compares 2 acls for equality
  232. //
  233. // Arguments: [pAcl1] -- First ACL
  234. // [pAcl2] -- Second ACL
  235. //
  236. // Returns: ERROR_SUCCESS -- They match
  237. // ERROR_INVALID_DATA -- They don't match
  238. //
  239. //----------------------------------------------------------------------------
  240. DWORD CompAcls(PACL pAcl1,
  241. PACL pAcl2)
  242. {
  243. DWORD dwErr = ERROR_SUCCESS;
  244. ACL_SIZE_INFORMATION AclSize1, AclSize2;
  245. ACL_REVISION_INFORMATION AclRev1, AclRev2;
  246. PKNOWN_ACE pAce1, pAce2;
  247. PSID pSid1, pSid2;
  248. DWORD iIndex;
  249. if(pAcl1 == NULL || pAcl2 == NULL)
  250. {
  251. if(pAcl1 != pAcl2)
  252. {
  253. if(fVerbose)
  254. {
  255. fprintf(stderr,"Acl %lu is NULL\n", pAcl1 == NULL ? 1 : 2);
  256. }
  257. dwErr = ERROR_INVALID_DATA;
  258. }
  259. }
  260. else
  261. {
  262. if(GetAclInformation(pAcl1,
  263. &AclRev1,
  264. sizeof(ACL_REVISION_INFORMATION),
  265. AclRevisionInformation) == FALSE ||
  266. GetAclInformation(pAcl2,
  267. &AclRev2,
  268. sizeof(ACL_REVISION_INFORMATION),
  269. AclRevisionInformation) == FALSE)
  270. {
  271. return(ERROR_INVALID_DATA);
  272. }
  273. if(GetAclInformation(pAcl1,
  274. &AclSize1,
  275. sizeof(ACL_SIZE_INFORMATION),
  276. AclSizeInformation) == FALSE ||
  277. GetAclInformation(pAcl2,
  278. &AclSize2,
  279. sizeof(ACL_SIZE_INFORMATION),
  280. AclSizeInformation) == FALSE)
  281. {
  282. return(ERROR_INVALID_DATA);
  283. }
  284. if(AclRev1.AclRevision != AclRev2.AclRevision)
  285. {
  286. if(fVerbose)
  287. {
  288. fprintf(stderr,
  289. "Revision mismatch: %lu %lu\n",
  290. AclRev1.AclRevision,
  291. AclRev2.AclRevision);
  292. }
  293. dwErr = ERROR_INVALID_DATA;
  294. }
  295. if(AclSize1.AceCount != AclSize2.AceCount)
  296. {
  297. if(fVerbose)
  298. {
  299. fprintf(stderr,
  300. "AceCount mismatch: %lu %lu\n",
  301. AclSize1.AceCount,
  302. AclSize2.AceCount);
  303. }
  304. dwErr = ERROR_INVALID_DATA;
  305. }
  306. if(AclSize1.AclBytesInUse != AclSize2.AclBytesInUse)
  307. {
  308. if(fVerbose)
  309. {
  310. fprintf(stderr,
  311. "BytesInUse mismatch: %lu %lu\n",
  312. AclSize1.AclBytesInUse,
  313. AclSize2.AclBytesInUse);
  314. }
  315. dwErr = ERROR_INVALID_DATA;
  316. }
  317. if(pAcl1->Sbz1 != pAcl2->Sbz1)
  318. {
  319. if(fVerbose)
  320. {
  321. fprintf(stderr,
  322. "Acl flags mismatch: %lu %lu\n",
  323. pAcl1->Sbz1,
  324. pAcl2->Sbz1);
  325. }
  326. dwErr = ERROR_INVALID_DATA;
  327. }
  328. if(dwErr != ERROR_SUCCESS)
  329. {
  330. return(dwErr);
  331. }
  332. //
  333. // Now, compare all of the aces
  334. //
  335. pAce1 = FirstAce(pAcl1);
  336. pAce2 = FirstAce(pAcl2);
  337. for(iIndex = 0;
  338. iIndex < pAcl1->AceCount && dwErr == ERROR_SUCCESS;
  339. iIndex++)
  340. {
  341. ACCESS_RIGHTS Rights1, Rights2;
  342. if(fVerbose)
  343. {
  344. printf("Ace %lu\n", iIndex);
  345. }
  346. if(pAce1->Header.AceType != pAce2->Header.AceType)
  347. {
  348. if(fVerbose)
  349. {
  350. fprintf(stderr,
  351. "\tAceType mismatch: %lu %lu\n",
  352. pAce1->Header.AceType,
  353. pAce2->Header.AceType);
  354. }
  355. dwErr = ERROR_INVALID_DATA;
  356. }
  357. if(pAce1->Header.AceFlags != pAce2->Header.AceFlags)
  358. {
  359. if(fVerbose)
  360. {
  361. fprintf(stderr,
  362. "\tAceType mismatch: %lu %lu\n",
  363. pAce1->Header.AceFlags,
  364. pAce2->Header.AceFlags);
  365. }
  366. dwErr = ERROR_INVALID_DATA;
  367. }
  368. if(pAce1->Header.AceSize != pAce2->Header.AceSize)
  369. {
  370. if(fVerbose)
  371. {
  372. fprintf(stderr,
  373. "\tAceType mismatch: %lu %lu\n",
  374. pAce1->Header.AceSize,
  375. pAce2->Header.AceSize);
  376. }
  377. dwErr = ERROR_INVALID_DATA;
  378. }
  379. ConvertAccessMaskToAccessRight(pAce1->Mask, &Rights1);
  380. ConvertAccessMaskToAccessRight(pAce2->Mask, &Rights2);
  381. if(Rights1 != Rights1)
  382. {
  383. if(fVerbose)
  384. {
  385. fprintf(stderr,
  386. "\tAccessMask mismatch: %lu %lu\n",
  387. Rights1,
  388. Rights2);
  389. }
  390. dwErr = ERROR_INVALID_DATA;
  391. }
  392. if(!RtlEqualSid((PSID)&(pAce1->SidStart), (PSID)&(pAce2->SidStart)))
  393. {
  394. if(fVerbose)
  395. {
  396. fprintf(stderr,
  397. "\tSids don't match\n");
  398. }
  399. dwErr = ERROR_INVALID_DATA;
  400. }
  401. pAce1 = NextAce(pAce1);
  402. pAce2 = NextAce(pAce2);
  403. }
  404. }
  405. return(dwErr);
  406. }
  407. //+---------------------------------------------------------------------------
  408. //
  409. // Function: CompStringsW
  410. //
  411. // Synopsis: Compares 2 string pointers for equality
  412. //
  413. // Arguments: [pwszStr1] -- First string
  414. // [pwszStr2] -- Second string
  415. //
  416. // Returns: ERROR_SUCCESS -- They match
  417. // ERROR_INVALID_DATA -- They don't match
  418. //
  419. //----------------------------------------------------------------------------
  420. DWORD
  421. CompStringsW(PWSTR pwszStr1, PWSTR pwszStr2)
  422. {
  423. if(pwszStr1 != NULL && pwszStr2 != NULL)
  424. {
  425. if(_wcsicmp(pwszStr1, pwszStr2) == 0)
  426. {
  427. return(ERROR_SUCCESS);
  428. }
  429. }
  430. else
  431. {
  432. if(pwszStr1 == NULL)
  433. {
  434. return(ERROR_SUCCESS);
  435. }
  436. }
  437. return(ERROR_INVALID_DATA);
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: CompStringsA
  442. //
  443. // Synopsis: Compares 2 string pointers for equality
  444. //
  445. // Arguments: [pszStr1] -- First string
  446. // [pszStr2] -- Second string
  447. //
  448. // Returns: ERROR_SUCCESS -- They match
  449. // ERROR_INVALID_DATA -- They don't match
  450. //
  451. //----------------------------------------------------------------------------
  452. DWORD
  453. CompStringsA(PSTR pszStr1, PSTR pszStr2)
  454. {
  455. if(pszStr1 != NULL && pszStr2 != NULL)
  456. {
  457. if(_stricmp(pszStr1, pszStr2) == 0)
  458. {
  459. return(ERROR_SUCCESS);
  460. }
  461. }
  462. else
  463. {
  464. if(pszStr1 == NULL)
  465. {
  466. return(ERROR_SUCCESS);
  467. }
  468. }
  469. return(ERROR_INVALID_DATA);
  470. }
  471. //+---------------------------------------------------------------------------
  472. //
  473. // Function: CompAccessW
  474. //
  475. // Synopsis: Compares 2 WIDE access lists for equality
  476. //
  477. // Arguments: [pAccess1] -- First list
  478. // [pAccess2] -- Second list
  479. //
  480. // Returns: ERROR_SUCCESS -- They match
  481. // ERROR_INVALID_DATA -- They don't match
  482. //
  483. //----------------------------------------------------------------------------
  484. DWORD CompAccessW(PACTRL_ACCESSW pAccess1,
  485. PACTRL_ACCESSW pAccess2)
  486. {
  487. DWORD dwErr = ERROR_SUCCESS;
  488. ULONG iIndex = 0;
  489. if(pAccess1 == NULL || pAccess2 == NULL)
  490. {
  491. if(pAccess1 != pAccess2)
  492. {
  493. if(fVerbose)
  494. {
  495. fprintf(stderr,"Access %lu is NULL\n",
  496. pAccess1 == NULL ? 1 : 2);
  497. }
  498. dwErr = ERROR_INVALID_DATA;
  499. }
  500. }
  501. else
  502. {
  503. PACTRL_ACCESS_ENTRY_LISTW pAAEL1;
  504. PACTRL_ACCESS_ENTRY_LISTW pAAEL2;
  505. dwErr = CompStringsW((PWSTR)pAccess1->pPropertyAccessList[0].lpProperty,
  506. (PWSTR)pAccess2->pPropertyAccessList[0].lpProperty);
  507. if(dwErr != ERROR_SUCCESS)
  508. {
  509. return(dwErr);
  510. }
  511. pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList;
  512. pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList;
  513. if(pAAEL1->cEntries != pAAEL2->cEntries)
  514. {
  515. dwErr = ERROR_INVALID_DATA;
  516. if(fVerbose)
  517. {
  518. fprintf(stderr, "cEntries: %lu %lu\n",
  519. pAAEL1->cEntries,
  520. pAAEL2->cEntries);
  521. }
  522. }
  523. else
  524. {
  525. //
  526. // Compare all of the entries
  527. //
  528. for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++)
  529. {
  530. if(_wcsicmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
  531. pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0)
  532. {
  533. if(fVerbose)
  534. {
  535. fprintf(stderr, "Trustees: %ws %ws\n",
  536. pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
  537. pAAEL2->pAccessList[iIndex].Trustee.ptstrName);
  538. }
  539. dwErr = ERROR_INVALID_DATA;
  540. continue;
  541. }
  542. if(pAAEL1->pAccessList[iIndex].fAccessFlags !=
  543. pAAEL1->pAccessList[iIndex].fAccessFlags)
  544. {
  545. if(fVerbose)
  546. {
  547. fprintf(stderr, "AccessFlags: %lu %lu\n",
  548. pAAEL1->pAccessList[iIndex].fAccessFlags,
  549. pAAEL2->pAccessList[iIndex].fAccessFlags);
  550. }
  551. dwErr = ERROR_INVALID_DATA;
  552. continue;
  553. }
  554. if(pAAEL1->pAccessList[iIndex].Access !=
  555. pAAEL1->pAccessList[iIndex].Access)
  556. {
  557. if(fVerbose)
  558. {
  559. fprintf(stderr, "Access: %lu %lu\n",
  560. pAAEL1->pAccessList[iIndex].Access,
  561. pAAEL2->pAccessList[iIndex].Access);
  562. }
  563. dwErr = ERROR_INVALID_DATA;
  564. continue;
  565. }
  566. if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess !=
  567. pAAEL1->pAccessList[iIndex].ProvSpecificAccess)
  568. {
  569. if(fVerbose)
  570. {
  571. fprintf(stderr, "ProvSpecificAccess: %lu %lu\n",
  572. pAAEL1->pAccessList[iIndex].ProvSpecificAccess,
  573. pAAEL2->pAccessList[iIndex].ProvSpecificAccess);
  574. }
  575. dwErr = ERROR_INVALID_DATA;
  576. continue;
  577. }
  578. if(pAAEL1->pAccessList[iIndex].Inheritance !=
  579. pAAEL1->pAccessList[iIndex].Inheritance)
  580. {
  581. if(fVerbose)
  582. {
  583. fprintf(stderr, "AccessFlags: %lu %lu\n",
  584. pAAEL1->pAccessList[iIndex].Inheritance,
  585. pAAEL2->pAccessList[iIndex].Inheritance);
  586. }
  587. dwErr = ERROR_INVALID_DATA;
  588. continue;
  589. }
  590. //
  591. // The inheritance property
  592. //
  593. dwErr = CompStringsW(
  594. (PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty,
  595. (PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty);
  596. if(dwErr == ERROR_SUCCESS && fVerbose)
  597. {
  598. printf("AccessEntry %lu\n", iIndex);
  599. }
  600. }
  601. }
  602. }
  603. return(dwErr);
  604. }
  605. //+---------------------------------------------------------------------------
  606. //
  607. // Function: CompAccessA
  608. //
  609. // Synopsis: Compares 2 ANSI access lists for equality
  610. //
  611. // Arguments: [pAccess1] -- First list
  612. // [pAccess2] -- Second list
  613. //
  614. // Returns: ERROR_SUCCESS -- They match
  615. // ERROR_INVALID_DATA -- They don't match
  616. //
  617. //----------------------------------------------------------------------------
  618. DWORD CompAccessA(PACTRL_ACCESSA pAccess1,
  619. PACTRL_ACCESSA pAccess2)
  620. {
  621. DWORD dwErr = ERROR_SUCCESS;
  622. ULONG iIndex = 0;
  623. if(pAccess1 == NULL || pAccess2 == NULL)
  624. {
  625. if(pAccess1 != pAccess2)
  626. {
  627. if(fVerbose)
  628. {
  629. fprintf(stderr,"Access %lu is NULL\n",
  630. pAccess1 == NULL ? 1 : 2);
  631. }
  632. dwErr = ERROR_INVALID_DATA;
  633. }
  634. }
  635. else
  636. {
  637. PACTRL_ACCESS_ENTRY_LISTA pAAEL1;
  638. PACTRL_ACCESS_ENTRY_LISTA pAAEL2;
  639. dwErr = CompStringsA((PSTR)pAccess1->pPropertyAccessList[0].lpProperty,
  640. (PSTR)pAccess2->pPropertyAccessList[0].lpProperty);
  641. if(dwErr != ERROR_SUCCESS)
  642. {
  643. return(dwErr);
  644. }
  645. pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList;
  646. pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList;
  647. if(pAAEL1->cEntries != pAAEL2->cEntries)
  648. {
  649. dwErr = ERROR_INVALID_DATA;
  650. if(fVerbose)
  651. {
  652. fprintf(stderr, "cEntries: %lu %lu\n",
  653. pAAEL1->cEntries,
  654. pAAEL2->cEntries);
  655. }
  656. }
  657. else
  658. {
  659. //
  660. // Compare all of the entries
  661. //
  662. for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++)
  663. {
  664. if(_stricmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
  665. pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0)
  666. {
  667. if(fVerbose)
  668. {
  669. fprintf(stderr, "Trustees: %ws %ws\n",
  670. pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
  671. pAAEL2->pAccessList[iIndex].Trustee.ptstrName);
  672. }
  673. dwErr = ERROR_INVALID_DATA;
  674. continue;
  675. }
  676. if(pAAEL1->pAccessList[iIndex].fAccessFlags !=
  677. pAAEL1->pAccessList[iIndex].fAccessFlags)
  678. {
  679. if(fVerbose)
  680. {
  681. fprintf(stderr, "AccessFlags: %lu %lu\n",
  682. pAAEL1->pAccessList[iIndex].fAccessFlags,
  683. pAAEL2->pAccessList[iIndex].fAccessFlags);
  684. }
  685. dwErr = ERROR_INVALID_DATA;
  686. continue;
  687. }
  688. if(pAAEL1->pAccessList[iIndex].Access !=
  689. pAAEL1->pAccessList[iIndex].Access)
  690. {
  691. if(fVerbose)
  692. {
  693. fprintf(stderr, "Access: %lu %lu\n",
  694. pAAEL1->pAccessList[iIndex].Access,
  695. pAAEL2->pAccessList[iIndex].Access);
  696. }
  697. dwErr = ERROR_INVALID_DATA;
  698. continue;
  699. }
  700. if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess !=
  701. pAAEL1->pAccessList[iIndex].ProvSpecificAccess)
  702. {
  703. if(fVerbose)
  704. {
  705. fprintf(stderr, "ProvSpecificAccess: %lu %lu\n",
  706. pAAEL1->pAccessList[iIndex].ProvSpecificAccess,
  707. pAAEL2->pAccessList[iIndex].ProvSpecificAccess);
  708. }
  709. dwErr = ERROR_INVALID_DATA;
  710. continue;
  711. }
  712. if(pAAEL1->pAccessList[iIndex].Inheritance !=
  713. pAAEL1->pAccessList[iIndex].Inheritance)
  714. {
  715. if(fVerbose)
  716. {
  717. fprintf(stderr, "AccessFlags: %lu %lu\n",
  718. pAAEL1->pAccessList[iIndex].Inheritance,
  719. pAAEL2->pAccessList[iIndex].Inheritance);
  720. }
  721. dwErr = ERROR_INVALID_DATA;
  722. continue;
  723. }
  724. //
  725. // The inheritance property
  726. //
  727. dwErr = CompStringsA(
  728. (PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty,
  729. (PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty);
  730. if(dwErr == ERROR_SUCCESS && fVerbose)
  731. {
  732. printf("AccessEntry %lu\n", iIndex);
  733. }
  734. }
  735. }
  736. }
  737. return(dwErr);
  738. }
  739. //+---------------------------------------------------------------------------
  740. //
  741. // Function: DumpAccessW
  742. //
  743. // Synopsis: Dumps an ACTRL_ACCESSW structure to the screen
  744. //
  745. // Arguments: [pAccess] -- Structure to dump
  746. //
  747. // Returns: VOID
  748. //
  749. //----------------------------------------------------------------------------
  750. VOID
  751. DumpAccessW(PACTRL_ACCESSW pAccess)
  752. {
  753. if(fVerbose)
  754. {
  755. ULONG iProp, iEnt;
  756. printf("\tEntries: %lu\n", pAccess->cEntries);
  757. for(iProp = 0; iProp < pAccess->cEntries; iProp++)
  758. {
  759. printf("\t\tProperty: %ws\n",
  760. pAccess->pPropertyAccessList[iProp].lpProperty == NULL ?
  761. L"NULL" :
  762. pAccess->pPropertyAccessList[iProp].lpProperty);
  763. printf("\t\tFlags: %lu\n",
  764. pAccess->pPropertyAccessList[iProp].fListFlags);
  765. if(pAccess->pPropertyAccessList[iProp].pAccessEntryList == NULL)
  766. {
  767. printf("\t\tpAccessEntryList: NULL\n");
  768. }
  769. else
  770. {
  771. PACTRL_ACCESS_ENTRYW pAE= pAccess->pPropertyAccessList[iProp].
  772. pAccessEntryList->pAccessList;
  773. printf("\t\t\tcEntries: %lu\n",
  774. pAccess->pPropertyAccessList[iProp].pAccessEntryList->
  775. cEntries);
  776. for(iEnt = 0;
  777. iEnt < pAccess->pPropertyAccessList[iProp].
  778. pAccessEntryList->cEntries;
  779. iEnt++)
  780. {
  781. printf("\t\t\tEntry %lu:\n", iEnt);
  782. printf("\t\t\t\tTrustee.Name: %ws\n",
  783. pAE[iEnt].Trustee.ptstrName);
  784. printf("\t\t\t\tfAccessFlags: %lu\n",
  785. pAE[iEnt].fAccessFlags);
  786. printf("\t\t\t\tAccess: 0x%lx\n", pAE[iEnt].Access);
  787. printf("\t\t\t\tProvSpecificAccess: %lu\n",
  788. pAE[iEnt].ProvSpecificAccess);
  789. printf("\t\t\t\tInheritance: %lu\n", pAE[iEnt].Inheritance);
  790. printf("\t\t\t\tlpInheritProperty: %ws\n",
  791. pAE[iEnt].lpInheritProperty == NULL ?
  792. L"" :
  793. pAE[iEnt].lpInheritProperty);
  794. }
  795. }
  796. }
  797. }
  798. }
  799. #define BUILD_COUNT 5
  800. //+---------------------------------------------------------------------------
  801. //
  802. // Function: Nt4BuildW
  803. //
  804. // Synopsis: Builds an ACL using the NT4 API WIDE apis
  805. //
  806. // Arguments: [ppAcl] -- Acl to build
  807. //
  808. // Returns: ERROR_SUCCESS -- Everything worked
  809. // ERROR_INVALID_DATA -- One of the compares failed
  810. //
  811. //----------------------------------------------------------------------------
  812. DWORD Nt4BuildW(PACL *ppAcl)
  813. {
  814. DWORD dwErr = ERROR_SUCCESS;
  815. ULONG cCount;
  816. EXPLICIT_ACCESS_W EAW;
  817. PEXPLICIT_ACCESS_W pEAW;
  818. PACL pAcl = NULL, pNewAcl;
  819. ULONG iIndex, iVer;
  820. PWSTR rgTrustees[BUILD_COUNT] = {EVERYONE,
  821. SYSTEM,
  822. GUEST,
  823. EVERYONE,
  824. SYSTEM};
  825. DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8,
  826. GENERIC_ALL,
  827. GENERIC_ALL | 0x8,
  828. GENERIC_ALL | 0x8,
  829. 0};
  830. ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS,
  831. DENY_ACCESS,
  832. SET_ACCESS,
  833. SET_ACCESS,
  834. REVOKE_ACCESS};
  835. DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE,
  836. NO_INHERITANCE,
  837. SUB_CONTAINERS_AND_OBJECTS_INHERIT,
  838. NO_INHERITANCE,
  839. SUB_CONTAINERS_AND_OBJECTS_INHERIT};
  840. DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
  841. {2, 1, 0},
  842. {3, 1, 2, 0},
  843. {3, 1, 3, 2},
  844. {2, 3, 2}};
  845. if(fVerbose)
  846. {
  847. printf("Nt4BuildW\n");
  848. }
  849. //
  850. // We'll do this in a loop, since we have BUILD_COUNT different builds to do
  851. //
  852. for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
  853. {
  854. //
  855. // Build the new entry
  856. //
  857. BuildExplicitAccessWithNameW(&EAW,
  858. rgTrustees[iIndex],
  859. rgAccess[iIndex],
  860. rgMode[iIndex],
  861. rgInherit[iIndex]);
  862. dwErr = SetEntriesInAclW(1,
  863. &EAW,
  864. pAcl,
  865. &pNewAcl);
  866. if(dwErr == ERROR_SUCCESS)
  867. {
  868. LocalFree(pAcl);
  869. pAcl = pNewAcl;
  870. //
  871. // Get the explicit entries, and we'll verify them...
  872. //
  873. dwErr = GetExplicitEntriesFromAclW(pAcl,
  874. &cCount,
  875. &pEAW);
  876. if(dwErr == ERROR_SUCCESS)
  877. {
  878. PDWORD pSrch = rgSrch[iIndex];
  879. ULONG cExpected = pSrch[0];
  880. if(cCount != cExpected)
  881. {
  882. dwErr = ERROR_INVALID_DATA;
  883. if(fVerbose)
  884. {
  885. printf("\tCount mismatched: %lu, expected %lu\n",
  886. cCount,
  887. cExpected);
  888. }
  889. }
  890. else
  891. {
  892. //
  893. // verify the rest of the data
  894. //
  895. for(iVer = 0; iVer < cExpected; iVer++)
  896. {
  897. ULONG iSrch = pSrch[iVer + 1];
  898. if(_wcsicmp(pEAW[iVer].Trustee.ptstrName,
  899. rgTrustees[iSrch]) != 0)
  900. {
  901. dwErr = ERROR_INVALID_DATA;
  902. if(fVerbose)
  903. {
  904. printf("\tTrustee mismatch[%lu]: %ws, expected "
  905. "%ws\n",
  906. iVer,
  907. pEAW[iVer].Trustee.ptstrName,
  908. rgTrustees[iSrch]);
  909. }
  910. }
  911. }
  912. }
  913. if(dwErr == ERROR_SUCCESS)
  914. {
  915. if(fVerbose)
  916. {
  917. printf("\tCount: %lu\n", cCount);
  918. }
  919. }
  920. LocalFree(pEAW);
  921. }
  922. else
  923. {
  924. fprintf(stderr,
  925. "\tNt4BuildW: SetEntriesInAclW failed with %lu\n",
  926. dwErr);
  927. }
  928. }
  929. else
  930. {
  931. fprintf(stderr,"\tNt4BuildW: SetEntriesInAclW failed with %lu\n",
  932. dwErr);
  933. }
  934. }
  935. if(dwErr == ERROR_SUCCESS)
  936. {
  937. *ppAcl = pAcl;
  938. }
  939. else
  940. {
  941. LocalFree(pAcl);
  942. }
  943. return(dwErr);
  944. }
  945. //+---------------------------------------------------------------------------
  946. //
  947. // Function: Nt4BuildA
  948. //
  949. // Synopsis: Builds an ACL using the NT4 API ANSI apis
  950. //
  951. // Arguments: [ppAcl] -- Acl to build
  952. //
  953. // Returns: ERROR_SUCCESS -- Everything worked
  954. // ERROR_INVALID_DATA -- One of the compares failed
  955. //
  956. //----------------------------------------------------------------------------
  957. DWORD Nt4BuildA(PACL *ppAcl)
  958. {
  959. DWORD dwErr = ERROR_SUCCESS;
  960. ULONG cCount;
  961. EXPLICIT_ACCESS_A EAA;
  962. PEXPLICIT_ACCESS_A pEAA;
  963. PACL pAcl = NULL, pNewAcl;
  964. ULONG iIndex, iVer;
  965. PSTR rgTrustees[BUILD_COUNT] = {EVERYONE_A,
  966. SYSTEM_A,
  967. GUEST_A,
  968. EVERYONE_A,
  969. SYSTEM_A};
  970. DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8,
  971. GENERIC_ALL,
  972. GENERIC_ALL | 0x8,
  973. GENERIC_ALL | 0x8,
  974. 0};
  975. ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS,
  976. DENY_ACCESS,
  977. SET_ACCESS,
  978. SET_ACCESS,
  979. REVOKE_ACCESS};
  980. DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE,
  981. NO_INHERITANCE,
  982. SUB_CONTAINERS_AND_OBJECTS_INHERIT,
  983. NO_INHERITANCE,
  984. SUB_CONTAINERS_AND_OBJECTS_INHERIT};
  985. DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
  986. {2, 1, 0},
  987. {3, 1, 2, 0},
  988. {3, 1, 3, 2},
  989. {2, 3, 2}};
  990. if(fVerbose)
  991. {
  992. printf("Nt4BuildA\n");
  993. }
  994. //
  995. // We'll do this in a loop, since we have BUILD_COUNT different builds to do
  996. //
  997. for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
  998. {
  999. //
  1000. // Build the new entry
  1001. //
  1002. BuildExplicitAccessWithNameA(&EAA,
  1003. rgTrustees[iIndex],
  1004. rgAccess[iIndex],
  1005. rgMode[iIndex],
  1006. rgInherit[iIndex]);
  1007. dwErr = SetEntriesInAclA(1,
  1008. &EAA,
  1009. pAcl,
  1010. &pNewAcl);
  1011. if(dwErr == ERROR_SUCCESS)
  1012. {
  1013. LocalFree(pAcl);
  1014. pAcl = pNewAcl;
  1015. //
  1016. // Get the explicit entries, and we'll verify them...
  1017. //
  1018. dwErr = GetExplicitEntriesFromAclA(pAcl,
  1019. &cCount,
  1020. &pEAA);
  1021. if(dwErr == ERROR_SUCCESS)
  1022. {
  1023. PDWORD pSrch = rgSrch[iIndex];
  1024. ULONG cExpected = pSrch[0];
  1025. if(cCount != cExpected)
  1026. {
  1027. dwErr = ERROR_INVALID_DATA;
  1028. if(fVerbose)
  1029. {
  1030. printf("\tCount mismatched: %lu, expected %lu\n",
  1031. cCount,
  1032. cExpected);
  1033. }
  1034. }
  1035. else
  1036. {
  1037. //
  1038. // verify the rest of the data
  1039. //
  1040. for(iVer = 0; iVer < cExpected; iVer++)
  1041. {
  1042. ULONG iSrch = pSrch[iVer + 1];
  1043. if(_stricmp(pEAA[iVer].Trustee.ptstrName,
  1044. rgTrustees[iSrch]) != 0)
  1045. {
  1046. dwErr = ERROR_INVALID_DATA;
  1047. if(fVerbose)
  1048. {
  1049. printf("\tTrustee mismatch[%lu]: %s, expected "
  1050. "%s\n",
  1051. iVer,
  1052. pEAA[iVer].Trustee.ptstrName,
  1053. rgTrustees[iSrch]);
  1054. }
  1055. }
  1056. }
  1057. }
  1058. if(dwErr == ERROR_SUCCESS)
  1059. {
  1060. if(fVerbose)
  1061. {
  1062. printf("\tCount: %lu\n", cCount);
  1063. }
  1064. }
  1065. LocalFree(pEAA);
  1066. }
  1067. else
  1068. {
  1069. fprintf(stderr,
  1070. "\tNt4BuildA: SetEntriesInAclA failed with %lu\n",
  1071. dwErr);
  1072. }
  1073. }
  1074. else
  1075. {
  1076. fprintf(stderr,"\tNt4BuildA: SetEntriesInAclA failed with %lu\n",
  1077. dwErr);
  1078. }
  1079. }
  1080. if(dwErr == ERROR_SUCCESS)
  1081. {
  1082. *ppAcl = pAcl;
  1083. }
  1084. else
  1085. {
  1086. LocalFree(pAcl);
  1087. }
  1088. return(dwErr);
  1089. }
  1090. #undef BUILD_COUNT
  1091. #define BUILD_COUNT 6
  1092. //+---------------------------------------------------------------------------
  1093. //
  1094. // Function: Nt5BuildW
  1095. //
  1096. // Synopsis: Builds an ACL using the NT5 API WIDE apis
  1097. //
  1098. // Arguments: [ppAccess] -- Access list to build
  1099. //
  1100. // Returns: ERROR_SUCCESS -- Everything worked
  1101. // ERROR_INVALID_DATA -- One of the compares failed
  1102. //
  1103. //----------------------------------------------------------------------------
  1104. DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess)
  1105. {
  1106. DWORD dwErr = ERROR_SUCCESS;
  1107. PACTRL_ACCESSW pAccess = NULL, pNewAccess;
  1108. ULONG iIndex, iVer;
  1109. PWSTR rgTrustees[BUILD_COUNT] = {SYSTEM, EVERYONE, SYSTEM, GUEST,
  1110. EVERYONE, SYSTEM};
  1111. DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED,
  1112. ACTRL_ACCESS_ALLOWED,
  1113. ACTRL_ACCESS_DENIED,
  1114. ACTRL_ACCESS_ALLOWED,
  1115. ACTRL_ACCESS_ALLOWED,
  1116. ACTRL_ACCESS_DENIED};
  1117. DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5,
  1118. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1,
  1119. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2,
  1120. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3,
  1121. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4,
  1122. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2};
  1123. ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS,
  1124. GRANT_ACCESS, GRANT_ACCESS,
  1125. REVOKE_ACCESS};
  1126. DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE,
  1127. NO_INHERITANCE, NO_INHERITANCE,
  1128. NO_INHERITANCE, NO_INHERITANCE};
  1129. DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
  1130. {1, 1},
  1131. {2, 2, 1},
  1132. {3, 2, 3, 1},
  1133. {4, 2, 4, 3, 1},
  1134. {3, 4, 3, 1}};
  1135. if(fVerbose)
  1136. {
  1137. printf("Nt5BuildW\n");
  1138. }
  1139. //
  1140. // We'll do this in a loop, since we have BUILD_COUNT different builds to do
  1141. //
  1142. for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
  1143. {
  1144. ACTRL_ACCESS_ENTRYW AAE;
  1145. BuildTrusteeWithNameW(&(AAE.Trustee),
  1146. rgTrustees[iIndex]);
  1147. AAE.fAccessFlags = rgTypes[iIndex];
  1148. AAE.Access = rgAccess[iIndex];
  1149. AAE.ProvSpecificAccess = 0;
  1150. AAE.Inheritance = rgInherit[iIndex];
  1151. AAE.lpInheritProperty = NULL;
  1152. dwErr = SetEntriesInAccessListW(1,
  1153. &AAE,
  1154. rgMode[iIndex],
  1155. NULL,
  1156. pAccess,
  1157. &pNewAccess);
  1158. if(dwErr == ERROR_SUCCESS)
  1159. {
  1160. LocalFree(pAccess);
  1161. pAccess = pNewAccess;
  1162. }
  1163. if(dwErr == ERROR_SUCCESS)
  1164. {
  1165. //
  1166. // Now, verify the new entries...
  1167. //
  1168. PACTRL_ACCESS_ENTRY_LISTW pAAELW =
  1169. pAccess->pPropertyAccessList[0].pAccessEntryList;
  1170. PDWORD pSrch = rgSrch[iIndex];
  1171. ULONG cExpected = pSrch[0];
  1172. if(pAAELW->cEntries != cExpected)
  1173. {
  1174. dwErr = ERROR_INVALID_DATA;
  1175. if(fVerbose)
  1176. {
  1177. printf("\tCount mismatched: %lu, expected %lu\n",
  1178. pAAELW->cEntries,
  1179. cExpected);
  1180. }
  1181. }
  1182. else
  1183. {
  1184. //
  1185. // verify the rest of the data
  1186. //
  1187. for(iVer = 0; iVer < pAAELW->cEntries; iVer++)
  1188. {
  1189. ULONG iSrch = pSrch[iVer + 1];
  1190. if(_wcsicmp(pAAELW->pAccessList[iVer].Trustee.ptstrName,
  1191. rgTrustees[iSrch]) != 0)
  1192. {
  1193. dwErr = ERROR_INVALID_DATA;
  1194. if(fVerbose)
  1195. {
  1196. printf("\tTrustee mismatch[%lu]: %ws, expected "
  1197. "%ws\n",
  1198. iVer,
  1199. pAAELW->pAccessList[iVer].Trustee.ptstrName,
  1200. rgTrustees[iSrch]);
  1201. }
  1202. }
  1203. }
  1204. }
  1205. if(dwErr == ERROR_SUCCESS)
  1206. {
  1207. if(fVerbose)
  1208. {
  1209. printf("\tCount: %lu\n", cExpected);
  1210. }
  1211. }
  1212. }
  1213. else
  1214. {
  1215. fprintf(stderr,"\tNt5BuildW: SetEntriesInAccessListW failed "
  1216. "with %lu\n",
  1217. dwErr);
  1218. }
  1219. }
  1220. if(dwErr == ERROR_SUCCESS)
  1221. {
  1222. *ppAccess = pAccess;
  1223. }
  1224. else
  1225. {
  1226. LocalFree(pAccess);
  1227. }
  1228. return(dwErr);
  1229. }
  1230. //+---------------------------------------------------------------------------
  1231. //
  1232. // Function: Nt5BuildA
  1233. //
  1234. // Synopsis: Builds an ACL using the NT5 API ANSI apis
  1235. //
  1236. // Arguments: [ppAccess] -- Access list to build
  1237. //
  1238. // Returns: ERROR_SUCCESS -- Everything worked
  1239. // ERROR_INVALID_DATA -- One of the compares failed
  1240. //
  1241. //----------------------------------------------------------------------------
  1242. DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess)
  1243. {
  1244. DWORD dwErr = ERROR_SUCCESS;
  1245. PACTRL_ACCESSA pAccess = NULL, pNewAccess;
  1246. ULONG iIndex, iVer;
  1247. PSTR rgTrustees[BUILD_COUNT] = {SYSTEM_A, EVERYONE_A, SYSTEM_A, GUEST_A,
  1248. EVERYONE_A, SYSTEM_A};
  1249. DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED,
  1250. ACTRL_ACCESS_ALLOWED,
  1251. ACTRL_ACCESS_DENIED,
  1252. ACTRL_ACCESS_ALLOWED,
  1253. ACTRL_ACCESS_ALLOWED,
  1254. ACTRL_ACCESS_DENIED};
  1255. DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5,
  1256. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1,
  1257. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2,
  1258. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3,
  1259. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4,
  1260. ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2};
  1261. ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS,
  1262. GRANT_ACCESS, GRANT_ACCESS,
  1263. REVOKE_ACCESS};
  1264. DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE,
  1265. NO_INHERITANCE, NO_INHERITANCE,
  1266. NO_INHERITANCE, NO_INHERITANCE};
  1267. DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
  1268. {1, 1},
  1269. {2, 2, 1},
  1270. {3, 2, 3, 1},
  1271. {4, 2, 4, 3, 1},
  1272. {3, 4, 3, 1}};
  1273. if(fVerbose)
  1274. {
  1275. printf("Nt5BuildA\n");
  1276. }
  1277. //
  1278. // We'll do this in a loop, since we have BUILD_COUNT different builds to do
  1279. //
  1280. for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
  1281. {
  1282. ACTRL_ACCESS_ENTRYA AAE;
  1283. BuildTrusteeWithNameA(&(AAE.Trustee),
  1284. rgTrustees[iIndex]);
  1285. AAE.fAccessFlags = rgTypes[iIndex];
  1286. AAE.Access = rgAccess[iIndex];
  1287. AAE.ProvSpecificAccess = 0;
  1288. AAE.Inheritance = rgInherit[iIndex];
  1289. AAE.lpInheritProperty = NULL;
  1290. dwErr = SetEntriesInAccessListA(1,
  1291. &AAE,
  1292. rgMode[iIndex],
  1293. NULL,
  1294. pAccess,
  1295. &pNewAccess);
  1296. if(dwErr == ERROR_SUCCESS)
  1297. {
  1298. LocalFree(pAccess);
  1299. pAccess = pNewAccess;
  1300. }
  1301. if(dwErr == ERROR_SUCCESS)
  1302. {
  1303. //
  1304. // Now, verify the new entries...
  1305. //
  1306. PACTRL_ACCESS_ENTRY_LISTA pAAELA =
  1307. pAccess->pPropertyAccessList[0].pAccessEntryList;
  1308. PDWORD pSrch = rgSrch[iIndex];
  1309. ULONG cExpected = pSrch[0];
  1310. if(pAAELA->cEntries != cExpected)
  1311. {
  1312. dwErr = ERROR_INVALID_DATA;
  1313. if(fVerbose)
  1314. {
  1315. printf("\tCount mismatched: %lu, expected %lu\n",
  1316. pAAELA->cEntries,
  1317. cExpected);
  1318. }
  1319. }
  1320. else
  1321. {
  1322. //
  1323. // verify the rest of the data
  1324. //
  1325. for(iVer = 0; iVer < pAAELA->cEntries; iVer++)
  1326. {
  1327. ULONG iSrch = pSrch[iVer + 1];
  1328. if(_stricmp(pAAELA->pAccessList[iVer].Trustee.ptstrName,
  1329. rgTrustees[iSrch]) != 0)
  1330. {
  1331. dwErr = ERROR_INVALID_DATA;
  1332. if(fVerbose)
  1333. {
  1334. printf("\tTrustee mismatch[%lu]: %s, expected "
  1335. "%s\n",
  1336. iVer,
  1337. pAAELA->pAccessList[iVer].Trustee.ptstrName,
  1338. rgTrustees[iSrch]);
  1339. }
  1340. }
  1341. }
  1342. }
  1343. if(dwErr == ERROR_SUCCESS)
  1344. {
  1345. if(fVerbose)
  1346. {
  1347. printf("\tCount: %lu\n", cExpected);
  1348. }
  1349. }
  1350. }
  1351. else
  1352. {
  1353. fprintf(stderr,"\tNt5BuildA: SetEntriesInAccessListA failed "
  1354. "with %lu\n",
  1355. dwErr);
  1356. }
  1357. }
  1358. if(dwErr == ERROR_SUCCESS)
  1359. {
  1360. *ppAccess = pAccess;
  1361. }
  1362. else
  1363. {
  1364. LocalFree(pAccess);
  1365. }
  1366. return(dwErr);
  1367. }
  1368. //+---------------------------------------------------------------------------
  1369. //
  1370. // Function: Nt4DrtW
  1371. //
  1372. // Synopsis: Does the actual API drt. This involves reading the existing
  1373. // access, writing the new one, rereading the new one and
  1374. // verifing the results, and then restores the old one. This
  1375. // uses the WIDE version of the NT4 APIs
  1376. //
  1377. // Arguments: [pAcl] -- Acl to write on the object
  1378. // [pszObject] -- The object in question
  1379. // [ObjType] -- Type of the object
  1380. //
  1381. // Returns: ERROR_SUCCESS -- Success
  1382. // ERROR_INVALID_DATA -- One of the compares failed
  1383. //
  1384. //----------------------------------------------------------------------------
  1385. DWORD Nt4DrtW(PACL pAcl,
  1386. PSTR pszObject,
  1387. SE_OBJECT_TYPE ObjType)
  1388. {
  1389. DWORD dwErr = ERROR_SUCCESS;
  1390. WCHAR wszPath[MAX_PATH + 1];
  1391. PACL pOldAcl = NULL;
  1392. PSECURITY_DESCRIPTOR pSD = NULL;
  1393. mbstowcs(wszPath, pszObject, strlen(pszObject) + 1);
  1394. if(fVerbose)
  1395. {
  1396. printf("Nt4DrtW: Processing %ws [%lu]\n", wszPath, ObjType);
  1397. }
  1398. //
  1399. // First, get the old acl
  1400. //
  1401. dwErr = GetNamedSecurityInfoW(wszPath,
  1402. ObjType,
  1403. DACL_SECURITY_INFORMATION,
  1404. NULL,
  1405. NULL,
  1406. &pOldAcl,
  1407. NULL,
  1408. &pSD);
  1409. if(dwErr == ERROR_SUCCESS)
  1410. {
  1411. //
  1412. // Set, get, and compare the new acl...
  1413. //
  1414. dwErr = SetNamedSecurityInfoW(wszPath,
  1415. ObjType,
  1416. DACL_SECURITY_INFORMATION,
  1417. NULL,
  1418. NULL,
  1419. pAcl,
  1420. NULL);
  1421. if(dwErr == ERROR_SUCCESS)
  1422. {
  1423. PACL pNewAcl = NULL;
  1424. PSECURITY_DESCRIPTOR pNewSD = NULL;
  1425. dwErr = GetNamedSecurityInfoW(wszPath,
  1426. ObjType,
  1427. DACL_SECURITY_INFORMATION,
  1428. NULL,
  1429. NULL,
  1430. &pNewAcl,
  1431. NULL,
  1432. &pNewSD);
  1433. if(dwErr == ERROR_SUCCESS)
  1434. {
  1435. //
  1436. // Compare them...
  1437. //
  1438. dwErr = CompAcls(pAcl, pNewAcl);
  1439. if(dwErr != ERROR_SUCCESS)
  1440. {
  1441. fprintf(stderr, "\tSet and old ACLs don't compare\n");
  1442. }
  1443. LocalFree(pNewSD);
  1444. }
  1445. else
  1446. {
  1447. if(fVerbose)
  1448. {
  1449. printf("\tSecond GetNamedSecurityW on %ws failed with %lu\n",
  1450. wszPath,
  1451. dwErr);
  1452. }
  1453. }
  1454. }
  1455. else
  1456. {
  1457. if(fVerbose)
  1458. {
  1459. printf("\tSetNamedSecurityInfoW on %ws failed with %lu\n",
  1460. wszPath,
  1461. dwErr);
  1462. }
  1463. }
  1464. }
  1465. else
  1466. {
  1467. fprintf(stderr,
  1468. "\tGetNamedSecurityInfoW failed on %ws: %lu\n",
  1469. wszPath,
  1470. dwErr);
  1471. }
  1472. //
  1473. // Restore the objects security
  1474. //
  1475. if(pSD != NULL)
  1476. {
  1477. DWORD dwErr2 = SetNamedSecurityInfoW(wszPath,
  1478. ObjType,
  1479. DACL_SECURITY_INFORMATION,
  1480. NULL,
  1481. NULL,
  1482. pOldAcl,
  1483. NULL);
  1484. if(dwErr2 != ERROR_SUCCESS)
  1485. {
  1486. fprintf(stderr,
  1487. "Restoring access to %ws failed with %lu\n",
  1488. wszPath,
  1489. dwErr2);
  1490. }
  1491. if(dwErr == ERROR_SUCCESS)
  1492. {
  1493. dwErr = dwErr2;
  1494. }
  1495. }
  1496. LocalFree(pSD);
  1497. return(dwErr);
  1498. }
  1499. //+---------------------------------------------------------------------------
  1500. //
  1501. // Function: Nt4DrtA
  1502. //
  1503. // Synopsis: Does the actual API drt. This involves reading the existing
  1504. // access, writing the new one, rereading the new one and
  1505. // verifing the results, and then restores the old one. This
  1506. // uses the ANSI version of the NT4 APIs
  1507. //
  1508. // Arguments: [pAcl] -- Acl to write on the object
  1509. // [pszObject] -- The object in question
  1510. // [ObjType] -- Type of the object
  1511. //
  1512. // Returns: ERROR_SUCCESS -- Success
  1513. // ERROR_INVALID_DATA -- One of the compares failed
  1514. //
  1515. //----------------------------------------------------------------------------
  1516. DWORD Nt4DrtA(PACL pAcl,
  1517. PSTR pszObject,
  1518. SE_OBJECT_TYPE ObjType)
  1519. {
  1520. DWORD dwErr = ERROR_SUCCESS;
  1521. PACL pOldAcl = NULL;
  1522. PSECURITY_DESCRIPTOR pSD = NULL;
  1523. if(fVerbose)
  1524. {
  1525. printf("Nt4DrtA: Processing %s [%lu]\n", pszObject, ObjType);
  1526. }
  1527. //
  1528. // First, get the old acl
  1529. //
  1530. dwErr = GetNamedSecurityInfoA(pszObject,
  1531. ObjType,
  1532. DACL_SECURITY_INFORMATION,
  1533. NULL,
  1534. NULL,
  1535. &pOldAcl,
  1536. NULL,
  1537. &pSD);
  1538. if(dwErr == ERROR_SUCCESS)
  1539. {
  1540. //
  1541. // Set, get, and compare the new acl...
  1542. //
  1543. dwErr = SetNamedSecurityInfoA(pszObject,
  1544. ObjType,
  1545. DACL_SECURITY_INFORMATION,
  1546. NULL,
  1547. NULL,
  1548. pAcl,
  1549. NULL);
  1550. if(dwErr == ERROR_SUCCESS)
  1551. {
  1552. PACL pNewAcl = NULL;
  1553. PSECURITY_DESCRIPTOR pNewSD = NULL;
  1554. dwErr = GetNamedSecurityInfoA(pszObject,
  1555. ObjType,
  1556. DACL_SECURITY_INFORMATION,
  1557. NULL,
  1558. NULL,
  1559. &pNewAcl,
  1560. NULL,
  1561. &pNewSD);
  1562. if(dwErr == ERROR_SUCCESS)
  1563. {
  1564. //
  1565. // Compare them...
  1566. //
  1567. dwErr = CompAcls(pAcl, pNewAcl);
  1568. if(dwErr != ERROR_SUCCESS)
  1569. {
  1570. fprintf(stderr, "\tSet and old ACLs don't compare\n");
  1571. }
  1572. LocalFree(pNewSD);
  1573. }
  1574. else
  1575. {
  1576. if(fVerbose)
  1577. {
  1578. printf("\tSecond GetNamedSecurityA on %s failed with %lu\n",
  1579. pszObject,
  1580. dwErr);
  1581. }
  1582. }
  1583. }
  1584. else
  1585. {
  1586. if(fVerbose)
  1587. {
  1588. printf("\tSetNamedSecurityInfoA on %s failed with %lu\n",
  1589. pszObject,
  1590. dwErr);
  1591. }
  1592. }
  1593. }
  1594. else
  1595. {
  1596. fprintf(stderr,
  1597. "\tGetNamedSecurityInfoA failed on %s: %lu\n",
  1598. pszObject,
  1599. dwErr);
  1600. }
  1601. //
  1602. // Restore the objects security
  1603. //
  1604. if(pSD != NULL)
  1605. {
  1606. DWORD dwErr2 = SetNamedSecurityInfoA(pszObject,
  1607. ObjType,
  1608. DACL_SECURITY_INFORMATION,
  1609. NULL,
  1610. NULL,
  1611. pOldAcl,
  1612. NULL);
  1613. if(dwErr2 != ERROR_SUCCESS)
  1614. {
  1615. fprintf(stderr,
  1616. "Restoring access to %s failed with %lu\n",
  1617. pszObject,
  1618. dwErr2);
  1619. }
  1620. if(dwErr == ERROR_SUCCESS)
  1621. {
  1622. dwErr = dwErr2;
  1623. }
  1624. }
  1625. LocalFree(pSD);
  1626. return(dwErr);
  1627. }
  1628. //+---------------------------------------------------------------------------
  1629. //
  1630. // Function: Nt5DrtW
  1631. //
  1632. // Synopsis: Does the actual API drt. This involves reading the existing
  1633. // access, writing the new one, rereading the new one and
  1634. // verifing the results, and then restores the old one. This
  1635. // uses the WIDE version of the NT5 APIs
  1636. //
  1637. // Arguments: [pAccess] -- Access list to write on the object
  1638. // [pszObject] -- The object in question
  1639. // [ObjType] -- Type of the object
  1640. //
  1641. // Returns: ERROR_SUCCESS -- Success
  1642. // ERROR_INVALID_DATA -- One of the compares failed
  1643. //
  1644. //----------------------------------------------------------------------------
  1645. DWORD Nt5DrtW(PACTRL_ACCESSW pAccess,
  1646. PSTR pszObject,
  1647. SE_OBJECT_TYPE ObjType)
  1648. {
  1649. DWORD dwErr = ERROR_SUCCESS;
  1650. WCHAR wszPath[MAX_PATH + 1];
  1651. PACTRL_ACCESSW pOldAccess = NULL;
  1652. mbstowcs(wszPath, pszObject, strlen(pszObject) + 1);
  1653. if(fVerbose)
  1654. {
  1655. printf("Nt5DrtW: Processing %ws [%lu]\n", wszPath, ObjType);
  1656. }
  1657. //
  1658. // First, get the old acl
  1659. //
  1660. dwErr = GetNamedSecurityInfoExW(wszPath,
  1661. ObjType,
  1662. DACL_SECURITY_INFORMATION,
  1663. NULL,
  1664. NULL,
  1665. &pOldAccess,
  1666. NULL,
  1667. NULL,
  1668. NULL);
  1669. if(dwErr == ERROR_SUCCESS)
  1670. {
  1671. //
  1672. // Set, get, and compare the new value...
  1673. //
  1674. dwErr = SetNamedSecurityInfoExW(wszPath,
  1675. ObjType,
  1676. DACL_SECURITY_INFORMATION,
  1677. NULL,
  1678. pAccess,
  1679. NULL,
  1680. NULL,
  1681. NULL,
  1682. NULL);
  1683. if(dwErr == ERROR_SUCCESS)
  1684. {
  1685. PACTRL_ACCESS pNewAccess = NULL;
  1686. dwErr = GetNamedSecurityInfoExW(wszPath,
  1687. ObjType,
  1688. DACL_SECURITY_INFORMATION,
  1689. NULL,
  1690. NULL,
  1691. &pNewAccess,
  1692. NULL,
  1693. NULL,
  1694. NULL);
  1695. if(dwErr == ERROR_SUCCESS)
  1696. {
  1697. //
  1698. // Compare them...
  1699. //
  1700. dwErr = CompAccessW(pAccess, pNewAccess);
  1701. if(dwErr != ERROR_SUCCESS)
  1702. {
  1703. fprintf(stderr, "\tSet and old Accesses don't compare\n");
  1704. }
  1705. }
  1706. else
  1707. {
  1708. if(fVerbose)
  1709. {
  1710. printf("\tSecond GetNamedSecurityExW on %ws failed "
  1711. "with %lu\n",
  1712. wszPath,
  1713. dwErr);
  1714. }
  1715. }
  1716. }
  1717. else
  1718. {
  1719. if(fVerbose)
  1720. {
  1721. printf("\tSetNamedSecurityInfoExW on %ws failed with %lu\n",
  1722. wszPath,
  1723. dwErr);
  1724. }
  1725. }
  1726. }
  1727. else
  1728. {
  1729. fprintf(stderr,
  1730. "\tGetNamedSecurityInfoExW failed on %ws: %lu\n",
  1731. wszPath,
  1732. dwErr);
  1733. }
  1734. //
  1735. // Restore the objects security
  1736. //
  1737. if(pOldAccess != NULL)
  1738. {
  1739. DWORD dwErr2 = SetNamedSecurityInfoExW(wszPath,
  1740. ObjType,
  1741. DACL_SECURITY_INFORMATION,
  1742. NULL,
  1743. pOldAccess,
  1744. NULL,
  1745. NULL,
  1746. NULL,
  1747. NULL);
  1748. if(dwErr2 != ERROR_SUCCESS)
  1749. {
  1750. fprintf(stderr,
  1751. "Restoring access to %ws failed with %lu\n",
  1752. wszPath,
  1753. dwErr2);
  1754. }
  1755. if(dwErr == ERROR_SUCCESS)
  1756. {
  1757. dwErr = dwErr2;
  1758. }
  1759. }
  1760. LocalFree(pOldAccess);
  1761. return(dwErr);
  1762. }
  1763. //+---------------------------------------------------------------------------
  1764. //
  1765. // Function: Nt5DrtA
  1766. //
  1767. // Synopsis: Does the actual API drt. This involves reading the existing
  1768. // access, writing the new one, rereading the new one and
  1769. // verifing the results, and then restores the old one. This
  1770. // uses the ANSI version of the NT5 APIs
  1771. //
  1772. // Arguments: [pAccess] -- Access list to write on the object
  1773. // [pszObject] -- The object in question
  1774. // [ObjType] -- Type of the object
  1775. //
  1776. // Returns: ERROR_SUCCESS -- Success
  1777. // ERROR_INVALID_DATA -- One of the compares failed
  1778. //
  1779. //----------------------------------------------------------------------------
  1780. DWORD Nt5DrtA(PACTRL_ACCESSA pAccess,
  1781. PSTR pszObject,
  1782. SE_OBJECT_TYPE ObjType)
  1783. {
  1784. DWORD dwErr = ERROR_SUCCESS;
  1785. PACTRL_ACCESSA pOldAccess = NULL;
  1786. if(fVerbose)
  1787. {
  1788. printf("Nt5DrtA: Processing %s [%lu]\n", pszObject, ObjType);
  1789. }
  1790. //
  1791. // First, get the old acl
  1792. //
  1793. dwErr = GetNamedSecurityInfoExA(pszObject,
  1794. ObjType,
  1795. DACL_SECURITY_INFORMATION,
  1796. NULL,
  1797. NULL,
  1798. &pOldAccess,
  1799. NULL,
  1800. NULL,
  1801. NULL);
  1802. if(dwErr == ERROR_SUCCESS)
  1803. {
  1804. //
  1805. // Set, get, and compare the new value...
  1806. //
  1807. dwErr = SetNamedSecurityInfoExA(pszObject,
  1808. ObjType,
  1809. DACL_SECURITY_INFORMATION,
  1810. NULL,
  1811. pAccess,
  1812. NULL,
  1813. NULL,
  1814. NULL,
  1815. NULL);
  1816. if(dwErr == ERROR_SUCCESS)
  1817. {
  1818. PACTRL_ACCESSA pNewAccess = NULL;
  1819. dwErr = GetNamedSecurityInfoExA(pszObject,
  1820. ObjType,
  1821. DACL_SECURITY_INFORMATION,
  1822. NULL,
  1823. NULL,
  1824. &pNewAccess,
  1825. NULL,
  1826. NULL,
  1827. NULL);
  1828. if(dwErr == ERROR_SUCCESS)
  1829. {
  1830. //
  1831. // Compare them...
  1832. //
  1833. dwErr = CompAccessA(pAccess, pNewAccess);
  1834. if(dwErr != ERROR_SUCCESS)
  1835. {
  1836. fprintf(stderr, "\tSet and old Accesses don't compare\n");
  1837. }
  1838. }
  1839. else
  1840. {
  1841. if(fVerbose)
  1842. {
  1843. printf("\tSecond GetNamedSecurityExA on %s failed "
  1844. "with %lu\n",
  1845. pszObject,
  1846. dwErr);
  1847. }
  1848. }
  1849. }
  1850. else
  1851. {
  1852. if(fVerbose)
  1853. {
  1854. printf("\tSetNamedSecurityInfoExA on %s failed with %lu\n",
  1855. pszObject,
  1856. dwErr);
  1857. }
  1858. }
  1859. }
  1860. else
  1861. {
  1862. fprintf(stderr,
  1863. "\tGetNamedSecurityInfoExA failed on %s: %lu\n",
  1864. pszObject,
  1865. dwErr);
  1866. }
  1867. //
  1868. // Restore the objects security
  1869. //
  1870. if(pOldAccess != NULL)
  1871. {
  1872. DWORD dwErr2 = SetNamedSecurityInfoExA(pszObject,
  1873. ObjType,
  1874. DACL_SECURITY_INFORMATION,
  1875. NULL,
  1876. pOldAccess,
  1877. NULL,
  1878. NULL,
  1879. NULL,
  1880. NULL);
  1881. if(dwErr2 != ERROR_SUCCESS)
  1882. {
  1883. fprintf(stderr,
  1884. "Restoring access to %s failed with %lu\n",
  1885. pszObject,
  1886. dwErr2);
  1887. }
  1888. if(dwErr == ERROR_SUCCESS)
  1889. {
  1890. dwErr = dwErr2;
  1891. }
  1892. }
  1893. LocalFree(pOldAccess);
  1894. //
  1895. // Finally, try to convert to and from a security descriptor
  1896. //
  1897. if(dwErr == ERROR_SUCCESS)
  1898. {
  1899. PSECURITY_DESCRIPTOR pSD;
  1900. dwErr = ConvertAccessToSecurityDescriptorA(pAccess,
  1901. NULL,
  1902. "ntds\\macm",
  1903. NULL,
  1904. &pSD);
  1905. if(dwErr != ERROR_SUCCESS)
  1906. {
  1907. fprintf(stderr,
  1908. "ConvertAccessToSecurityDescriptor failed with %lu\n",
  1909. dwErr);
  1910. }
  1911. else
  1912. {
  1913. PACTRL_ACCESSA pNewAccess;
  1914. PSTR pszName;
  1915. dwErr = ConvertSecurityDescriptorToAccessA(pszObject,
  1916. ObjType,
  1917. pSD,
  1918. &pNewAccess,
  1919. NULL,
  1920. &pszName,
  1921. NULL);
  1922. if(dwErr == ERROR_SUCCESS)
  1923. {
  1924. AccFree(pszName);
  1925. AccFree(pNewAccess);
  1926. }
  1927. else
  1928. {
  1929. fprintf(stderr,
  1930. "ConvertSecurityDescriptorToAccessA failed with %lu\n",
  1931. dwErr);
  1932. }
  1933. LocalFree(pSD);
  1934. }
  1935. }
  1936. return(dwErr);
  1937. }