//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1996. // // File: ACLAPI.C // // Contents: Implements the drt for MARTA and Win32Ex APIs // // History: 14-Sep-96 MacM Created // // Notes: // //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #define EVERYONE L"EVERYONE" #define EVERYONE_A "EVERYONE" #define GUEST L"GUEST" #define GUEST_A "GUEST" #define GUEST_COMPARE L"GUEST" #define SYSTEM L"SYSTEM" #define SYSTEM_A "SYSTEM" #define MAX_LINE 256 // // Globals // BOOL fVerbose = FALSE; // // Function prototypes // DWORD Nt4BuildW(PACL *ppAcl); DWORD Nt4BuildA(PACL *ppAcl); DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess); DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess); DWORD Nt4DrtW(PACL pAcl, PSTR pszObject, SE_OBJECT_TYPE ObjType); DWORD Nt4DrtA(PACL pAcl, PSTR pszObject, SE_OBJECT_TYPE ObjType); DWORD Nt5DrtW(PACTRL_ACCESSW pAccess, PSTR pszObject, SE_OBJECT_TYPE ObjType); DWORD Nt5DrtA(PACTRL_ACCESSA pAccess, PSTR pszObject, SE_OBJECT_TYPE ObjType); VOID ConvertAccessMaskToAccessRight(IN ACCESS_MASK AccessMask, OUT PACCESS_RIGHTS pAccessRight); //+--------------------------------------------------------------------------- // // Function: main // // Synopsis: The main // // Arguments: [IN argc] -- Count of arguments // [IN argv] -- List of arguments // // Returns: 0 -- Success // non-0 -- Failure // //---------------------------------------------------------------------------- __cdecl main(INT argc, CHAR *argv[]) { DWORD dwErr = ERROR_SUCCESS; PACL pNt4AclW = NULL, pNt4AclA = NULL; PACTRL_ACCESSW pNt5AccessW = NULL; PACTRL_ACCESSA pNt5AccessA = NULL; FILE *fp = NULL; SE_OBJECT_TYPE ObjType; CHAR szBuff[MAX_LINE]; if (argc < 2 || argc > 3) { fprintf(stderr,"USAGE: aclexdrt input_file [verbose]\n"); exit(1); } if(argc == 3) { fVerbose = TRUE; } AccProvInit(dwErr); // // Do the Nt4 style build routines // if(dwErr == ERROR_SUCCESS) { dwErr = Nt4BuildW(&pNt4AclW); } if(dwErr == ERROR_SUCCESS) { dwErr = Nt4BuildA(&pNt4AclA); } if(dwErr == ERROR_SUCCESS) { dwErr = Nt5BuildW(&pNt5AccessW); } if(dwErr == ERROR_SUCCESS) { dwErr = Nt5BuildA(&pNt5AccessA); } // // Now, open the file and process it... // if(dwErr == ERROR_SUCCESS) { fp = fopen(argv[1], "r"); if(fp == NULL) { fprintf(stderr, "File %s not found\n", argv[1]); dwErr = ERROR_FILE_NOT_FOUND; } while(dwErr == ERROR_SUCCESS && fgets(szBuff, MAX_LINE, fp) != NULL) { BOOL fIsDSObj = FALSE; PSTR pszType; PSTR pszObject = strtok(szBuff, " "); if(pszObject != NULL) { pszType = strtok(NULL," \n\r\0"); } if(pszObject == NULL && pszType == NULL) { continue; } else if(pszObject == NULL || pszType == NULL) { fprintf(stderr, "Invalid entry %s in input file %s\n", szBuff, argv[1]); dwErr = ERROR_INVALID_DATA; } else { if(_stricmp(pszType, "FILE") == 0) { ObjType = SE_FILE_OBJECT; } else if(_stricmp(pszType, "SERVICE") == 0) { ObjType = SE_SERVICE; } else if(_stricmp(pszType, "PRINTER") == 0) { ObjType = SE_PRINTER; } else if (_stricmp(pszType, "REGISTRY_KEY") == 0) { ObjType = SE_REGISTRY_KEY; } else if(_stricmp(pszType, "SHARE") == 0) { ObjType = SE_LMSHARE; } else if(_stricmp(pszType, "DSOBJ") == 0) { ObjType = SE_DS_OBJECT; fIsDSObj = TRUE; } else if(_stricmp(pszType, "DSOBJALL") == 0) { ObjType = SE_DS_OBJECT_ALL; fIsDSObj = TRUE; } else { fprintf(stderr, "Invalid object type %s\n", pszType); dwErr = ERROR_INVALID_DATA; } } // // If it worked, do the tests... // if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE) { dwErr = Nt4DrtW(pNt4AclW, pszObject, ObjType); } if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE) { dwErr = Nt4DrtA(pNt4AclA, pszObject, ObjType); } if(dwErr == ERROR_SUCCESS) { dwErr = Nt5DrtW(pNt5AccessW, pszObject, ObjType); } if(dwErr == ERROR_SUCCESS) { dwErr = Nt5DrtA(pNt5AccessA, pszObject, ObjType); } } if(fp != NULL) { fclose(fp); } } LocalFree(pNt4AclW); LocalFree(pNt4AclA); LocalFree(pNt5AccessW); LocalFree(pNt5AccessA); if(dwErr == ERROR_SUCCESS) { printf("Success\n"); } else { printf("Failure: %lu\n", dwErr); } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: CompareAcls // // Synopsis: Compares 2 acls for equality // // Arguments: [pAcl1] -- First ACL // [pAcl2] -- Second ACL // // Returns: ERROR_SUCCESS -- They match // ERROR_INVALID_DATA -- They don't match // //---------------------------------------------------------------------------- DWORD CompAcls(PACL pAcl1, PACL pAcl2) { DWORD dwErr = ERROR_SUCCESS; ACL_SIZE_INFORMATION AclSize1, AclSize2; ACL_REVISION_INFORMATION AclRev1, AclRev2; PKNOWN_ACE pAce1, pAce2; PSID pSid1, pSid2; DWORD iIndex; if(pAcl1 == NULL || pAcl2 == NULL) { if(pAcl1 != pAcl2) { if(fVerbose) { fprintf(stderr,"Acl %lu is NULL\n", pAcl1 == NULL ? 1 : 2); } dwErr = ERROR_INVALID_DATA; } } else { if(GetAclInformation(pAcl1, &AclRev1, sizeof(ACL_REVISION_INFORMATION), AclRevisionInformation) == FALSE || GetAclInformation(pAcl2, &AclRev2, sizeof(ACL_REVISION_INFORMATION), AclRevisionInformation) == FALSE) { return(ERROR_INVALID_DATA); } if(GetAclInformation(pAcl1, &AclSize1, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) == FALSE || GetAclInformation(pAcl2, &AclSize2, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) == FALSE) { return(ERROR_INVALID_DATA); } if(AclRev1.AclRevision != AclRev2.AclRevision) { if(fVerbose) { fprintf(stderr, "Revision mismatch: %lu %lu\n", AclRev1.AclRevision, AclRev2.AclRevision); } dwErr = ERROR_INVALID_DATA; } if(AclSize1.AceCount != AclSize2.AceCount) { if(fVerbose) { fprintf(stderr, "AceCount mismatch: %lu %lu\n", AclSize1.AceCount, AclSize2.AceCount); } dwErr = ERROR_INVALID_DATA; } if(AclSize1.AclBytesInUse != AclSize2.AclBytesInUse) { if(fVerbose) { fprintf(stderr, "BytesInUse mismatch: %lu %lu\n", AclSize1.AclBytesInUse, AclSize2.AclBytesInUse); } dwErr = ERROR_INVALID_DATA; } if(pAcl1->Sbz1 != pAcl2->Sbz1) { if(fVerbose) { fprintf(stderr, "Acl flags mismatch: %lu %lu\n", pAcl1->Sbz1, pAcl2->Sbz1); } dwErr = ERROR_INVALID_DATA; } if(dwErr != ERROR_SUCCESS) { return(dwErr); } // // Now, compare all of the aces // pAce1 = FirstAce(pAcl1); pAce2 = FirstAce(pAcl2); for(iIndex = 0; iIndex < pAcl1->AceCount && dwErr == ERROR_SUCCESS; iIndex++) { ACCESS_RIGHTS Rights1, Rights2; if(fVerbose) { printf("Ace %lu\n", iIndex); } if(pAce1->Header.AceType != pAce2->Header.AceType) { if(fVerbose) { fprintf(stderr, "\tAceType mismatch: %lu %lu\n", pAce1->Header.AceType, pAce2->Header.AceType); } dwErr = ERROR_INVALID_DATA; } if(pAce1->Header.AceFlags != pAce2->Header.AceFlags) { if(fVerbose) { fprintf(stderr, "\tAceType mismatch: %lu %lu\n", pAce1->Header.AceFlags, pAce2->Header.AceFlags); } dwErr = ERROR_INVALID_DATA; } if(pAce1->Header.AceSize != pAce2->Header.AceSize) { if(fVerbose) { fprintf(stderr, "\tAceType mismatch: %lu %lu\n", pAce1->Header.AceSize, pAce2->Header.AceSize); } dwErr = ERROR_INVALID_DATA; } ConvertAccessMaskToAccessRight(pAce1->Mask, &Rights1); ConvertAccessMaskToAccessRight(pAce2->Mask, &Rights2); if(Rights1 != Rights1) { if(fVerbose) { fprintf(stderr, "\tAccessMask mismatch: %lu %lu\n", Rights1, Rights2); } dwErr = ERROR_INVALID_DATA; } if(!RtlEqualSid((PSID)&(pAce1->SidStart), (PSID)&(pAce2->SidStart))) { if(fVerbose) { fprintf(stderr, "\tSids don't match\n"); } dwErr = ERROR_INVALID_DATA; } pAce1 = NextAce(pAce1); pAce2 = NextAce(pAce2); } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: CompStringsW // // Synopsis: Compares 2 string pointers for equality // // Arguments: [pwszStr1] -- First string // [pwszStr2] -- Second string // // Returns: ERROR_SUCCESS -- They match // ERROR_INVALID_DATA -- They don't match // //---------------------------------------------------------------------------- DWORD CompStringsW(PWSTR pwszStr1, PWSTR pwszStr2) { if(pwszStr1 != NULL && pwszStr2 != NULL) { if(_wcsicmp(pwszStr1, pwszStr2) == 0) { return(ERROR_SUCCESS); } } else { if(pwszStr1 == NULL) { return(ERROR_SUCCESS); } } return(ERROR_INVALID_DATA); } //+--------------------------------------------------------------------------- // // Function: CompStringsA // // Synopsis: Compares 2 string pointers for equality // // Arguments: [pszStr1] -- First string // [pszStr2] -- Second string // // Returns: ERROR_SUCCESS -- They match // ERROR_INVALID_DATA -- They don't match // //---------------------------------------------------------------------------- DWORD CompStringsA(PSTR pszStr1, PSTR pszStr2) { if(pszStr1 != NULL && pszStr2 != NULL) { if(_stricmp(pszStr1, pszStr2) == 0) { return(ERROR_SUCCESS); } } else { if(pszStr1 == NULL) { return(ERROR_SUCCESS); } } return(ERROR_INVALID_DATA); } //+--------------------------------------------------------------------------- // // Function: CompAccessW // // Synopsis: Compares 2 WIDE access lists for equality // // Arguments: [pAccess1] -- First list // [pAccess2] -- Second list // // Returns: ERROR_SUCCESS -- They match // ERROR_INVALID_DATA -- They don't match // //---------------------------------------------------------------------------- DWORD CompAccessW(PACTRL_ACCESSW pAccess1, PACTRL_ACCESSW pAccess2) { DWORD dwErr = ERROR_SUCCESS; ULONG iIndex = 0; if(pAccess1 == NULL || pAccess2 == NULL) { if(pAccess1 != pAccess2) { if(fVerbose) { fprintf(stderr,"Access %lu is NULL\n", pAccess1 == NULL ? 1 : 2); } dwErr = ERROR_INVALID_DATA; } } else { PACTRL_ACCESS_ENTRY_LISTW pAAEL1; PACTRL_ACCESS_ENTRY_LISTW pAAEL2; dwErr = CompStringsW((PWSTR)pAccess1->pPropertyAccessList[0].lpProperty, (PWSTR)pAccess2->pPropertyAccessList[0].lpProperty); if(dwErr != ERROR_SUCCESS) { return(dwErr); } pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList; pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList; if(pAAEL1->cEntries != pAAEL2->cEntries) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { fprintf(stderr, "cEntries: %lu %lu\n", pAAEL1->cEntries, pAAEL2->cEntries); } } else { // // Compare all of the entries // for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++) { if(_wcsicmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName, pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0) { if(fVerbose) { fprintf(stderr, "Trustees: %ws %ws\n", pAAEL1->pAccessList[iIndex].Trustee.ptstrName, pAAEL2->pAccessList[iIndex].Trustee.ptstrName); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].fAccessFlags != pAAEL1->pAccessList[iIndex].fAccessFlags) { if(fVerbose) { fprintf(stderr, "AccessFlags: %lu %lu\n", pAAEL1->pAccessList[iIndex].fAccessFlags, pAAEL2->pAccessList[iIndex].fAccessFlags); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].Access != pAAEL1->pAccessList[iIndex].Access) { if(fVerbose) { fprintf(stderr, "Access: %lu %lu\n", pAAEL1->pAccessList[iIndex].Access, pAAEL2->pAccessList[iIndex].Access); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess != pAAEL1->pAccessList[iIndex].ProvSpecificAccess) { if(fVerbose) { fprintf(stderr, "ProvSpecificAccess: %lu %lu\n", pAAEL1->pAccessList[iIndex].ProvSpecificAccess, pAAEL2->pAccessList[iIndex].ProvSpecificAccess); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].Inheritance != pAAEL1->pAccessList[iIndex].Inheritance) { if(fVerbose) { fprintf(stderr, "AccessFlags: %lu %lu\n", pAAEL1->pAccessList[iIndex].Inheritance, pAAEL2->pAccessList[iIndex].Inheritance); } dwErr = ERROR_INVALID_DATA; continue; } // // The inheritance property // dwErr = CompStringsW( (PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty, (PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty); if(dwErr == ERROR_SUCCESS && fVerbose) { printf("AccessEntry %lu\n", iIndex); } } } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: CompAccessA // // Synopsis: Compares 2 ANSI access lists for equality // // Arguments: [pAccess1] -- First list // [pAccess2] -- Second list // // Returns: ERROR_SUCCESS -- They match // ERROR_INVALID_DATA -- They don't match // //---------------------------------------------------------------------------- DWORD CompAccessA(PACTRL_ACCESSA pAccess1, PACTRL_ACCESSA pAccess2) { DWORD dwErr = ERROR_SUCCESS; ULONG iIndex = 0; if(pAccess1 == NULL || pAccess2 == NULL) { if(pAccess1 != pAccess2) { if(fVerbose) { fprintf(stderr,"Access %lu is NULL\n", pAccess1 == NULL ? 1 : 2); } dwErr = ERROR_INVALID_DATA; } } else { PACTRL_ACCESS_ENTRY_LISTA pAAEL1; PACTRL_ACCESS_ENTRY_LISTA pAAEL2; dwErr = CompStringsA((PSTR)pAccess1->pPropertyAccessList[0].lpProperty, (PSTR)pAccess2->pPropertyAccessList[0].lpProperty); if(dwErr != ERROR_SUCCESS) { return(dwErr); } pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList; pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList; if(pAAEL1->cEntries != pAAEL2->cEntries) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { fprintf(stderr, "cEntries: %lu %lu\n", pAAEL1->cEntries, pAAEL2->cEntries); } } else { // // Compare all of the entries // for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++) { if(_stricmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName, pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0) { if(fVerbose) { fprintf(stderr, "Trustees: %ws %ws\n", pAAEL1->pAccessList[iIndex].Trustee.ptstrName, pAAEL2->pAccessList[iIndex].Trustee.ptstrName); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].fAccessFlags != pAAEL1->pAccessList[iIndex].fAccessFlags) { if(fVerbose) { fprintf(stderr, "AccessFlags: %lu %lu\n", pAAEL1->pAccessList[iIndex].fAccessFlags, pAAEL2->pAccessList[iIndex].fAccessFlags); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].Access != pAAEL1->pAccessList[iIndex].Access) { if(fVerbose) { fprintf(stderr, "Access: %lu %lu\n", pAAEL1->pAccessList[iIndex].Access, pAAEL2->pAccessList[iIndex].Access); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess != pAAEL1->pAccessList[iIndex].ProvSpecificAccess) { if(fVerbose) { fprintf(stderr, "ProvSpecificAccess: %lu %lu\n", pAAEL1->pAccessList[iIndex].ProvSpecificAccess, pAAEL2->pAccessList[iIndex].ProvSpecificAccess); } dwErr = ERROR_INVALID_DATA; continue; } if(pAAEL1->pAccessList[iIndex].Inheritance != pAAEL1->pAccessList[iIndex].Inheritance) { if(fVerbose) { fprintf(stderr, "AccessFlags: %lu %lu\n", pAAEL1->pAccessList[iIndex].Inheritance, pAAEL2->pAccessList[iIndex].Inheritance); } dwErr = ERROR_INVALID_DATA; continue; } // // The inheritance property // dwErr = CompStringsA( (PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty, (PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty); if(dwErr == ERROR_SUCCESS && fVerbose) { printf("AccessEntry %lu\n", iIndex); } } } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: DumpAccessW // // Synopsis: Dumps an ACTRL_ACCESSW structure to the screen // // Arguments: [pAccess] -- Structure to dump // // Returns: VOID // //---------------------------------------------------------------------------- VOID DumpAccessW(PACTRL_ACCESSW pAccess) { if(fVerbose) { ULONG iProp, iEnt; printf("\tEntries: %lu\n", pAccess->cEntries); for(iProp = 0; iProp < pAccess->cEntries; iProp++) { printf("\t\tProperty: %ws\n", pAccess->pPropertyAccessList[iProp].lpProperty == NULL ? L"NULL" : pAccess->pPropertyAccessList[iProp].lpProperty); printf("\t\tFlags: %lu\n", pAccess->pPropertyAccessList[iProp].fListFlags); if(pAccess->pPropertyAccessList[iProp].pAccessEntryList == NULL) { printf("\t\tpAccessEntryList: NULL\n"); } else { PACTRL_ACCESS_ENTRYW pAE= pAccess->pPropertyAccessList[iProp]. pAccessEntryList->pAccessList; printf("\t\t\tcEntries: %lu\n", pAccess->pPropertyAccessList[iProp].pAccessEntryList-> cEntries); for(iEnt = 0; iEnt < pAccess->pPropertyAccessList[iProp]. pAccessEntryList->cEntries; iEnt++) { printf("\t\t\tEntry %lu:\n", iEnt); printf("\t\t\t\tTrustee.Name: %ws\n", pAE[iEnt].Trustee.ptstrName); printf("\t\t\t\tfAccessFlags: %lu\n", pAE[iEnt].fAccessFlags); printf("\t\t\t\tAccess: 0x%lx\n", pAE[iEnt].Access); printf("\t\t\t\tProvSpecificAccess: %lu\n", pAE[iEnt].ProvSpecificAccess); printf("\t\t\t\tInheritance: %lu\n", pAE[iEnt].Inheritance); printf("\t\t\t\tlpInheritProperty: %ws\n", pAE[iEnt].lpInheritProperty == NULL ? L"" : pAE[iEnt].lpInheritProperty); } } } } } #define BUILD_COUNT 5 //+--------------------------------------------------------------------------- // // Function: Nt4BuildW // // Synopsis: Builds an ACL using the NT4 API WIDE apis // // Arguments: [ppAcl] -- Acl to build // // Returns: ERROR_SUCCESS -- Everything worked // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt4BuildW(PACL *ppAcl) { DWORD dwErr = ERROR_SUCCESS; ULONG cCount; EXPLICIT_ACCESS_W EAW; PEXPLICIT_ACCESS_W pEAW; PACL pAcl = NULL, pNewAcl; ULONG iIndex, iVer; PWSTR rgTrustees[BUILD_COUNT] = {EVERYONE, SYSTEM, GUEST, EVERYONE, SYSTEM}; DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8, GENERIC_ALL, GENERIC_ALL | 0x8, GENERIC_ALL | 0x8, 0}; ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, DENY_ACCESS, SET_ACCESS, SET_ACCESS, REVOKE_ACCESS}; DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE, SUB_CONTAINERS_AND_OBJECTS_INHERIT, NO_INHERITANCE, SUB_CONTAINERS_AND_OBJECTS_INHERIT}; DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0}, {2, 1, 0}, {3, 1, 2, 0}, {3, 1, 3, 2}, {2, 3, 2}}; if(fVerbose) { printf("Nt4BuildW\n"); } // // We'll do this in a loop, since we have BUILD_COUNT different builds to do // for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++) { // // Build the new entry // BuildExplicitAccessWithNameW(&EAW, rgTrustees[iIndex], rgAccess[iIndex], rgMode[iIndex], rgInherit[iIndex]); dwErr = SetEntriesInAclW(1, &EAW, pAcl, &pNewAcl); if(dwErr == ERROR_SUCCESS) { LocalFree(pAcl); pAcl = pNewAcl; // // Get the explicit entries, and we'll verify them... // dwErr = GetExplicitEntriesFromAclW(pAcl, &cCount, &pEAW); if(dwErr == ERROR_SUCCESS) { PDWORD pSrch = rgSrch[iIndex]; ULONG cExpected = pSrch[0]; if(cCount != cExpected) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tCount mismatched: %lu, expected %lu\n", cCount, cExpected); } } else { // // verify the rest of the data // for(iVer = 0; iVer < cExpected; iVer++) { ULONG iSrch = pSrch[iVer + 1]; if(_wcsicmp(pEAW[iVer].Trustee.ptstrName, rgTrustees[iSrch]) != 0) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tTrustee mismatch[%lu]: %ws, expected " "%ws\n", iVer, pEAW[iVer].Trustee.ptstrName, rgTrustees[iSrch]); } } } } if(dwErr == ERROR_SUCCESS) { if(fVerbose) { printf("\tCount: %lu\n", cCount); } } LocalFree(pEAW); } else { fprintf(stderr, "\tNt4BuildW: SetEntriesInAclW failed with %lu\n", dwErr); } } else { fprintf(stderr,"\tNt4BuildW: SetEntriesInAclW failed with %lu\n", dwErr); } } if(dwErr == ERROR_SUCCESS) { *ppAcl = pAcl; } else { LocalFree(pAcl); } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt4BuildA // // Synopsis: Builds an ACL using the NT4 API ANSI apis // // Arguments: [ppAcl] -- Acl to build // // Returns: ERROR_SUCCESS -- Everything worked // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt4BuildA(PACL *ppAcl) { DWORD dwErr = ERROR_SUCCESS; ULONG cCount; EXPLICIT_ACCESS_A EAA; PEXPLICIT_ACCESS_A pEAA; PACL pAcl = NULL, pNewAcl; ULONG iIndex, iVer; PSTR rgTrustees[BUILD_COUNT] = {EVERYONE_A, SYSTEM_A, GUEST_A, EVERYONE_A, SYSTEM_A}; DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8, GENERIC_ALL, GENERIC_ALL | 0x8, GENERIC_ALL | 0x8, 0}; ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, DENY_ACCESS, SET_ACCESS, SET_ACCESS, REVOKE_ACCESS}; DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE, SUB_CONTAINERS_AND_OBJECTS_INHERIT, NO_INHERITANCE, SUB_CONTAINERS_AND_OBJECTS_INHERIT}; DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0}, {2, 1, 0}, {3, 1, 2, 0}, {3, 1, 3, 2}, {2, 3, 2}}; if(fVerbose) { printf("Nt4BuildA\n"); } // // We'll do this in a loop, since we have BUILD_COUNT different builds to do // for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++) { // // Build the new entry // BuildExplicitAccessWithNameA(&EAA, rgTrustees[iIndex], rgAccess[iIndex], rgMode[iIndex], rgInherit[iIndex]); dwErr = SetEntriesInAclA(1, &EAA, pAcl, &pNewAcl); if(dwErr == ERROR_SUCCESS) { LocalFree(pAcl); pAcl = pNewAcl; // // Get the explicit entries, and we'll verify them... // dwErr = GetExplicitEntriesFromAclA(pAcl, &cCount, &pEAA); if(dwErr == ERROR_SUCCESS) { PDWORD pSrch = rgSrch[iIndex]; ULONG cExpected = pSrch[0]; if(cCount != cExpected) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tCount mismatched: %lu, expected %lu\n", cCount, cExpected); } } else { // // verify the rest of the data // for(iVer = 0; iVer < cExpected; iVer++) { ULONG iSrch = pSrch[iVer + 1]; if(_stricmp(pEAA[iVer].Trustee.ptstrName, rgTrustees[iSrch]) != 0) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tTrustee mismatch[%lu]: %s, expected " "%s\n", iVer, pEAA[iVer].Trustee.ptstrName, rgTrustees[iSrch]); } } } } if(dwErr == ERROR_SUCCESS) { if(fVerbose) { printf("\tCount: %lu\n", cCount); } } LocalFree(pEAA); } else { fprintf(stderr, "\tNt4BuildA: SetEntriesInAclA failed with %lu\n", dwErr); } } else { fprintf(stderr,"\tNt4BuildA: SetEntriesInAclA failed with %lu\n", dwErr); } } if(dwErr == ERROR_SUCCESS) { *ppAcl = pAcl; } else { LocalFree(pAcl); } return(dwErr); } #undef BUILD_COUNT #define BUILD_COUNT 6 //+--------------------------------------------------------------------------- // // Function: Nt5BuildW // // Synopsis: Builds an ACL using the NT5 API WIDE apis // // Arguments: [ppAccess] -- Access list to build // // Returns: ERROR_SUCCESS -- Everything worked // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess) { DWORD dwErr = ERROR_SUCCESS; PACTRL_ACCESSW pAccess = NULL, pNewAccess; ULONG iIndex, iVer; PWSTR rgTrustees[BUILD_COUNT] = {SYSTEM, EVERYONE, SYSTEM, GUEST, EVERYONE, SYSTEM}; DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_DENIED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_DENIED}; DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2}; ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS, GRANT_ACCESS, GRANT_ACCESS, REVOKE_ACCESS}; DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE}; DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0}, {1, 1}, {2, 2, 1}, {3, 2, 3, 1}, {4, 2, 4, 3, 1}, {3, 4, 3, 1}}; if(fVerbose) { printf("Nt5BuildW\n"); } // // We'll do this in a loop, since we have BUILD_COUNT different builds to do // for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++) { ACTRL_ACCESS_ENTRYW AAE; BuildTrusteeWithNameW(&(AAE.Trustee), rgTrustees[iIndex]); AAE.fAccessFlags = rgTypes[iIndex]; AAE.Access = rgAccess[iIndex]; AAE.ProvSpecificAccess = 0; AAE.Inheritance = rgInherit[iIndex]; AAE.lpInheritProperty = NULL; dwErr = SetEntriesInAccessListW(1, &AAE, rgMode[iIndex], NULL, pAccess, &pNewAccess); if(dwErr == ERROR_SUCCESS) { LocalFree(pAccess); pAccess = pNewAccess; } if(dwErr == ERROR_SUCCESS) { // // Now, verify the new entries... // PACTRL_ACCESS_ENTRY_LISTW pAAELW = pAccess->pPropertyAccessList[0].pAccessEntryList; PDWORD pSrch = rgSrch[iIndex]; ULONG cExpected = pSrch[0]; if(pAAELW->cEntries != cExpected) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tCount mismatched: %lu, expected %lu\n", pAAELW->cEntries, cExpected); } } else { // // verify the rest of the data // for(iVer = 0; iVer < pAAELW->cEntries; iVer++) { ULONG iSrch = pSrch[iVer + 1]; if(_wcsicmp(pAAELW->pAccessList[iVer].Trustee.ptstrName, rgTrustees[iSrch]) != 0) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tTrustee mismatch[%lu]: %ws, expected " "%ws\n", iVer, pAAELW->pAccessList[iVer].Trustee.ptstrName, rgTrustees[iSrch]); } } } } if(dwErr == ERROR_SUCCESS) { if(fVerbose) { printf("\tCount: %lu\n", cExpected); } } } else { fprintf(stderr,"\tNt5BuildW: SetEntriesInAccessListW failed " "with %lu\n", dwErr); } } if(dwErr == ERROR_SUCCESS) { *ppAccess = pAccess; } else { LocalFree(pAccess); } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt5BuildA // // Synopsis: Builds an ACL using the NT5 API ANSI apis // // Arguments: [ppAccess] -- Access list to build // // Returns: ERROR_SUCCESS -- Everything worked // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess) { DWORD dwErr = ERROR_SUCCESS; PACTRL_ACCESSA pAccess = NULL, pNewAccess; ULONG iIndex, iVer; PSTR rgTrustees[BUILD_COUNT] = {SYSTEM_A, EVERYONE_A, SYSTEM_A, GUEST_A, EVERYONE_A, SYSTEM_A}; DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_DENIED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_ALLOWED, ACTRL_ACCESS_DENIED}; DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4, ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2}; ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS, GRANT_ACCESS, GRANT_ACCESS, REVOKE_ACCESS}; DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE, NO_INHERITANCE}; DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0}, {1, 1}, {2, 2, 1}, {3, 2, 3, 1}, {4, 2, 4, 3, 1}, {3, 4, 3, 1}}; if(fVerbose) { printf("Nt5BuildA\n"); } // // We'll do this in a loop, since we have BUILD_COUNT different builds to do // for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++) { ACTRL_ACCESS_ENTRYA AAE; BuildTrusteeWithNameA(&(AAE.Trustee), rgTrustees[iIndex]); AAE.fAccessFlags = rgTypes[iIndex]; AAE.Access = rgAccess[iIndex]; AAE.ProvSpecificAccess = 0; AAE.Inheritance = rgInherit[iIndex]; AAE.lpInheritProperty = NULL; dwErr = SetEntriesInAccessListA(1, &AAE, rgMode[iIndex], NULL, pAccess, &pNewAccess); if(dwErr == ERROR_SUCCESS) { LocalFree(pAccess); pAccess = pNewAccess; } if(dwErr == ERROR_SUCCESS) { // // Now, verify the new entries... // PACTRL_ACCESS_ENTRY_LISTA pAAELA = pAccess->pPropertyAccessList[0].pAccessEntryList; PDWORD pSrch = rgSrch[iIndex]; ULONG cExpected = pSrch[0]; if(pAAELA->cEntries != cExpected) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tCount mismatched: %lu, expected %lu\n", pAAELA->cEntries, cExpected); } } else { // // verify the rest of the data // for(iVer = 0; iVer < pAAELA->cEntries; iVer++) { ULONG iSrch = pSrch[iVer + 1]; if(_stricmp(pAAELA->pAccessList[iVer].Trustee.ptstrName, rgTrustees[iSrch]) != 0) { dwErr = ERROR_INVALID_DATA; if(fVerbose) { printf("\tTrustee mismatch[%lu]: %s, expected " "%s\n", iVer, pAAELA->pAccessList[iVer].Trustee.ptstrName, rgTrustees[iSrch]); } } } } if(dwErr == ERROR_SUCCESS) { if(fVerbose) { printf("\tCount: %lu\n", cExpected); } } } else { fprintf(stderr,"\tNt5BuildA: SetEntriesInAccessListA failed " "with %lu\n", dwErr); } } if(dwErr == ERROR_SUCCESS) { *ppAccess = pAccess; } else { LocalFree(pAccess); } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt4DrtW // // Synopsis: Does the actual API drt. This involves reading the existing // access, writing the new one, rereading the new one and // verifing the results, and then restores the old one. This // uses the WIDE version of the NT4 APIs // // Arguments: [pAcl] -- Acl to write on the object // [pszObject] -- The object in question // [ObjType] -- Type of the object // // Returns: ERROR_SUCCESS -- Success // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt4DrtW(PACL pAcl, PSTR pszObject, SE_OBJECT_TYPE ObjType) { DWORD dwErr = ERROR_SUCCESS; WCHAR wszPath[MAX_PATH + 1]; PACL pOldAcl = NULL; PSECURITY_DESCRIPTOR pSD = NULL; mbstowcs(wszPath, pszObject, strlen(pszObject) + 1); if(fVerbose) { printf("Nt4DrtW: Processing %ws [%lu]\n", wszPath, ObjType); } // // First, get the old acl // dwErr = GetNamedSecurityInfoW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldAcl, NULL, &pSD); if(dwErr == ERROR_SUCCESS) { // // Set, get, and compare the new acl... // dwErr = SetNamedSecurityInfoW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL); if(dwErr == ERROR_SUCCESS) { PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR pNewSD = NULL; dwErr = GetNamedSecurityInfoW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pNewAcl, NULL, &pNewSD); if(dwErr == ERROR_SUCCESS) { // // Compare them... // dwErr = CompAcls(pAcl, pNewAcl); if(dwErr != ERROR_SUCCESS) { fprintf(stderr, "\tSet and old ACLs don't compare\n"); } LocalFree(pNewSD); } else { if(fVerbose) { printf("\tSecond GetNamedSecurityW on %ws failed with %lu\n", wszPath, dwErr); } } } else { if(fVerbose) { printf("\tSetNamedSecurityInfoW on %ws failed with %lu\n", wszPath, dwErr); } } } else { fprintf(stderr, "\tGetNamedSecurityInfoW failed on %ws: %lu\n", wszPath, dwErr); } // // Restore the objects security // if(pSD != NULL) { DWORD dwErr2 = SetNamedSecurityInfoW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, pOldAcl, NULL); if(dwErr2 != ERROR_SUCCESS) { fprintf(stderr, "Restoring access to %ws failed with %lu\n", wszPath, dwErr2); } if(dwErr == ERROR_SUCCESS) { dwErr = dwErr2; } } LocalFree(pSD); return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt4DrtA // // Synopsis: Does the actual API drt. This involves reading the existing // access, writing the new one, rereading the new one and // verifing the results, and then restores the old one. This // uses the ANSI version of the NT4 APIs // // Arguments: [pAcl] -- Acl to write on the object // [pszObject] -- The object in question // [ObjType] -- Type of the object // // Returns: ERROR_SUCCESS -- Success // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt4DrtA(PACL pAcl, PSTR pszObject, SE_OBJECT_TYPE ObjType) { DWORD dwErr = ERROR_SUCCESS; PACL pOldAcl = NULL; PSECURITY_DESCRIPTOR pSD = NULL; if(fVerbose) { printf("Nt4DrtA: Processing %s [%lu]\n", pszObject, ObjType); } // // First, get the old acl // dwErr = GetNamedSecurityInfoA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldAcl, NULL, &pSD); if(dwErr == ERROR_SUCCESS) { // // Set, get, and compare the new acl... // dwErr = SetNamedSecurityInfoA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL); if(dwErr == ERROR_SUCCESS) { PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR pNewSD = NULL; dwErr = GetNamedSecurityInfoA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pNewAcl, NULL, &pNewSD); if(dwErr == ERROR_SUCCESS) { // // Compare them... // dwErr = CompAcls(pAcl, pNewAcl); if(dwErr != ERROR_SUCCESS) { fprintf(stderr, "\tSet and old ACLs don't compare\n"); } LocalFree(pNewSD); } else { if(fVerbose) { printf("\tSecond GetNamedSecurityA on %s failed with %lu\n", pszObject, dwErr); } } } else { if(fVerbose) { printf("\tSetNamedSecurityInfoA on %s failed with %lu\n", pszObject, dwErr); } } } else { fprintf(stderr, "\tGetNamedSecurityInfoA failed on %s: %lu\n", pszObject, dwErr); } // // Restore the objects security // if(pSD != NULL) { DWORD dwErr2 = SetNamedSecurityInfoA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, pOldAcl, NULL); if(dwErr2 != ERROR_SUCCESS) { fprintf(stderr, "Restoring access to %s failed with %lu\n", pszObject, dwErr2); } if(dwErr == ERROR_SUCCESS) { dwErr = dwErr2; } } LocalFree(pSD); return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt5DrtW // // Synopsis: Does the actual API drt. This involves reading the existing // access, writing the new one, rereading the new one and // verifing the results, and then restores the old one. This // uses the WIDE version of the NT5 APIs // // Arguments: [pAccess] -- Access list to write on the object // [pszObject] -- The object in question // [ObjType] -- Type of the object // // Returns: ERROR_SUCCESS -- Success // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt5DrtW(PACTRL_ACCESSW pAccess, PSTR pszObject, SE_OBJECT_TYPE ObjType) { DWORD dwErr = ERROR_SUCCESS; WCHAR wszPath[MAX_PATH + 1]; PACTRL_ACCESSW pOldAccess = NULL; mbstowcs(wszPath, pszObject, strlen(pszObject) + 1); if(fVerbose) { printf("Nt5DrtW: Processing %ws [%lu]\n", wszPath, ObjType); } // // First, get the old acl // dwErr = GetNamedSecurityInfoExW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldAccess, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { // // Set, get, and compare the new value... // dwErr = SetNamedSecurityInfoExW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, pAccess, NULL, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { PACTRL_ACCESS pNewAccess = NULL; dwErr = GetNamedSecurityInfoExW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pNewAccess, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { // // Compare them... // dwErr = CompAccessW(pAccess, pNewAccess); if(dwErr != ERROR_SUCCESS) { fprintf(stderr, "\tSet and old Accesses don't compare\n"); } } else { if(fVerbose) { printf("\tSecond GetNamedSecurityExW on %ws failed " "with %lu\n", wszPath, dwErr); } } } else { if(fVerbose) { printf("\tSetNamedSecurityInfoExW on %ws failed with %lu\n", wszPath, dwErr); } } } else { fprintf(stderr, "\tGetNamedSecurityInfoExW failed on %ws: %lu\n", wszPath, dwErr); } // // Restore the objects security // if(pOldAccess != NULL) { DWORD dwErr2 = SetNamedSecurityInfoExW(wszPath, ObjType, DACL_SECURITY_INFORMATION, NULL, pOldAccess, NULL, NULL, NULL, NULL); if(dwErr2 != ERROR_SUCCESS) { fprintf(stderr, "Restoring access to %ws failed with %lu\n", wszPath, dwErr2); } if(dwErr == ERROR_SUCCESS) { dwErr = dwErr2; } } LocalFree(pOldAccess); return(dwErr); } //+--------------------------------------------------------------------------- // // Function: Nt5DrtA // // Synopsis: Does the actual API drt. This involves reading the existing // access, writing the new one, rereading the new one and // verifing the results, and then restores the old one. This // uses the ANSI version of the NT5 APIs // // Arguments: [pAccess] -- Access list to write on the object // [pszObject] -- The object in question // [ObjType] -- Type of the object // // Returns: ERROR_SUCCESS -- Success // ERROR_INVALID_DATA -- One of the compares failed // //---------------------------------------------------------------------------- DWORD Nt5DrtA(PACTRL_ACCESSA pAccess, PSTR pszObject, SE_OBJECT_TYPE ObjType) { DWORD dwErr = ERROR_SUCCESS; PACTRL_ACCESSA pOldAccess = NULL; if(fVerbose) { printf("Nt5DrtA: Processing %s [%lu]\n", pszObject, ObjType); } // // First, get the old acl // dwErr = GetNamedSecurityInfoExA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldAccess, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { // // Set, get, and compare the new value... // dwErr = SetNamedSecurityInfoExA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, pAccess, NULL, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { PACTRL_ACCESSA pNewAccess = NULL; dwErr = GetNamedSecurityInfoExA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, NULL, &pNewAccess, NULL, NULL, NULL); if(dwErr == ERROR_SUCCESS) { // // Compare them... // dwErr = CompAccessA(pAccess, pNewAccess); if(dwErr != ERROR_SUCCESS) { fprintf(stderr, "\tSet and old Accesses don't compare\n"); } } else { if(fVerbose) { printf("\tSecond GetNamedSecurityExA on %s failed " "with %lu\n", pszObject, dwErr); } } } else { if(fVerbose) { printf("\tSetNamedSecurityInfoExA on %s failed with %lu\n", pszObject, dwErr); } } } else { fprintf(stderr, "\tGetNamedSecurityInfoExA failed on %s: %lu\n", pszObject, dwErr); } // // Restore the objects security // if(pOldAccess != NULL) { DWORD dwErr2 = SetNamedSecurityInfoExA(pszObject, ObjType, DACL_SECURITY_INFORMATION, NULL, pOldAccess, NULL, NULL, NULL, NULL); if(dwErr2 != ERROR_SUCCESS) { fprintf(stderr, "Restoring access to %s failed with %lu\n", pszObject, dwErr2); } if(dwErr == ERROR_SUCCESS) { dwErr = dwErr2; } } LocalFree(pOldAccess); // // Finally, try to convert to and from a security descriptor // if(dwErr == ERROR_SUCCESS) { PSECURITY_DESCRIPTOR pSD; dwErr = ConvertAccessToSecurityDescriptorA(pAccess, NULL, "ntds\\macm", NULL, &pSD); if(dwErr != ERROR_SUCCESS) { fprintf(stderr, "ConvertAccessToSecurityDescriptor failed with %lu\n", dwErr); } else { PACTRL_ACCESSA pNewAccess; PSTR pszName; dwErr = ConvertSecurityDescriptorToAccessA(pszObject, ObjType, pSD, &pNewAccess, NULL, &pszName, NULL); if(dwErr == ERROR_SUCCESS) { AccFree(pszName); AccFree(pNewAccess); } else { fprintf(stderr, "ConvertSecurityDescriptorToAccessA failed with %lu\n", dwErr); } LocalFree(pSD); } } return(dwErr); }