Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2377 lines
63 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1996.
//
// File: FILE.C
//
// Contents: Unit test for file propagation, issues
//
// 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 <seopaque.h>
#include <ntrtl.h>
#define FLAG_ON(flags,bit) ((flags) & (bit))
#define DEFAULT_ACCESS ACTRL_STD_RIGHTS_ALL | ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST
//
// The following is the list of the directory tree to possibly be created
//
PWSTR gpwszTreeList[] = {L"\\dir1", L"\\dir1\\dir2",L"\\dir1\\dir3",
L"\\dir1\\dir2\\dir4", L"\\dir1\\dir3\\dir5",
L"\\dir1\\dir3\\dir6", L"\\dir1\\dir2\\dir4\\dir7",
L"\\dir1\\dir2\\dir4\\dir7\\dir8",
L"\\dir1\\dir2\\dir4\\dir7\\dir9"};
PWSTR gpwszFileList[] = {L"\\dir1\\file1", L"\\dir1\\dir3\\dir6\\file2",
L"\\dir1\\dir2\\dir4\\dir7\\dir9\\file3"};
ULONG cTree = sizeof(gpwszTreeList) / sizeof(PWSTR);
ULONG cFile = sizeof(gpwszFileList) / sizeof(PWSTR);
//
// Flags for tests
//
#define FTEST_READ 0x00000001
#define FTEST_TREE 0x00000002
#define FTEST_INTERRUPT 0x00000004
#define FTEST_COMPRESS 0x00000008
#define FTEST_NOACCESS 0x00000010
#define FTEST_OPENDIR 0x00000020
#define FTEST_COMPRESS2 0x00000040
#define FTEST_PROTECT 0x00000080
#define FTEST_GET3 0x00000100
#define FTEST_GETOWNER 0x00000200
#define RandomIndex(Max) (rand() % (Max))
#define RandomIndexNotRoot(Max) (rand() % (Max - 1) + 1)
#define HANDLE_CLOSE(h) if((h) != NULL) { CloseHandle(h); (h) = NULL;}
DWORD
AddAE (
IN PWSTR pwszUser,
IN ACCESS_RIGHTS AccessRights,
IN INHERIT_FLAGS Inherit,
IN ULONG fAccess,
IN PACTRL_ACCESS pExistingAccess,
OUT PACTRL_ACCESS *ppNewAccess
)
/*++
Routine Description:
Initialize an access entry
Arguments:
pwszUser - User to set
AccessRights - Access rights to set
Inherit - Any inheritance flags
fAccess - Allowed or denied node?
pExistingAccess - Access Entry to add to
ppNewAccess - Where the new access is returned
Return Value:
ERROR_SUCCESS - Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
ACTRL_ACCESS_ENTRY AAE;
BuildTrusteeWithNameW(&(AAE.Trustee),
pwszUser);
AAE.fAccessFlags = fAccess;
AAE.Access = AccessRights;
AAE.ProvSpecificAccess = 0;
AAE.Inheritance = Inherit;
AAE.lpInheritProperty = NULL;
dwErr = SetEntriesInAccessListW(1,
&AAE,
GRANT_ACCESS,
NULL,
pExistingAccess,
ppNewAccess);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to add new access entry: %lu\n", dwErr);
}
return(dwErr);
}
DWORD
BuildTree (
IN PWSTR pwszRoot
)
/*++
Routine Description:
Builds the test tree
Arguments:
pwszRoot - Root directory under which to create the tree
Return Value:
ERROR_SUCCESS - Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
ULONG i;
WCHAR wszPath[MAX_PATH + 1];
HANDLE hFile;
for(i = 0; i < cTree; i++)
{
swprintf(wszPath,
L"%ws%ws",
pwszRoot,
gpwszTreeList[i]);
//
// Now, create the directory...
//
if(CreateDirectory(wszPath, NULL) == FALSE)
{
dwErr = GetLastError();
break;
}
}
//
// If all of that worked, we'll create the files
//
for(i = 0; i < cFile && dwErr == ERROR_SUCCESS; i++)
{
swprintf(wszPath,
L"%ws%ws",
pwszRoot,
gpwszFileList[i]);
hFile = CreateFile(wszPath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
}
else
{
CloseHandle(hFile);
}
}
if(dwErr != ERROR_SUCCESS)
{
printf("FAILED to create %ws: %lu\n",
wszPath,
dwErr);
}
return(dwErr);
}
DWORD
DeleteTree (
IN PWSTR pwszRoot
)
/*++
Routine Description:
Removes the test tree
Arguments:
pwszRoot - Root directory under which the tree was created
Return Value:
VOID
--*/
{
ULONG i;
WCHAR wszPath[MAX_PATH + 1];
DWORD dwErr = ERROR_SUCCESS;
for(i = cFile; i != 0 && dwErr == ERROR_SUCCESS; i--)
{
swprintf(wszPath,
L"%ws%ws",
pwszRoot,
gpwszFileList[i - 1]);
if(DeleteFile(wszPath) == FALSE)
{
dwErr = GetLastError();
printf("FAILED to delete %ws: 0x%lx\n",
wszPath,
dwErr);
break;
}
}
for(i = cTree; i != 0 && dwErr == ERROR_SUCCESS; i--)
{
swprintf(wszPath,
L"%ws%ws",
pwszRoot,
gpwszTreeList[i - 1]);
if(RemoveDirectory(wszPath) == FALSE)
{
dwErr = GetLastError();
if(dwErr == ERROR_PATH_NOT_FOUND || dwErr == ERROR_FILE_NOT_FOUND)
{
dwErr = ERROR_SUCCESS;
}
else
{
printf("FAILED to remove %ws: 0x%lx\n",
wszPath,
GetLastError());
}
}
}
return(dwErr);
}
VOID
Usage (
IN PSTR pszExe
)
/*++
Routine Description:
Displays the usage
Arguments:
pszExe - Name of the exe
Return Value:
VOID
--*/
{
printf("%s path user [/C] [/O] [/I] [/P] [/test] [/H]\n", pszExe);
printf(" where path is the root path to use\n");
printf(" user is the name of a user to set access for\n");
printf(" /test indicates which test to run:\n");
printf(" /READ (Simple read/write)\n");
printf(" /TREE (Propagation of entries through tree)\n");
printf(" /INTERRUPT (Propagation interruptus and continuation)\n");
printf(" /COMPRESS (Compression of access entries)\n");
printf(" /NOACCESS (Propagation across a directory w/ no traverse access)\n");
printf(" /OPENDIR (Propagation with the directory already open\n");
printf(" /COMPRESS2 (Compression of big list of access entries)\n");
printf(" /PROTECT (Protected child acls)\n");
printf(" /GET3 (Get Dacl/Owner/Group)\n");
printf(" /GETOWNER (Get Owner test)\n");
printf(" if test is not specified, all variations are run\n");
printf(" /H indicates to use the handle version of the APIs\n");
printf(" /C is Container Inherit\n");
printf(" /O is Object Inherit\n");
printf(" /I is InheritOnly\n");
printf(" /P is Inherit No Propagate\n");
return;
}
//
// Conceptually, this is a companion function for GetSecurityForPath
//
#define SetSecurityForPath(path,usehandle,handle,access) \
(usehandle == TRUE ? \
SetSecurityInfoExW(handle, \
SE_FILE_OBJECT, \
DACL_SECURITY_INFORMATION, \
NULL, \
access, \
NULL, \
NULL, \
NULL, \
NULL) : \
SetNamedSecurityInfoExW(path, \
SE_FILE_OBJECT, \
DACL_SECURITY_INFORMATION, \
NULL, \
access, \
NULL, \
NULL, \
NULL, \
NULL))
DWORD
GetSecurityForPath (
IN PWSTR pwszPath,
IN BOOL fUseHandle,
IN ULONG OpenFlags,
OUT HANDLE *phObj,
OUT PACTRL_ACCESSW *ppAccess
)
/*++
Routine Description:
Reads the dacl off the specified path
Arguments:
pwszPath -- Path to read
fUseHandle -- Use handle or path based API
OpenFlags -- Flags to use if opening the object
phObj -- Handle to object
ppAccess -- Where the access is returned
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
if(fUseHandle == TRUE)
{
//
// Open the object
//
if(*phObj == NULL)
{
*phObj = CreateFile(pwszPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
OpenFlags | READ_CONTROL | WRITE_DAC,
NULL);
if(*phObj == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
*phObj = NULL;
}
}
if(dwErr == ERROR_SUCCESS)
{
dwErr = GetSecurityInfoExW(*phObj,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
ppAccess,
NULL,
NULL,
NULL);
if(dwErr != ERROR_SUCCESS)
{
HANDLE_CLOSE(*phObj);
}
}
}
else
{
dwErr = GetNamedSecurityInfoExW(pwszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
ppAccess,
NULL,
NULL,
NULL);
if(phObj != NULL)
{
*phObj = NULL;
}
}
return(dwErr);
}
DWORD
VerifyTreeSet (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit
)
/*++
Routine Description:
Reads the dacl off the specified path
Arguments:
pwszPath -- Root path to verify
pwszUser -- User to verify
Inherit -- Expected inheritance
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[3][MAX_PATH];
INT i,j;
PACTRL_ACCESSW pAccess;
PACTRL_ACCESS_ENTRYW pAE;
BOOL fInNoP = FALSE;
if(FLAG_ON(Inherit, INHERIT_NO_PROPAGATE))
{
fInNoP = TRUE;
}
//
// Now, verify it...
//
if(fInNoP == TRUE)
{
i = rand() % 2 + 1;
}
else
{
i = RandomIndexNotRoot(cTree);
}
swprintf(rgwszPaths[0],
L"%ws%ws",
pwszPath,
gpwszTreeList[i]);
if(fInNoP == TRUE)
{
i = 0;
}
else
{
i = RandomIndex(cFile);
}
swprintf(rgwszPaths[1],
L"%ws%ws",
pwszPath,
gpwszFileList[i]);
//
// Finally, if this is an inherit, no propagate, check one of the
// leaf entries for non-compliance
//
if(fInNoP == TRUE)
{
i = rand() % 6 + 3;
swprintf(rgwszPaths[2],
L"%ws%ws",
pwszPath,
gpwszTreeList[i]);
Inherit &= ~(SUB_CONTAINERS_AND_OBJECTS_INHERIT);
}
for(i = 0; i < (fInNoP == TRUE ? 3 : 2) && dwErr == ERROR_SUCCESS; i++)
{
//
// Get the security off the node, find the entry we added, and verify
// that the entry is correct
//
dwErr = GetSecurityForPath(rgwszPaths[i],
FALSE,
FILE_FLAG_BACKUP_SEMANTICS,
NULL,
&pAccess);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
rgwszPaths[i], dwErr);
break;
}
pAE = NULL;
for(j = 0;
j < (INT)pAccess->pPropertyAccessList[0].pAccessEntryList->cEntries;
j++)
{
if(_wcsicmp(pwszUser,
pAccess->pPropertyAccessList[0].pAccessEntryList->
pAccessList[j].Trustee.ptstrName) == 0)
{
pAE = &(pAccess->pPropertyAccessList[0].pAccessEntryList->
pAccessList[j]);
break;
}
}
if(pAE == NULL)
{
if((i == 0 && FLAG_ON(Inherit,SUB_CONTAINERS_ONLY_INHERIT)) ||
(i == 1 && FLAG_ON(Inherit,SUB_OBJECTS_ONLY_INHERIT)))
{
printf(" FAILED to find entry for %ws on path %ws\n",
pwszUser, rgwszPaths[i]);
dwErr = ERROR_INVALID_FUNCTION;
}
}
else
{
//
// Verify that the info is correct
//
if(!FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY))
{
printf(" Access entry on %ws is not inherited!\n",
rgwszPaths[i]);
dwErr = ERROR_INVALID_FUNCTION;
}
if(i == 0)
{
if(FLAG_ON(Inherit, SUB_CONTAINERS_ONLY_INHERIT) &&
!FLAG_ON(pAE->Inheritance, SUB_CONTAINERS_ONLY_INHERIT))
{
printf(" No container inherit on %ws!\n",
rgwszPaths[i]);
dwErr = ERROR_INVALID_FUNCTION;
}
}
else if(i == 1)
{
if(FLAG_ON(Inherit, SUB_OBJECTS_ONLY_INHERIT) &&
FLAG_ON(pAE->Inheritance, SUB_OBJECTS_ONLY_INHERIT))
{
printf(" Object inherit bit on object on %ws!\n",
rgwszPaths[i]);
dwErr = ERROR_INVALID_FUNCTION;
}
}
else
{
printf(" Inherit No Propagate node found on child %ws\n",
rgwszPaths[i]);
dwErr = ERROR_INVALID_FUNCTION;
}
}
if(dwErr == ERROR_SUCCESS)
{
printf(" Successfully verified %ws\n", rgwszPaths[i]);
}
LocalFree(pAccess);
}
return(dwErr);
}
DWORD
DoReadTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the simple read test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[2][MAX_PATH];
INT i;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj;
ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
printf("Simple read/write test\n");
swprintf(rgwszPaths[0],
L"%ws%ws",
pwszPath,
gpwszTreeList[RandomIndex(cTree)]);
swprintf(rgwszPaths[1],
L"%ws%ws",
pwszPath,
gpwszFileList[RandomIndex(cFile)]);
for(i = 0; i < 2; i++)
{
printf(" Processing path %ws\n", rgwszPaths[i]);
hObj = NULL;
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
//
// Ok, now add the entry for our user
//
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
0,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it
//
dwErr = SetSecurityForPath(rgwszPaths[i],
fDoHandle,
hObj,pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" Set FAILED: %lu\n", dwErr);
}
LocalFree(pNew);
}
//
// If that worked, reread the new security, and see if it's correct
//
if(dwErr == ERROR_SUCCESS)
{
HANDLE_CLOSE(hObj);
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
//
// We should only have one property, so cheat...
//
ULONG cExpected = 1 + pCurrent->pPropertyAccessList[0].
pAccessEntryList->cEntries;
ULONG cGot = pNew->pPropertyAccessList[0].
pAccessEntryList->cEntries;
if(cExpected != cGot)
{
printf(" Expected %lu entries, got %lu\n",
cExpected, cGot);
dwErr = ERROR_INVALID_FUNCTION;
}
LocalFree(pNew);
}
//
// Restore the current security
//
SetNamedSecurityInfoExW(rgwszPaths[i],
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
}
LocalFree(pCurrent);
}
HANDLE_CLOSE(hObj);
if(dwErr != ERROR_SUCCESS)
{
break;
}
}
return(dwErr);
}
DWORD
DoTreeTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the simple tree test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
Inherit -- Inheritance flags
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
INT i,j;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj = NULL;
WCHAR wszPath[MAX_PATH + 1];
WCHAR rgwszPaths[2][MAX_PATH];
PACTRL_ACCESS_ENTRYW pAE;
printf("Tree propagation test\n");
swprintf(wszPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[0]);
//
// Set the access on the root, and then we'll read the child and look for
// the appropratie access
//
dwErr = GetSecurityForPath(wszPath,
fDoHandle,
FILE_FLAG_BACKUP_SEMANTICS,
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
wszPath, dwErr);
return(dwErr);
}
//
// Ok, add the access
//
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
Inherit,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it
//
dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
if(dwErr != ERROR_SUCCESS)
{
printf("Set FAILED: %lu\n", dwErr);
}
LocalFree(pNew);
}
dwErr = VerifyTreeSet(pwszPath,
pwszUser,
Inherit);
if(dwErr != ERROR_SUCCESS)
{
printf(" VerifyTreeSet FAILED with %lu\n", dwErr);
}
//
// Restore the current security
//
dwErr2 = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszPath, dwErr2);
}
LocalFree(pCurrent);
HANDLE_CLOSE(hObj);
return(dwErr);
}
DWORD
DoInterruptTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the interrupt tree/repeat tree test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
Inherit -- Inheritance flags
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj = NULL;
WCHAR wszPath[MAX_PATH + 1];
ACTRL_OVERLAPPED Overlapped;
printf("Tree propagation with interruption\n");
swprintf(wszPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[0]);
//
// Set the access on the root, and then we'll read the child and look for
// the appropratie access
//
dwErr = GetSecurityForPath(wszPath,
fDoHandle,
FILE_FLAG_BACKUP_SEMANTICS,
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
wszPath, dwErr);
return(dwErr);
}
//
// Ok, add the access
//
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
Inherit,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it, interrupt it, and set it again
//
if(fDoHandle == TRUE)
{
dwErr = SetSecurityInfoExW(hObj,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pNew,
NULL,
NULL,
NULL,
&Overlapped);
}
else
{
dwErr = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pNew,
NULL,
NULL,
NULL,
&Overlapped);
}
//
// Immeadiately cancel it...
//
if(dwErr == ERROR_SUCCESS)
{
WaitForSingleObject(Overlapped.hEvent,
100);
dwErr = CancelOverlappedAccess(&Overlapped);
if(dwErr != ERROR_SUCCESS)
{
printf("Cancel FAILED with %lu\n", dwErr);
}
}
//
// Now, reset it and verify it
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
if(dwErr != ERROR_SUCCESS)
{
printf("Set FAILED: %lu\n", dwErr);
}
}
LocalFree(pNew);
}
dwErr = VerifyTreeSet(pwszPath,
pwszUser,
Inherit);
if(dwErr != ERROR_SUCCESS)
{
printf(" VerifyTreeSet FAILED with %lu\n", dwErr);
}
//
// Restore the current security
//
dwErr2 = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszPath, dwErr2);
}
LocalFree(pCurrent);
HANDLE_CLOSE(hObj);
return(dwErr);
}
DWORD
DoCompressTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the entry compression test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
fDoHandle -- Do the handle based API
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[2][MAX_PATH];
INT i,j;
ULONG cOrigCnt;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj;
ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
ACCESS_RIGHTS Rights[] = {ACTRL_DELETE,
ACTRL_READ_CONTROL,
ACTRL_CHANGE_ACCESS,
ACTRL_CHANGE_OWNER,
ACTRL_SYNCHRONIZE,
ACTRL_STD_RIGHTS_ALL};
printf("Entry compression test\n");
swprintf(rgwszPaths[0],
L"%ws%ws",
pwszPath,
gpwszTreeList[RandomIndex(cTree)]);
swprintf(rgwszPaths[1],
L"%ws%ws",
pwszPath,
gpwszFileList[RandomIndex(cFile)]);
for(i = 0; i < 2; i++)
{
cOrigCnt = 0;
printf(" Processing path %ws\n", rgwszPaths[i]);
for(j = 0; j < sizeof(Rights) / sizeof(ACCESS_RIGHTS); j++)
{
hObj = NULL;
printf(" Processing right 0x%lx\n", Rights[j]);
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
if(cOrigCnt == 0)
{
cOrigCnt = pCurrent->pPropertyAccessList[0].
pAccessEntryList->cEntries;
}
//
// Ok, now add the entry for our user
//
dwErr = AddAE(pwszUser,
Rights[0] | ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST,
0,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it
//
dwErr = SetSecurityForPath(rgwszPaths[i], fDoHandle,
hObj, pNew);
if(dwErr != ERROR_SUCCESS)
{
printf("Set FAILED: %lu\n", dwErr);
}
LocalFree(pNew);
}
//
// If that worked, reread the new security, and see if it's
// correct
//
if(dwErr == ERROR_SUCCESS)
{
HANDLE_CLOSE(hObj);
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
//
// We should only have one property, so cheat...
//
ULONG cGot = pNew->pPropertyAccessList[0].
pAccessEntryList->cEntries;
if(cOrigCnt + 1 != cGot)
{
printf(" Expected %lu entries, got %lu\n",
cOrigCnt + 1, cGot);
dwErr = ERROR_INVALID_FUNCTION;
}
LocalFree(pNew);
}
//
// Restore the current security
//
SetNamedSecurityInfoExW(rgwszPaths[i],
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
}
LocalFree(pCurrent);
}
HANDLE_CLOSE(hObj);
if(dwErr != ERROR_SUCCESS)
{
break;
}
}
}
return(dwErr);
}
DWORD
DoCompress2Test (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the big list entry compression test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
fDoHandle -- Do the handle based API
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[2][MAX_PATH];
INT i,j;
ULONG cOrigCnt;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj;
ULONG OpenFlags[] = {FILE_FLAG_BACKUP_SEMANTICS, 0};
ACCESS_RIGHTS Rights[] = {ACTRL_DELETE,
ACTRL_READ_CONTROL,
ACTRL_CHANGE_ACCESS,
ACTRL_CHANGE_OWNER,
ACTRL_SYNCHRONIZE,
ACTRL_STD_RIGHTS_ALL,
ACTRL_DIR_TRAVERSE | ACTRL_DIR_LIST};
INT cItems = sizeof(Rights) / sizeof(ACCESS_RIGHTS);
ACTRL_ACCESS_ENTRY AAEList[sizeof(Rights) / sizeof(ACCESS_RIGHTS)];
PACTRL_ACCESS_ENTRY pAE;
printf("Entry compression test\n");
swprintf(rgwszPaths[0],
L"%ws%ws",
pwszPath,
gpwszTreeList[RandomIndex(cTree)]);
swprintf(rgwszPaths[1],
L"%ws%ws",
pwszPath,
gpwszFileList[RandomIndex(cFile)]);
for(i = 0; i < 2; i++)
{
printf(" Processing path %ws\n", rgwszPaths[i]);
cOrigCnt = 0;
hObj = NULL;
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
if(cOrigCnt == 0)
{
cOrigCnt = pCurrent->pPropertyAccessList[0].
pAccessEntryList->cEntries;
}
//
// Ok, now add the entries for our user
//
for(j = 0; j < sizeof(Rights) / sizeof(ACCESS_RIGHTS); j++)
{
printf(" Processing right 0x%lx\n", Rights[j]);
BuildTrusteeWithNameW(&(AAEList[j].Trustee),
pwszUser);
AAEList[j].fAccessFlags = ACTRL_ACCESS_ALLOWED;
AAEList[j].Access = Rights[j];
AAEList[j].ProvSpecificAccess = 0;
AAEList[j].Inheritance = 0;
AAEList[j].lpInheritProperty = NULL;
}
//
// Now, add 'em
//
dwErr = SetEntriesInAccessListW(cItems,
AAEList,
GRANT_ACCESS,
NULL,
pCurrent,
&pNew);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it
//
dwErr = SetSecurityForPath(rgwszPaths[i], fDoHandle,
hObj, pNew);
if(dwErr != ERROR_SUCCESS)
{
printf("Set FAILED: %lu\n", dwErr);
}
LocalFree(pNew);
}
//
// If that worked, reread the new security, and see if it's
// correct
//
if(dwErr == ERROR_SUCCESS)
{
HANDLE_CLOSE(hObj);
dwErr = GetSecurityForPath(rgwszPaths[i],
fDoHandle,
OpenFlags[i],
&hObj,
&pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to read the 2nd DACL off %ws: %lu\n",
rgwszPaths[i], dwErr);
}
else
{
//
// We should only have one property, so cheat...
//
ULONG cGot = pNew->pPropertyAccessList[0].
pAccessEntryList->cEntries;
if(cOrigCnt + 1 != cGot)
{
printf(" Expected %lu entries, got %lu\n",
cOrigCnt + 1, cGot);
dwErr = ERROR_INVALID_FUNCTION;
}
else
{
//
// Find the added entry...
//
pAE = NULL;
for(j = 0;
j < (INT)pNew->pPropertyAccessList[0].
pAccessEntryList->cEntries;
j++)
{
if(_wcsicmp(pwszUser,
pNew->pPropertyAccessList[0].
pAccessEntryList->pAccessList[j].
Trustee.ptstrName) == 0)
{
pAE = &(pNew->pPropertyAccessList[0].
pAccessEntryList->pAccessList[j]);
break;
}
}
if(pAE == NULL)
{
printf(" Couldn't find entry for %ws\n", pwszUser);
dwErr = ERROR_INVALID_FUNCTION;
}
else
{
ACCESS_RIGHTS ExpectedAR = 0;
for(j = 0; j < cItems; j++)
{
ExpectedAR |= Rights[j];
}
if(pAE->Access != ExpectedAR)
{
printf(" Expected compressed rights of 0x%lx, not 0x%lx\n",
ExpectedAR, pAE->Access);
dwErr = ERROR_INVALID_FUNCTION;
}
}
}
LocalFree(pNew);
}
//
// Restore the current security
//
SetNamedSecurityInfoExW(rgwszPaths[i],
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
}
LocalFree(pCurrent);
}
HANDLE_CLOSE(hObj);
if(dwErr != ERROR_SUCCESS)
{
break;
}
}
return(dwErr);
}
DWORD
DoNoAccessTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the NoAccess tree test, where some child node does not have access
to its children
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
Inherit -- Inheritance flags
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
INT i,j, iChild;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pCurrentChild;
PACTRL_ACCESS pNew;
PACTRL_ACCESS pNewChild;
HANDLE hObj = NULL;
HANDLE hChildObj = NULL;
WCHAR wszPath[MAX_PATH + 1];
WCHAR wszChildPath[MAX_PATH + 1];
WCHAR rgwszPaths[2][MAX_PATH];
PACTRL_ACCESS_ENTRYW pAE;
PSECURITY_DESCRIPTOR pSD;
printf("NoAccess Tree test\n");
swprintf(wszPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[0]);
iChild = RandomIndexNotRoot(cTree);
if(iChild == (INT)(cTree - 1))
{
iChild--;
}
//
// Set the access on the root, and then we'll read the child and look for
// the appropratie access
//
dwErr = GetSecurityForPath(wszPath,
fDoHandle,
FILE_FLAG_BACKUP_SEMANTICS,
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
wszPath, dwErr);
return(dwErr);
}
else
{
swprintf(wszChildPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[iChild]);
dwErr = GetSecurityForPath(wszChildPath,
fDoHandle,
FILE_FLAG_BACKUP_SEMANTICS,
&hChildObj,
&pCurrentChild);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
wszPath, dwErr);
HANDLE_CLOSE(hObj);
LocalFree(pCurrent);
return(dwErr);
}
}
//
// Ok, add the access to the child
//
dwErr = AddAE(L"Everyone",
ACTRL_DIR_LIST | ACTRL_DIR_TRAVERSE,
0,
ACTRL_ACCESS_DENIED,
pCurrentChild,
&pNewChild);
if(dwErr == ERROR_SUCCESS)
{
//
// Set it
//
dwErr = SetSecurityForPath(wszChildPath,fDoHandle,hChildObj,pNewChild);
if(dwErr != ERROR_SUCCESS)
{
printf("Child set FAILED: %lu\n", dwErr);
}
LocalFree(pNewChild);
}
if(dwErr == ERROR_SUCCESS)
{
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
Inherit,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
//
// Set it
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
if(dwErr != ERROR_SUCCESS)
{
printf("Set returned %lu as expected\n", dwErr);
if(dwErr == ERROR_ACCESS_DENIED)
{
dwErr = ERROR_SUCCESS;
}
}
else
{
printf("Set succeeded when it should have FAILED!\n");
dwErr = ERROR_INVALID_FUNCTION;
}
}
LocalFree(pNew);
}
//
// Restore the current child security. Use the old APIs so we don't
// end up trying to do propagation
//
dwErr2 = ConvertAccessToSecurityDescriptor(pCurrentChild,
NULL,
NULL,
NULL,
&pSD);
if(dwErr2 == ERROR_SUCCESS)
{
if(SetFileSecurity(wszChildPath,
DACL_SECURITY_INFORMATION,
pSD) == FALSE)
{
dwErr2 = GetLastError();
printf("SetFileSecurity on %ws FAILED with %lu\n",
wszChildPath, dwErr2);
}
LocalFree(pSD);
}
else
{
printf("ConvertAccessToSecurityDescriptor FAILED with %lu\n",
dwErr2);
}
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszChildPath, dwErr2);
}
LocalFree(pCurrentChild);
//
// Restore the current security
//
dwErr2 = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszPath, dwErr2);
}
LocalFree(pCurrent);
HANDLE_CLOSE(hObj);
HANDLE_CLOSE(hChildObj);
return(dwErr);
}
DWORD
DoOpenDirTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the OpenDir tree test, where some child node has been opened
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
Inherit -- Inheritance flags
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
INT i,iChild;
PACTRL_ACCESS pCurrent;
PACTRL_ACCESS pNew;
HANDLE hObj = NULL;
HANDLE hChild = NULL;
WCHAR wszPath[MAX_PATH + 1];
WCHAR wszChildPath[MAX_PATH + 1];
ULONG ShareFlags[] = {0, FILE_SHARE_WRITE, FILE_SHARE_READ};
PSTR rgszShareFlags[] = {"None", "Write", "Read"};
ULONG ExpectedReturn[] = {ERROR_SHARING_VIOLATION,
ERROR_SHARING_VIOLATION,
ERROR_SUCCESS};
printf("Open Directory test\n");
swprintf(wszPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[0]);
iChild = RandomIndex(cTree);
//
// Set the access on the root, and then we'll read the child and look for
// the appropratie access
//
dwErr = GetSecurityForPath(wszPath,
fDoHandle,
FILE_FLAG_BACKUP_SEMANTICS,
&hObj,
&pCurrent);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED to get the security for %ws: %lu\n",
wszPath, dwErr);
return(dwErr);
}
else
{
swprintf(wszChildPath,
L"%ws%ws",
pwszPath,
gpwszTreeList[iChild]);
}
//
// Do this through all our flags
//
for(i = 0;
i < sizeof(ShareFlags) / sizeof(ULONG) && dwErr == ERROR_SUCCESS;
i++)
{
printf(" Opening %ws with share flags %s\n",
wszChildPath, rgszShareFlags[i]);
//
// Open the child
//
hChild = CreateFile(wszChildPath,
GENERIC_READ | GENERIC_WRITE,
ShareFlags[i],
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if(hChild == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
}
//
// Create the new entry
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
Inherit,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
//
// Set it
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
if(dwErr == ExpectedReturn[i])
{
printf(" Set returned %lu as expected\n", dwErr);
dwErr = ERROR_SUCCESS;
}
else
{
printf(" Set returned an unexpected %lu instead of %lu!\n",
dwErr, ExpectedReturn[i]);
if(dwErr == ERROR_SUCCESS)
{
dwErr = ERROR_INVALID_FUNCTION;
}
}
}
LocalFree(pNew);
}
HANDLE_CLOSE(hChild);
}
//
// Restore the current security
//
dwErr2 = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszPath, dwErr2);
}
LocalFree(pCurrent);
HANDLE_CLOSE(hObj);
return(dwErr);
}
DWORD
DoProtectedTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN INHERIT_FLAGS Inherit,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the protected child test.
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
Inherit -- Inheritance flags
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
WCHAR wszPath[MAX_PATH + 1];
WCHAR wszChildPath[MAX_PATH + 1];
PACTRL_ACCESS pCurrent, pCurrentChild, pNew;
HANDLE hObj = NULL;
printf("Propagation with protected child test\n");
//
// Pick a file
//
swprintf(wszChildPath,
L"%ws%ws",
pwszPath,
gpwszFileList[RandomIndex(cFile)]);
//
// Build the parent
//
wcscpy(wszPath, wszChildPath);
*(wcsrchr(wszPath, L'\\')) = L'\0';
//
// Get the current security off of both
//
dwErr = GetSecurityForPath(wszPath, fDoHandle, FILE_FLAG_BACKUP_SEMANTICS, &hObj, &pCurrent);
if(dwErr == ERROR_SUCCESS)
{
dwErr = GetSecurityForPath(wszChildPath, FALSE, 0, NULL, &pCurrentChild);
if(dwErr != ERROR_SUCCESS)
{
LocalFree(pCurrent);
}
}
if(dwErr == ERROR_SUCCESS)
{
//
// Set a NULL security descriptor on child
//
SECURITY_DESCRIPTOR SD;
InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&SD, TRUE, NULL, FALSE);
//
// Stamp it on the object directly
//
if(SetFileSecurity(wszChildPath, DACL_SECURITY_INFORMATION, &SD) == FALSE)
{
dwErr = GetLastError();
printf(" Setting NULL DACL on %ws FAILED with %lu\n", wszChildPath, dwErr);
}
}
else
{
printf(" FAILED to read the security: %lu\n", dwErr);
return(dwErr);
}
//
// Ok, now we'll set on the parent, and then look at the child
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = AddAE(pwszUser,
DEFAULT_ACCESS,
Inherit,
ACTRL_ACCESS_ALLOWED,
pCurrent,
&pNew);
//
// Set it
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = SetSecurityForPath(wszPath,fDoHandle,hObj,pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" Setting security on %ws FAILED with %lu\n", wszPath, dwErr);
}
LocalFree(pNew);
}
}
//
// Now, if all of that worked, we'll read the security off the child, and make sure that
// it is correct
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = GetSecurityForPath(wszChildPath, FALSE, 0, NULL, &pNew);
if(dwErr != ERROR_SUCCESS)
{
printf(" GetSecurity on child %ws FAILED with %lu\n", wszChildPath, dwErr);
}
else
{
//
// We should have a protected acl and an empty list
//
ASSERT(pNew->pPropertyAccessList != NULL);
if(!FLAG_ON(pNew->pPropertyAccessList[0].fListFlags, ACTRL_ACCESS_PROTECTED))
{
printf(" Child list not protected\n");
dwErr = ERROR_INVALID_FUNCTION;
}
if(pNew->pPropertyAccessList[0].pAccessEntryList != NULL)
{
printf(" Child list not NULL\n");
dwErr = ERROR_INVALID_FUNCTION;
}
}
}
//
// Restore the current security, child first
//
dwErr2 = SetNamedSecurityInfoExW(wszChildPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrentChild,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszChildPath, dwErr2);
}
dwErr2 = SetNamedSecurityInfoExW(wszPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
pCurrent,
NULL,
NULL,
NULL,
NULL);
if(dwErr2 != ERROR_SUCCESS)
{
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
printf("FAILED to restore the security for %ws: %lu\n",
wszPath, dwErr2);
}
LocalFree(pCurrent);
LocalFree(pCurrentChild);
HANDLE_CLOSE(hObj);
return(dwErr);
}
DWORD
DoGet3Test (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN BOOL fDoHandle
)
/*++
Routine Description:
Does the simple read test
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[MAX_PATH];
PACTRL_ACCESS pAccessList = NULL, pAuditList = NULL;
LPWSTR lpOwner = NULL, lpGroup = NULL;
ULONG SeInfo = DACL_SECURITY_INFORMATION;
printf("Get3 Test\n");
swprintf(rgwszPaths,
L"%ws%ws",
pwszPath,
gpwszTreeList[RandomIndex(cTree)]);
printf(" Processing path %ws\n", rgwszPaths);
if(rand() % 2 == 1)
{
SeInfo |= OWNER_SECURITY_INFORMATION;
}
if(rand() % 2 == 1 || SeInfo == DACL_SECURITY_INFORMATION)
{
SeInfo |= GROUP_SECURITY_INFORMATION;
}
dwErr = GetNamedSecurityInfoEx( rgwszPaths, SE_FILE_OBJECT,
SeInfo,
NULL,NULL,&pAccessList,&pAuditList,
&lpOwner,&lpGroup);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED: %lu\n", dwErr);
}
else
{
printf(" SeInfo: %lu\n", SeInfo);
if ((SeInfo & OWNER_SECURITY_INFORMATION) != 0) {
printf(" Owner: %ws\n", lpOwner);
LocalFree(lpOwner);
}
if ((SeInfo & GROUP_SECURITY_INFORMATION) != 0) {
printf(" Group: %ws\n", lpGroup);
LocalFree(lpGroup);
}
LocalFree(pAccessList);
LocalFree(pAuditList);
}
return(dwErr);
}
DWORD
DoGetOwnerTest (
IN PWSTR pwszPath,
IN PWSTR pwszUser,
IN BOOL fDoHandle
)
/*++
Routine Description:
Gets the owner from a file
Arguments:
pwszPath -- Root path
pwszUser -- User to run with
fDoHandle -- If true, use the handle based APIs
Return Value:
ERROR_SUCCESS -- Success
--*/
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR rgwszPaths[MAX_PATH];
PACTRL_ACCESS pAccessList = NULL, pAuditList = NULL;
LPWSTR lpOwner = NULL, lpGroup = NULL;
ULONG SeInfo = DACL_SECURITY_INFORMATION;
printf("GetOwner Test\n");
swprintf(rgwszPaths,
L"%ws%ws",
pwszPath,
gpwszTreeList[RandomIndex(cTree)]);
printf(" Processing path %ws\n", rgwszPaths);
dwErr = GetNamedSecurityInfoEx( rgwszPaths, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
NULL,NULL,&pAccessList,&pAuditList,
&lpOwner,&lpGroup);
if(dwErr != ERROR_SUCCESS)
{
printf(" FAILED: %lu\n", dwErr);
}
else
{
printf(" Owner: %ws\n", lpOwner);
LocalFree(lpOwner);
}
return(dwErr);
}
__cdecl main (
IN INT argc,
IN CHAR *argv[])
/*++
Routine Description:
The main
Arguments:
argc -- Count of arguments
argv -- List of arguments
Return Value:
0 -- Success
non-0 -- Failure
--*/
{
DWORD dwErr = ERROR_SUCCESS, dwErr2;
WCHAR wszPath[MAX_PATH + 1];
WCHAR wszUser[MAX_PATH + 1];
INHERIT_FLAGS Inherit = 0;
ULONG Tests = 0;
INT i;
BOOL fHandle = FALSE;
srand((ULONG)(GetTickCount() * GetCurrentThreadId()));
if(argc < 3)
{
Usage(argv[0]);
exit(1);
}
mbstowcs(wszPath, argv[1], strlen(argv[1]) + 1);
mbstowcs(wszUser, argv[2], strlen(argv[2]) + 1);
//
// process the command line
//
for(i = 3; i < argc; i++)
{
if(_stricmp(argv[i], "/h") == 0)
{
fHandle = TRUE;
}
else if(_stricmp(argv[i],"/C") == 0)
{
Inherit |= SUB_CONTAINERS_ONLY_INHERIT;
}
else if(_stricmp(argv[i],"/O") == 0)
{
Inherit |= SUB_OBJECTS_ONLY_INHERIT;
}
else if(_stricmp(argv[i],"/I") == 0)
{
Inherit |= INHERIT_ONLY;
}
else if(_stricmp(argv[i],"/P") == 0)
{
Inherit |= INHERIT_NO_PROPAGATE;
}
else if(_stricmp(argv[i],"/READ") == 0)
{
Tests |= FTEST_READ;
}
else if(_stricmp(argv[i],"/TREE") == 0)
{
Tests |= FTEST_TREE;
}
else if(_stricmp(argv[i],"/INTERRUPT") == 0)
{
Tests |= FTEST_INTERRUPT;
}
else if(_stricmp(argv[i],"/COMPRESS") == 0)
{
Tests |= FTEST_COMPRESS;
}
else if(_stricmp(argv[i],"/NOACCESS") == 0)
{
Tests |= FTEST_NOACCESS;
}
else if(_stricmp(argv[i],"/OPENDIR") == 0)
{
Tests |= FTEST_OPENDIR;
}
else if(_stricmp(argv[i],"/COMPRESS2") == 0)
{
Tests |= FTEST_COMPRESS2;
}
else if(_stricmp(argv[i],"/PROTECT") == 0)
{
Tests |= FTEST_PROTECT;
}
else if(_stricmp(argv[i],"/GET3") == 0)
{
Tests |= FTEST_GET3;
}
else if(_stricmp(argv[i],"/GETOWNER") == 0)
{
Tests |= FTEST_GETOWNER;
}
else
{
Usage(argv[0]);
exit(1);
break;
}
}
if(Tests == 0)
{
Tests = FTEST_READ |
FTEST_TREE |
FTEST_INTERRUPT |
FTEST_COMPRESS |
FTEST_NOACCESS |
FTEST_OPENDIR |
FTEST_COMPRESS2 |
FTEST_PROTECT |
FTEST_GET3 |
FTEST_GETOWNER;
}
//
// Build the tree
//
dwErr = BuildTree(wszPath);
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_READ))
{
dwErr = DoReadTest(wszPath, wszUser, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_TREE))
{
dwErr = DoTreeTest(wszPath, wszUser, Inherit, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_INTERRUPT))
{
dwErr = DoInterruptTest(wszPath, wszUser, Inherit, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_COMPRESS))
{
dwErr = DoCompressTest(wszPath, wszUser, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_NOACCESS))
{
dwErr = DoNoAccessTest(wszPath, wszUser, Inherit, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_OPENDIR))
{
dwErr = DoOpenDirTest(wszPath, wszUser, Inherit, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_COMPRESS2))
{
dwErr = DoCompress2Test(wszPath, wszUser, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_PROTECT))
{
dwErr = DoProtectedTest(wszPath, wszUser, Inherit, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_GET3))
{
dwErr = DoGet3Test(wszPath, wszUser, fHandle);
}
if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, FTEST_GETOWNER))
{
dwErr = DoGetOwnerTest(wszPath, wszUser, fHandle);
}
dwErr2 = DeleteTree(wszPath);
if(dwErr2 != ERROR_SUCCESS)
{
printf("FAILED to delete the tree: %lu\n", dwErr);
if(dwErr == ERROR_SUCCESS)
{
dwErr = dwErr2;
}
}
printf("%s\n", dwErr == ERROR_SUCCESS ?
"success" :
"failed");
return(dwErr);
}