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

//+---------------------------------------------------------------------------
//
// 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 <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <aclapi.h>
#include <marta.h>
#include <seopaque.h>
#include <ntrtl.h>
#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);
}