|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1996.
//
// File: MARTABAS.CXX
//
// Contents: Implementation of the base MARTA funcitons
//
// History: 22-Jul-96 MacM Created
//
//----------------------------------------------------------------------------
#include <aclpch.hxx>
#pragma hdrstop
#include <ntprov.hxx>
#include <strings.h>
#include <ntdsguid.h>
CSList gWrkrList(NtProvFreeWorkerItem); // List of active worker threads
//+---------------------------------------------------------------------------
//
// Function: AccProvGetCapabilities
//
// Synopsis: Gets the provider capabilities
//
// Arguments: [IN fClass] -- Class of capabilities to request
// [OUT pulCaps] -- Provider capabilities
//
// Returns: VOID
//
// Notes:
//
//----------------------------------------------------------------------------
VOID WINAPI AccProvGetCapabilities(IN ULONG fClass, OUT PULONG pulCaps) { acDebugOut((DEB_TRACE_API,"in.out AccProvGetCapabilities\n"));
if(fClass == ACTRL_CLASS_GENERAL) { *pulCaps = ACTRL_CAP_KNOWS_SIDS | ACTRL_CAP_SUPPORTS_HANDLES; } else { *pulCaps = ACTRL_CAP_NONE; }
return; }
//+---------------------------------------------------------------------------
//
// Function: AccProvIsObjectAccessible
//
// Synopsis: Determines if the given path is accessible or not
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
//
// Returns: ERROR_SUCCESS -- The path is recognized
// ERROR_PATH_NOT_FOUND -- The path was not recognized
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvIsObjectAccessible(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType) { acDebugOut((DEB_TRACE_API,"in AccProvIsObjectAccessible\n")); DWORD dwErr = ERROR_PATH_NOT_FOUND; PWSTR DsServerlessPath, OldServerPath = NULL;
static NTMARTA_ACCESS_CACHE rgAccessCache[MAX_ACCESS_ENTRIES]; static ULONG cCacheEntries = 0; static ULONG iCacheOldest = 0;
//
// First, check our cache. Maybe we can get out cheap. Note that
// we expect our result to be failure when we start.
//
ULONG dwObjLen = wcslen(pwszObjectPath); if(dwObjLen < MAX_PATH) { RtlAcquireResourceShared(&gCacheLock, TRUE); for(ULONG iIndex = 0; iIndex < cCacheEntries && dwErr == ERROR_PATH_NOT_FOUND; iIndex++) { //
// We'll have to do this base on object type...
//
switch(ObjectType) { case SE_SERVICE: case SE_PRINTER: case SE_REGISTRY_KEY: //
// See if it's a UNC name, in which case we'll compare
// the only the server\\share name.
//
if(dwObjLen > 1 && pwszObjectPath[1] == L'\\') { //
// It's a UNC name
//
if(_wcsnicmp(pwszObjectPath, rgAccessCache[iIndex].wszPath, rgAccessCache[iIndex].cLen) == 0 && (*(pwszObjectPath + rgAccessCache[iIndex].cLen) == L'\0' || *(pwszObjectPath + rgAccessCache[iIndex].cLen) == L'\\')) { dwErr = ERROR_SUCCESS; } } else { if(_wcsicmp(pwszObjectPath, rgAccessCache[iIndex].wszPath) == 0) { dwErr = ERROR_SUCCESS; } } break;
case SE_DS_OBJECT: case SE_DS_OBJECT_ALL: //
// These have to match exact. Handle the case where we were given a
// server name prefixed DS path
//
if(IS_UNC_PATH(pwszObjectPath, dwObjLen ) ) { DsServerlessPath = wcschr(pwszObjectPath+2, L'\\');
if(DsServerlessPath != NULL) { DsServerlessPath++; OldServerPath = ( PWSTR )pwszObjectPath; pwszObjectPath = DsServerlessPath; dwObjLen = wcslen(DsServerlessPath); } }
if(dwObjLen == rgAccessCache[iIndex].cLen && _wcsicmp(pwszObjectPath, rgAccessCache[iIndex].wszPath) == 0) { dwErr = ERROR_SUCCESS; }
break;
case SE_FILE_OBJECT: case SE_KERNEL_OBJECT: case SE_LMSHARE: case SE_WMIGUID_OBJECT:
if(dwObjLen == rgAccessCache[iIndex].cLen && _wcsicmp(pwszObjectPath, rgAccessCache[iIndex].wszPath) == 0) { dwErr = ERROR_SUCCESS; }
break; }
//
// Make sure our types match...
//
if(dwErr == ERROR_SUCCESS && ObjectType != rgAccessCache[iIndex].ObjectType) { dwErr = ERROR_PATH_NOT_FOUND; } #ifdef DBG
if(dwErr == ERROR_SUCCESS) { acDebugOut((DEB_TRACE_CACHE, "Object %ws [%lu] found in cache!\n", rgAccessCache[iIndex].wszPath, rgAccessCache[iIndex].ObjectType)); } #endif
}
RtlReleaseResource(&gCacheLock); }
//
// If we got a match, return
//
if(dwErr == ERROR_SUCCESS) { return(ERROR_SUCCESS); }
//
// Well, that didn't work, so we'll have to go check. Note that there
// is not a lock here, so there is a window whereby an entry could be added
// for the path that we are currently checking. If that happens, it only
// means that the same entry will be in the cache more than once. This
// is harmless.
//
HANDLE hHandle;
switch (ObjectType) { case SE_FILE_OBJECT: dwErr = IsFilePathLocalOrLM((PWSTR)pwszObjectPath); break;
case SE_SERVICE: dwErr = OpenServiceObject((PWSTR)pwszObjectPath, SERVICE_USER_DEFINED_CONTROL, (SC_HANDLE *)&hHandle); if(dwErr == ERROR_SUCCESS) { CloseServiceHandle((SC_HANDLE)hHandle); } else { if(dwErr == ERROR_SERVICE_DOES_NOT_EXIST || dwErr == ERROR_INVALID_NAME) { dwErr = ERROR_PATH_NOT_FOUND; } } break;
case SE_PRINTER: dwErr = OpenPrinterObject((PWSTR)pwszObjectPath, PRINTER_ACCESS_USE, &hHandle); if(dwErr == ERROR_SUCCESS) { ClosePrinter(hHandle); } else { if(dwErr == ERROR_INVALID_PRINTER_NAME) { dwErr = ERROR_PATH_NOT_FOUND; } } break;
case SE_REGISTRY_KEY: dwErr = OpenRegistryObject((PWSTR)pwszObjectPath, KEY_EXECUTE, &hHandle); if(dwErr == ERROR_SUCCESS) { RegCloseKey((HKEY)hHandle); } else { if(dwErr == ERROR_INVALID_PARAMETER || dwErr == ERROR_FILE_NOT_FOUND) { dwErr = ERROR_PATH_NOT_FOUND; }
}
break;
case SE_LMSHARE: //
// Note that this doesn't have to be a local share, just a lan man
// share
//
dwErr = PingLmShare(pwszObjectPath);
break;
case SE_KERNEL_OBJECT: // FALL THROUGH
case SE_WMIGUID_OBJECT:
//
// Can't have kernel objects outside of NT, so just return success
//
dwErr = ERROR_SUCCESS; break;
case SE_DS_OBJECT: // FALL THROUGH
case SE_DS_OBJECT_ALL: dwErr = PingDSObj(OldServerPath ? OldServerPath : pwszObjectPath); break;
default:
//
// Unknown object type. Pass it on.
//
dwErr = ERROR_PATH_NOT_FOUND; break; }
if(dwErr == ERROR_ACCESS_DENIED) {
dwErr = ERROR_SUCCESS; }
//
// Add it to the cache, if we succeeded
//
if(dwErr == ERROR_SUCCESS && (ObjectType != SE_KERNEL_OBJECT && ObjectType != SE_WMIGUID_OBJECT)) { //
// Lock the cache
//
RtlAcquireResourceExclusive(&gCacheLock, TRUE);
//
// For some items, we'll want to save the root of the path, since it
// is not possible to have linked services, registry keys, etc, while
// for files and shares, it can cause problems. If an entry is too
// long to be cached, we'll ignore it.
//
if(dwObjLen <= MAX_PATH) { //
// Save off the object type and path name. For those that
// need it, we'll go through and shorten them as requried.
//
rgAccessCache[iCacheOldest].ObjectType = ObjectType; wcscpy(rgAccessCache[iCacheOldest].wszPath, pwszObjectPath); rgAccessCache[iCacheOldest].cLen = dwObjLen;
PWSTR pwszLop = rgAccessCache[iCacheOldest].wszPath; switch (ObjectType) { case SE_SERVICE: case SE_PRINTER: case SE_REGISTRY_KEY: //
// See if it's a UNC name, in which case we'll lop
// it off
//
if(IS_UNC_PATH(pwszObjectPath, dwObjLen)) { //
// It's a UNC name, so lop it off
//
pwszLop = wcschr(pwszLop + 2, L'\\'); if(pwszLop != NULL) { pwszLop = wcschr(pwszLop + 1, '\\');
if(pwszLop != NULL) { *pwszLop = L'\0'; rgAccessCache[iCacheOldest].cLen = (DWORD)(pwszLop - rgAccessCache[iCacheOldest].wszPath); } } } break;
case SE_DS_OBJECT: case SE_DS_OBJECT_ALL: //
// Save off the domain name part
//
//
// Note that we'll get the object in RDN format, so
// it's a simple matter to lop it off if necessary
pwszLop = wcschr(pwszLop, L'\\'); if(pwszLop != NULL) { *pwszLop = L'\0'; rgAccessCache[iCacheOldest].cLen = (DWORD)(pwszLop - rgAccessCache[iCacheOldest].wszPath); } break; }
//
// Update our indexes and counts
//
if(cCacheEntries < MAX_ACCESS_ENTRIES) { cCacheEntries++; }
iCacheOldest++; if(iCacheOldest == MAX_ACCESS_ENTRIES) { iCacheOldest = 0; } }
RtlReleaseResource(&gCacheLock); }
if ( dwErr == ERROR_INVALID_NAME ) {
acDebugOut(( DEB_ERROR, "%ws returned ERROR_INVALID_NAME\n", pwszObjectPath )); ASSERT( FALSE );
} acDebugOut((DEB_TRACE_API,"out AccProvIsObjectAccessible: %lu\n", dwErr)); return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleIsObjectAccessible
//
// Synopsis: Determines if the given object is accessible or not given
// a handle to it
//
// Arguments: [IN hObject] -- Object handle
// [IN ObjectType] -- Type of the object
//
// Returns: ERROR_SUCCESS -- The path is recognized
// ERROR_PATH_NOT_FOUND -- The path was not recognized
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleIsObjectAccessible(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType) { acDebugOut((DEB_TRACE_API,"in AccProvHandleIsObjectAccessible\n"));
DWORD dwErr = ERROR_PATH_NOT_FOUND;
//
// Because a handle can get reused, we can't cache them like we did
// above...
//
switch (ObjectType) { case SE_FILE_OBJECT: { DWORD dwHigh; DWORD dwSize = GetFileSize(hObject, &dwHigh); if(dwSize == 0xFFFFFFFF) { dwErr = GetLastError(); } else { dwErr = ERROR_SUCCESS; } } break;
case SE_SERVICE: { SERVICE_STATUS SvcStatus;
if(QueryServiceStatus((SC_HANDLE)hObject, &SvcStatus) == FALSE) { dwErr = GetLastError(); } else { dwErr = ERROR_SUCCESS; } } break;
case SE_PRINTER: { dwErr = LoadDLLFuncTable(); if(dwErr == ERROR_SUCCESS) { ULONG cNeeded; if(DLLFuncs.PGetPrinter(hObject, 1, NULL, 0, &cNeeded) == FALSE) { dwErr = GetLastError(); if(dwErr == ERROR_INSUFFICIENT_BUFFER) { dwErr = ERROR_SUCCESS; } } } } break;
case SE_REGISTRY_KEY: dwErr = RegQueryInfoKey((HKEY)hObject, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); break;
case SE_KERNEL_OBJECT: // FALL THROUGH
case SE_WINDOW_OBJECT: // FALL THROUGH
case SE_WMIGUID_OBJECT: //
// Can't have kernel/windows objects outside of NT, so just return
// success
//
dwErr = ERROR_SUCCESS; break;
case SE_LMSHARE: // FALL THROUGH
case SE_DS_OBJECT: // FALL THROUGH
case SE_DS_OBJECT_ALL: //
// Can't have handles to DS objects
//
dwErr = ERROR_PATH_NOT_FOUND; break;
default:
//
// Unknown object type. Pass it on.
//
dwErr = ERROR_PATH_NOT_FOUND; break; }
//
// Make sure the reason we failed isn't because of permissions
//
if(dwErr == ERROR_ACCESS_DENIED) { dwErr = ERROR_SUCCESS; }
acDebugOut((DEB_TRACE_API,"out AccProvIsObjectAccessible: %lu\n", dwErr)); return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvCancelOperation
//
// Synopsis: Cancels an ongoing operation.
//
// Arguments: [IN pOverlapped] -- Operation to cancel
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad overlapped structure was
// given
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvCancelOperation(IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
//
// Ok, first, grab a read lock, so nobody inserts on us, and find the
// right node
//
PNTMARTA_WRKR_INFO pWrkrNode = NULL;
{ // RtlAcquireResourceShared(&gWrkrLock, TRUE);
RtlAcquireResourceExclusive(&gWrkrLock, TRUE);
pWrkrNode = (PNTMARTA_WRKR_INFO)gWrkrList.Find((PVOID)pOverlapped, NtProvFindWorkerItem); RtlReleaseResource(&gWrkrLock); }
if(pWrkrNode == NULL) { dwErr = ERROR_INVALID_PARAMETER; } else { //
// All right. We'll set our stop flag, and wait for it to return..
// It doesn't matter what we set the flag to, since all we need to do
// is set it non-0
//
pWrkrNode->fState++;
//
// Now, wait for the call to finish
//
WaitForSingleObject(pWrkrNode->hWorker, INFINITE); }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvGetOperationResults
//
// Synopsis: Gets the results of an operation
//
// Arguments: [IN pOverlapped] -- Operation to cancel
// [OUT dwResults] -- Where the results are returned
// [OUT pcProcessed] -- Number of items processed
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad overlapped structure was
// given
// ERROR_IO_PENDING -- Operation hasn't completed yet
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvGetOperationResults(IN PACTRL_OVERLAPPED pOverlapped, OUT PDWORD dwResults, OUT PDWORD pcProcessed) { DWORD dwErr = ERROR_SUCCESS; PNTMARTA_WRKR_INFO pWrkrNode = NULL;
//
// Ok, first, grab a write lock. This will prevent anyone from
// reading and or writing to the list, until we get done updating
// our overlapped structure.
//
RtlAcquireResourceExclusive(&gWrkrLock, TRUE);
pWrkrNode = (PNTMARTA_WRKR_INFO)gWrkrList.Find((PVOID)pOverlapped, NtProvFindWorkerItem);
RtlReleaseResource(&gWrkrLock);
if(pWrkrNode == NULL) { //
// Now, the reason we may have not found the node is that somebody
// has removed it. If so, check our overlapped structure, since
// that will have been updated by the last call
//
if(pOverlapped->hEvent != NULL) { dwErr = ERROR_INVALID_PARAMETER; } else { *dwResults = pOverlapped->Reserved2; if(pcProcessed != NULL) { *pcProcessed = pOverlapped->Reserved1; } } } else { //
// See if the thread has stopped processing or not
//
if(WaitForSingleObject(pWrkrNode->hWorker, 0) == WAIT_TIMEOUT) { if(pcProcessed != NULL) { *pcProcessed = pWrkrNode->cProcessed; } dwErr = ERROR_IO_PENDING; } else { //
// Get the results of the thread exit first.
//
if(GetExitCodeThread(pWrkrNode->hWorker, dwResults) == FALSE) { dwErr = GetLastError(); } else { dwErr = ERROR_SUCCESS; CloseHandle(pWrkrNode->hWorker); pWrkrNode->hWorker = NULL;
//
// Save off the results. They go in Reserved2 parameter
//
pOverlapped->Reserved2 = *dwResults; pOverlapped->Reserved1 = pWrkrNode->cProcessed;
//
// Remove the node from our list, and do our updates. We
// need to do all of this before releasing our resource,
// to prevent some race conditions
//
RtlAcquireResourceExclusive(&gWrkrLock, TRUE);
gWrkrList.Remove((PVOID)pWrkrNode);
RtlReleaseResource(&gWrkrLock);
//
// Deallocate our memory
//
AccFree(pWrkrNode); } } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvSetAccessRights
//
// Synopsis: Sets the access rights on the given object. It replaces any
// existing rights.
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pAccessList] -- Optional. The list of access
// rights to set.
// [IN pAuditList] -- Optional. The list of access
// rights to set.
// [IN pOwner] -- Optional. Owner to set
// [IN pGroup] -- Optional. Group to set
// [IN pOverlapped] -- Overlapped structure to use for
// asynchronous control
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvSetAccessRights(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN SECURITY_INFORMATION SecurityInfo, IN OPTIONAL PACTRL_ACCESS pAccessList, IN OPTIONAL PACTRL_AUDIT pAuditList, IN OPTIONAL PTRUSTEE pOwner, IN OPTIONAL PTRUSTEE pGroup, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr;
CAccessList *pAccList = new CAccessList; if(pAccList == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { dwErr = pAccList->SetObjectType(ObjectType); if(dwErr == ERROR_SUCCESS) { if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION)) { dwErr = pAccList->AddAccessLists(DACL_SECURITY_INFORMATION, pAccessList, FALSE); }
if(dwErr == ERROR_SUCCESS && FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION)) { dwErr = pAccList->AddAccessLists(SACL_SECURITY_INFORMATION, pAuditList, FALSE); }
if(dwErr == ERROR_SUCCESS) { //
// Add the owner and group
//
dwErr = pAccList->AddOwnerGroup(SecurityInfo, pOwner, pGroup); } }
if(dwErr == ERROR_SUCCESS) { //
// Finally, if all that worked, we'll do the rest
//
dwErr = NtProvDoSet(pwszObjectPath, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete(pAccList); } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleSetAccessRights
//
// Synopsis: Sets the access rights on the given object. It replaces any
// existing rights.
//
// Arguments: [IN hObject] -- Handle to the object
// [IN ObjectType] -- Type of the object
// [IN pAccessList] -- Optional. The list of access
// rights to set.
// [IN pAuditList] -- Optional. The list of access
// rights to set.
// [IN pOwner] -- Optional. Owner to set
// [IN pGroup] -- Optional. Group to set
// [IN pOverlapped] -- Overlapped structure to use for
// asynchronous control
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleSetAccessRights(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN SECURITY_INFORMATION SecurityInfo, IN PACTRL_ACCESS pAccessList OPTIONAL, IN PACTRL_AUDIT pAuditList OPTIONAL, IN PTRUSTEE pOwner OPTIONAL, IN PTRUSTEE pGroup OPTIONAL, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr;
CAccessList *pAccList = new CAccessList; if(pAccList == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { dwErr = pAccList->SetObjectType(ObjectType); if(dwErr == ERROR_SUCCESS) { if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION)) { dwErr = pAccList->AddAccessLists(DACL_SECURITY_INFORMATION, pAccessList, FALSE); }
if(dwErr == ERROR_SUCCESS && FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION)) { dwErr = pAccList->AddAccessLists(SACL_SECURITY_INFORMATION, pAuditList, FALSE); }
if(dwErr == ERROR_SUCCESS) { //
// Add the owner and group
//
dwErr = pAccList->AddOwnerGroup(SecurityInfo, pOwner, pGroup); } }
if(dwErr == ERROR_SUCCESS) { //
// Finally, if all that worked, we'll do the rest
//
dwErr = NtProvDoHandleSet(hObject, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvGrantAccessRights
//
// Synopsis: Grants the access rights on the given object. It merges the
// supplied rights with any existing rights.
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pAccessList] -- Optional. The list of access
// rights to set.
// [IN pAuditList] -- Optional. The list of access
// rights to set.
//
// Returns: ERROR_SUCCESS -- The path is recognized
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvGrantAccessRights(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL PACTRL_ACCESS pAccessList, IN OPTIONAL PACTRL_AUDIT pAuditList, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
//
// First, read the relevant information. This will involve getting the
// access and audit lists for each property specified in the access and
// audit list.
//
PACTRL_RIGHTS_INFO pRightsList = NULL; ULONG cItems; dwErr = NtProvSetRightsList(pAccessList, pAuditList, &cItems, &pRightsList); if(dwErr == ERROR_SUCCESS) { //
// First, read all of the rights
//
CAccessList *pAccList = NULL;
//
// NtProvGetAccessListForObject modifies its first
// parameter, so we can't pass in a CONST string.
//
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject( pwszTmpObjectPath, ObjectType, pRightsList, cItems, &pAccList);
//
// Now, process the input lists
//
if(dwErr == ERROR_SUCCESS) { //
// First, the access list
//
if(pAccessList != NULL) { dwErr = pAccList->AddAccessLists(DACL_SECURITY_INFORMATION, pAccessList, TRUE);
}
//
// Then, the audit list
//
if(dwErr == ERROR_SUCCESS && pAuditList != NULL) { dwErr = pAccList->AddAccessLists(SACL_SECURITY_INFORMATION, pAuditList, TRUE); } }
if(dwErr == ERROR_SUCCESS) { //
// Finally, if all that worked, we'll do the rest
//
dwErr = NtProvDoSet(pwszObjectPath, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; }
AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
AccFree(pRightsList); }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleGrantAccessRights
//
// Synopsis: Grants the access rights on the given object. It merges the
// supplied rights with any existing rights.
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN pAccessList] -- Optional. The list of access
// rights to set.
// [IN pAuditList] -- Optional. The list of access
// rights to set.
//
// Returns: ERROR_SUCCESS -- The path is recognized
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleGrantAccessRights(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL PACTRL_ACCESS pAccessList, IN OPTIONAL PACTRL_AUDIT pAuditList, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
//
// First, read the relevant information. This will involve getting the
// access and audit lists for each property specified in the access and
// audit list.
//
PACTRL_RIGHTS_INFO pRightsList = NULL; ULONG cItems; dwErr = NtProvSetRightsList(pAccessList, pAuditList, &cItems, &pRightsList); if(dwErr == ERROR_SUCCESS) { //
// First, read all of the rights
//
CAccessList *pAccList = NULL; dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, pRightsList, cItems, &pAccList); //
// Don't need the rights list, so we might as well release it
//
AccFree(pRightsList);
//
// Now, process the input lists
//
if(dwErr == ERROR_SUCCESS) { //
// First, the access list
//
if(pAccessList != NULL) { dwErr = pAccList->AddAccessLists(DACL_SECURITY_INFORMATION, pAccessList, TRUE);
}
//
// Then, the audit list
//
if(dwErr == ERROR_SUCCESS && pAuditList != NULL) { dwErr = pAccList->AddAccessLists(SACL_SECURITY_INFORMATION, pAuditList, TRUE); } }
if(dwErr == ERROR_SUCCESS) { //
// Finally, if all that worked, we'll do the rest
//
dwErr = NtProvDoHandleSet(hObject, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvRevokeAccessRights
//
// Synopsis: Revokes the access rights on the given object. It goes
// through and removes any explicit entries for the given
// trustees
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN cTrustees] -- Number of trustees in list
// [IN prgTrustees] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvRevokeAccessRights(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL LPCWSTR pwszProperty, IN ULONG cTrustees, IN PTRUSTEE prgTrustees, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
CAccessList *pAccList = NULL; //
// First, read the relevant information
//
if(dwErr == ERROR_SUCCESS) { ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = DACL_SECURITY_INFORMATION;
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject(pwszTmpObjectPath, ObjectType, &RI, 1, &pAccList);
AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; } }
for(DWORD iIndex = 0; iIndex < cTrustees && dwErr == ERROR_SUCCESS; iIndex++) { dwErr = pAccList->RemoveTrusteeFromAccess(DACL_SECURITY_INFORMATION, &(prgTrustees[iIndex]), (PWSTR)pwszProperty); }
//
// Then, do the set
//
if(dwErr == ERROR_SUCCESS) { dwErr = NtProvDoSet(pwszObjectPath, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleRevokeAccessRights
//
// Synopsis: Revokes the access rights on the given object. It goes
// through and removes any explicit entries for the given
// trustees
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN cTrustees] -- Number of trustees in list
// [IN prgTrustees] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleRevokeAccessRights(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL LPCWSTR pwszProperty, IN ULONG cTrustees, IN PTRUSTEE prgTrustees, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
CAccessList *pAccList = NULL;
//
// First, read the relevant information
//
if(dwErr == ERROR_SUCCESS) { ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = DACL_SECURITY_INFORMATION; dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, &RI, 1, &pAccList); }
for(DWORD iIndex = 0; iIndex < cTrustees && dwErr == ERROR_SUCCESS; iIndex++) { dwErr = pAccList->RemoveTrusteeFromAccess(DACL_SECURITY_INFORMATION, &(prgTrustees[iIndex]), (PWSTR)pwszProperty); }
//
// Then, do the set
//
if(dwErr == ERROR_SUCCESS) { dwErr = NtProvDoHandleSet(hObject, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvRevokeAuditRights
//
// Synopsis: Revokes the audit rights on the given object. It goes
// through and removes any explicit entries for the given
// trustees
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN cTrustees] -- Number of trustees in list
// [IN prgTrustees] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvRevokeAuditRights(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL LPCWSTR pwszProperty, IN ULONG cTrustees, IN PTRUSTEE prgTrustees, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
CAccessList *pAccList = NULL; //
// First, read the relevant information
//
if(dwErr == ERROR_SUCCESS) { ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SACL_SECURITY_INFORMATION;
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject(pwszTmpObjectPath, ObjectType, &RI, 1, &pAccList); AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; } }
for(DWORD iIndex = 0; iIndex < cTrustees && dwErr == ERROR_SUCCESS; iIndex++) { dwErr = pAccList->RemoveTrusteeFromAccess(SACL_SECURITY_INFORMATION, &(prgTrustees[iIndex]), (PWSTR)pwszProperty); }
//
// Then, do the set
//
if(dwErr == ERROR_SUCCESS) { dwErr = NtProvDoSet(pwszObjectPath, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleRevokeAuditRights
//
// Synopsis: Revokes the audit rights on the given object. It goes
// through and removes any explicit entries for the given
// trustees
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN cTrustees] -- Number of trustees in list
// [IN prgTrustees] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleRevokeAuditRights(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN OPTIONAL LPCWSTR pwszProperty, IN ULONG cTrustees, IN PTRUSTEE prgTrustees, IN PACTRL_OVERLAPPED pOverlapped) { DWORD dwErr = ERROR_SUCCESS;
CAccessList *pAccList = NULL; //
// First, read the relevant information
//
if(dwErr == ERROR_SUCCESS) { ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SACL_SECURITY_INFORMATION; dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, &RI, 1, &pAccList); }
for(DWORD iIndex = 0; iIndex < cTrustees && dwErr == ERROR_SUCCESS; iIndex++) { dwErr = pAccList->RemoveTrusteeFromAccess(SACL_SECURITY_INFORMATION, &(prgTrustees[iIndex]), (PWSTR)pwszProperty); }
//
// Then, do the set
//
if(dwErr == ERROR_SUCCESS) { dwErr = NtProvDoHandleSet(hObject, ObjectType, pAccList, pOverlapped, NTMARTA_DELETE_ALIST); }
if(dwErr != ERROR_SUCCESS) { delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvGetAllRights
//
// Synopsis: Gets the all the requested rights from the object. This
// includes the access rights, audit rights, and owner and group
// if supported.
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [OUT ppAccessList] -- Optional. Where to return the
// access list
// [OUT ppAuditList] -- Optional. Where to return the
// audit list.
// [OUT ppOwner] -- Number of trustees in list
// [OUT ppGroup] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
// ERROR_INVALID_PARAMETER -- An non-NULL property name was
// given on an object that doesn't
// support properties.
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvGetAllRights(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR pwszProperty, OUT OPTIONAL PACTRL_ACCESS *ppAccessList, OUT OPTIONAL PACTRL_AUDIT *ppAuditList, OUT OPTIONAL PTRUSTEE *ppOwner, OUT OPTIONAL PTRUSTEE *ppGroup) { acDebugOut((DEB_TRACE_API,"in AccProvGetAllRights\n")); DWORD dwErr = ERROR_SUCCESS;
//
// Do the simple parameter checks first...
//
if(pwszProperty != NULL && !(ObjectType == SE_DS_OBJECT_ALL || ObjectType == SE_DS_OBJECT)) { return(ERROR_INVALID_PARAMETER); }
SECURITY_INFORMATION SeInfo = 0;
//
// Determine what we need to read
//
if(ppAccessList != NULL) { SeInfo |= DACL_SECURITY_INFORMATION; *ppAccessList = NULL; }
if(ppAuditList != NULL) { SeInfo |= SACL_SECURITY_INFORMATION; *ppAuditList = NULL; }
if(ppOwner != NULL) { SeInfo |= OWNER_SECURITY_INFORMATION; *ppOwner = NULL; }
if(ppGroup != NULL) { SeInfo |= GROUP_SECURITY_INFORMATION; *ppGroup = NULL; }
//
// If nothing was requested, do nothing...
//
if(SeInfo == 0) { return(ERROR_SUCCESS); }
//
// Now, go ahead and do the read...
//
CAccessList *pAccList;
ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SeInfo;
//
// NtProvGetAccessListForObject modifies its first
// parameter, so we can't pass in a CONST string.
//
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject(pwszTmpObjectPath, ObjectType, &RI, 1, &pAccList);
//
// Now, get the data in the form we need
//
if(dwErr == ERROR_SUCCESS) { //
// Now, convert the stuff that we need to...
//
dwErr = pAccList->MarshalAccessLists(SeInfo, ppAccessList, ppAuditList);
if(dwErr == ERROR_SUCCESS && ppOwner != NULL) { dwErr = pAccList->GetSDSidAsTrustee(OWNER_SECURITY_INFORMATION, ppOwner); }
if(dwErr == ERROR_SUCCESS && ppGroup != NULL) { dwErr = pAccList->GetSDSidAsTrustee(GROUP_SECURITY_INFORMATION, ppGroup); }
//
// Ok, if anything failed, we'll do the cleanup
//
if(dwErr != ERROR_SUCCESS) { if((SeInfo & DACL_SECURITY_INFORMATION) != 0) { AccFree(*ppAccessList); }
if((SeInfo & SACL_SECURITY_INFORMATION) != 0) { AccFree(*ppAuditList); }
if((SeInfo & OWNER_SECURITY_INFORMATION) != 0) { AccFree(*ppOwner); }
if((SeInfo & GROUP_SECURITY_INFORMATION) != 0) { AccFree(*ppGroup); } }
delete pAccList; }
AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
//
// The destruction of the CAclList class will clean up all of the
// memory we obtained
//
acDebugOut((DEB_TRACE_API,"out AccProvGetAllRights: %lu\n", dwErr)); return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleGetAllRights
//
// Synopsis: Gets the all the requested rights from the object. This
// includes the access rights, audit rights, and owner and group
// if supported.
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [OUT ppAccessList] -- Optional. Where to return the
// access list
// [OUT ppAuditList] -- Optional. Where to return the
// audit list.
// [OUT ppOwner] -- Number of trustees in list
// [OUT ppGroup] -- List of trustees to revoke
//
// Returns: ERROR_SUCCESS -- The operation succeeded
// ERROR_INVALID_PARAMETER -- An non-NULL property name was
// given on an object that doesn't
// support properties.
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleGetAllRights(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR pwszProperty, OUT OPTIONAL PACTRL_ACCESS *ppAccessList, OUT OPTIONAL PACTRL_AUDIT *ppAuditList, OUT OPTIONAL PTRUSTEE *ppOwner, OUT OPTIONAL PTRUSTEE *ppGroup) { acDebugOut((DEB_TRACE_API,"in AccProvHandleGetAllRights\n")); DWORD dwErr = ERROR_SUCCESS;
//
// Do the simple parameter checks first...
//
if(pwszProperty != NULL && (ObjectType != SE_DS_OBJECT_ALL && ObjectType != SE_DS_OBJECT)) { return(ERROR_INVALID_PARAMETER); }
SECURITY_INFORMATION SeInfo = 0;
//
// Determine what we need to read
//
if(ppAccessList != NULL) { SeInfo |= DACL_SECURITY_INFORMATION; *ppAccessList = NULL; }
if(ppAuditList != NULL) { SeInfo |= SACL_SECURITY_INFORMATION; *ppAuditList = NULL; }
if(ppOwner != NULL) { SeInfo |= OWNER_SECURITY_INFORMATION; *ppOwner = NULL; }
if(ppGroup != NULL) { SeInfo |= GROUP_SECURITY_INFORMATION; *ppGroup = NULL; }
//
// If nothing was requested, do nothing...
//
if(SeInfo == 0) { return(ERROR_SUCCESS); }
//
// Now, go ahead and do the read...
//
CAccessList *pAccList;
ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SeInfo; dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, &RI, 1, &pAccList);
//
// Now, get the data in the form we need
//
if(dwErr == ERROR_SUCCESS) { //
// Now, convert the stuff that we need to...
//
dwErr = pAccList->MarshalAccessLists(SeInfo, ppAccessList, ppAuditList);
if(dwErr == ERROR_SUCCESS && ppOwner != NULL) { dwErr = pAccList->GetSDSidAsTrustee(OWNER_SECURITY_INFORMATION, ppOwner); }
if(dwErr == ERROR_SUCCESS && ppGroup != NULL) { dwErr = pAccList->GetSDSidAsTrustee(GROUP_SECURITY_INFORMATION, ppGroup); }
//
// Ok, if anything failed, we'll do the cleanup
//
if(dwErr != ERROR_SUCCESS) { if((SeInfo & DACL_SECURITY_INFORMATION) != 0) { AccFree(*ppAccessList); }
if((SeInfo & SACL_SECURITY_INFORMATION) != 0) { AccFree(*ppAuditList); }
if((SeInfo & OWNER_SECURITY_INFORMATION) != 0) { AccFree(*ppOwner); }
if((SeInfo & GROUP_SECURITY_INFORMATION) != 0) { AccFree(*ppGroup); } }
delete pAccList; }
//
// The destruction of the CAclList class will clean up all of the
// memory we obtained
//
acDebugOut((DEB_TRACE_API,"out AccProvHandleGetAllRights: %lu\n", dwErr)); return(dwErr); }
DWORD AccProvpDoTrusteeAccessCalculations(IN CAccessList *pAccList, IN PTRUSTEE pTrustee, IN OUT PTRUSTEE_ACCESS pTrusteeAccess) { DWORD dwErr;
ULONG DeniedMask; ULONG AllowedMask; dwErr = pAccList->GetExplicitAccess(pTrustee, (PWSTR)pTrusteeAccess->lpProperty, &DeniedMask, &AllowedMask); if(dwErr == ERROR_SUCCESS) { //
// Process the entries
//
//
// It depends on what it is we're looking for...
//
pTrusteeAccess->fReturnedAccess = 0; if(pTrusteeAccess->fAccessFlags == TRUSTEE_ACCESS_EXPLICIT) { //
// Ok, we'll look for these explicit rights
//
//
// First, see if any of our denieds match...
//
if (pTrusteeAccess->Access == TRUSTEE_ACCESS_ALL) { pTrusteeAccess->fReturnedAccess = AllowedMask & ~DeniedMask; } else { if((pTrusteeAccess->Access & DeniedMask) == 0) { //
// Now, see if we're allowed
//
if((pTrusteeAccess->Access & AllowedMask) == pTrusteeAccess->Access) { pTrusteeAccess->fReturnedAccess = TRUSTEE_ACCESS_ALLOWED; } } } } else if(FLAG_ON(pTrusteeAccess->fAccessFlags, TRUSTEE_ACCESS_READ) || FLAG_ON(pTrusteeAccess->fAccessFlags, TRUSTEE_ACCESS_WRITE)) { //
// We're only looking for read/write access
//
ACCESS_RIGHTS Access[2]; ULONG fValue[2], i = 0;
if(FLAG_ON(pTrusteeAccess->fAccessFlags, TRUSTEE_ACCESS_READ)) { Access[i] = ACTRL_READ_CONTROL; fValue[i] = TRUSTEE_ACCESS_READ; i++; }
if(FLAG_ON(pTrusteeAccess->fAccessFlags, TRUSTEE_ACCESS_WRITE)) { Access[i] = ACTRL_CHANGE_ACCESS | ACTRL_CHANGE_OWNER; fValue[i] = TRUSTEE_ACCESS_WRITE; i++; }
for(ULONG iIndex = 0; iIndex < i; iIndex++) { if((Access[iIndex] & DeniedMask) == 0) { //
// Now, see if we're allowed
//
if((Access[iIndex] & AllowedMask) == Access[iIndex]) { pTrusteeAccess->fReturnedAccess |= fValue[iIndex]; } } } } else { dwErr = ERROR_INVALID_PARAMETER; }
//
// If we asked for read/write access, make sure we have them both
//
if(dwErr == ERROR_SUCCESS && pTrusteeAccess->fAccessFlags == TRUSTEE_ACCESS_READ_WRITE) { if( pTrusteeAccess->fReturnedAccess != TRUSTEE_ACCESS_READ_WRITE ) { pTrusteeAccess->fReturnedAccess = 0; } }
}
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvGetTrusteesAccess
//
// Synopsis: Determines whether the given trustee has the specified
// rights to the object
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN OUT pTrusteeAccess] -- Type of access to check for
// and where the access is returned
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvGetTrusteesAccess(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN PTRUSTEE pTrustee, IN OUT PTRUSTEE_ACCESS pTrusteeAccess) { DWORD dwErr = ERROR_SUCCESS;
//
// Ok, first, we'll load all the objects entries that we need
//
CAccessList *pAccList; ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pTrusteeAccess->lpProperty; RI.SeInfo = DACL_SECURITY_INFORMATION;
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject(pwszTmpObjectPath, ObjectType, &RI, 1, &pAccList); AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpDoTrusteeAccessCalculations(pAccList, pTrustee, pTrusteeAccess); delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleGetTrusteesAccess
//
// Synopsis: Determines whether the given trustee has the specified
// rights to the object
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN OUT pTrusteeAccess] -- Type of access to check for
// and where the access is returned
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleGetTrusteesAccess(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN PTRUSTEE pTrustee, IN OUT PTRUSTEE_ACCESS pTrusteeAccess) { DWORD dwErr = ERROR_SUCCESS;
//
// Ok, first, we'll load all the objects entries that we need
//
CAccessList *pAccList; ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pTrusteeAccess->lpProperty; RI.SeInfo = DACL_SECURITY_INFORMATION;
dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, &RI, 1, &pAccList); if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpDoTrusteeAccessCalculations(pAccList, pTrustee, pTrusteeAccess);
delete pAccList; }
return(dwErr); }
DWORD AccProvpDoAccessAuditedCalculations(IN CAccessList *pAccList, IN LPCWSTR pwszProperty, IN PTRUSTEE pTrustee, IN ACCESS_RIGHTS ulAuditRights, OUT PBOOL pfAuditedSuccess, OUT PBOOL pfAuditedFailure) { ULONG SuccessMask; ULONG FailureMask; DWORD dwErr = pAccList->GetExplicitAudits(pTrustee, (PWSTR)pwszProperty, &SuccessMask, &FailureMask); if(dwErr == ERROR_SUCCESS) {
//
// Process the entries
//
*pfAuditedSuccess = FALSE; *pfAuditedFailure = FALSE; if((ulAuditRights & SuccessMask) == ulAuditRights) { *pfAuditedSuccess = TRUE; }
if((ulAuditRights & FailureMask) == ulAuditRights) { *pfAuditedFailure = TRUE; } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvIsAccessAudited
//
// Synopsis: Determines whether the given trustee will envoke an audit
// entry by accessing the object
//
// Arguments: [IN pwszObjectPath] -- Path to the object in question
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN pTrustee] -- Trustee for which to check access
// [IN AuditRights] -- Type of audit we care about
// [OUT pfAccessAllowed] -- Where the results are returned.
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvIsAccessAudited(IN LPCWSTR pwszObjectPath, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR pwszProperty, IN PTRUSTEE pTrustee, IN ACCESS_RIGHTS AuditRights, OUT PBOOL pfAuditedSuccess, OUT PBOOL pfAuditedFailure) { DWORD dwErr = ERROR_SUCCESS;
//
// Ok, first, we'll load all the objects entries that we need
//
CAccessList *pAccList;
ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SACL_SECURITY_INFORMATION;
PWSTR pwszTmpObjectPath = (PWSTR)AccAlloc( (wcslen(pwszObjectPath) + 1) * sizeof( WCHAR ) );
if (pwszTmpObjectPath) { wcscpy( pwszTmpObjectPath, pwszObjectPath ); pwszTmpObjectPath[wcslen(pwszObjectPath)] = UNICODE_NULL;
dwErr = NtProvGetAccessListForObject(pwszTmpObjectPath, ObjectType, &RI, 1, &pAccList); AccFree( pwszTmpObjectPath ); } else { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpDoAccessAuditedCalculations(pAccList, pwszProperty, pTrustee, AuditRights, pfAuditedSuccess, pfAuditedFailure); delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleIsAccessAudited
//
// Synopsis: Determines whether the given trustee will envoke an audit
// entry by accessing the object
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN pwszProperty] -- Optional. The name of the
// property on the object to revoke
// for
// [IN pTrustee] -- Trustee for which to check access
// [IN ulAuditRights] -- Type of audit we care about
// [OUT pfAccessAllowed] -- Where the results are returned.
//
// Returns: ERROR_SUCCESS -- The operation succeeded
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleIsAccessAudited(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR pwszProperty, IN PTRUSTEE pTrustee, IN ACCESS_RIGHTS AuditRights, OUT PBOOL pfAuditedSuccess, OUT PBOOL pfAuditedFailure) { DWORD dwErr = ERROR_SUCCESS;
//
// Ok, first, we'll load all the objects entries that we need
//
CAccessList *pAccList;
ACTRL_RIGHTS_INFO RI; RI.pwszProperty = (PWSTR)pwszProperty; RI.SeInfo = SACL_SECURITY_INFORMATION; dwErr = NtProvGetAccessListForHandle(hObject, ObjectType, &RI, 1, &pAccList); if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpDoAccessAuditedCalculations(pAccList, pwszProperty, pTrustee, AuditRights, pfAuditedSuccess, pfAuditedFailure); delete pAccList; }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvpGetAccessInfoPerObjectType
//
// Synopsis: Returns the list of available access permissions for the
// specified object type
//
// Arguments: [IN ObjectType] -- Type of the object
// [IN DsObjType] -- If this is a DS object, the type
// of the object
// [IN pwszDsPath] -- Full path to the object
//
// [IN lpProperty] -- Optional. If present, the name of
// the property to get the access
// rights for.
// [IN fIsDir] -- If TRUE, the path is a directory
// [OUT pcEntries] -- Where the count of items is returned
// [OUT ppAccessInfo] -- Where the list of items is returned
// [OUT pcControlRights] -- Count of control rights are
// is returned here
// [OUT ppControlRights] -- Where the list of control rights
// is returned
// [OUT pfAccessFlags] -- Where the provider flags are
// returned.
//
// Returns: ERROR_SUCCESS -- The operation succeeded
// ERROR_INVALID_PARAMETER -- The operation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvpGetAccessInfoPerObjectType(IN SE_OBJECT_TYPE ObjectType, IN BOOL fIsDir, IN PWSTR pwszDsPath, IN PWSTR lpProperty, OUT PULONG pcEntries, OUT PACTRL_ACCESS_INFO *ppAccessInfoList, OUT PULONG pcControlRights, OUT PACTRL_CONTROL_INFOW *ppControlRights, OUT PULONG pfAccessFlags) { DWORD dwErr = ERROR_SUCCESS; BOOL ControlRightsValid = FALSE; ULONG cStart = 0; ULONG cItems = 0;
#define LENGTH_OF_STR_GUID 37
#define LENGTH_OF_LONGEST_STRING 20
//
// DS control rights
//
*pfAccessFlags = ACTRL_ACCESS_NO_OPTIONS;
*ppControlRights = NULL; *pcControlRights = 0;
*ppAccessInfoList = 0; *pcEntries = 0;
//
// Do the right thing based on the object type
//
switch (ObjectType) { case SE_LMSHARE: // FALL THROUGH
case SE_FILE_OBJECT: if(fIsDir == TRUE) { cStart = ACCPROV_DIR_ACCESS; cItems = ACCPROV_NUM_DIR; } else { cStart = ACCPROV_FILE_ACCESS; cItems = ACCPROV_NUM_FILE; } break;
case SE_SERVICE: cStart = ACCPROV_SERVICE_ACCESS; cItems = ACCPROV_NUM_SERVICE; break;
case SE_PRINTER: cStart = ACCPROV_PRINT_ACCESS; cItems = ACCPROV_NUM_PRINT; break;
case SE_REGISTRY_KEY: cStart = ACCPROV_REGISTRY_ACCESS; cItems = ACCPROV_NUM_REGISTRY; break;
case SE_KERNEL_OBJECT: // FALL THROUGH
case SE_WMIGUID_OBJECT: cStart = ACCPROV_KERNEL_ACCESS; cItems = ACCPROV_NUM_KERNEL; break;
case SE_DS_OBJECT: // FALL THROUGH
case SE_DS_OBJECT_ALL: cStart = ACCPROV_DS_ACCESS; cItems = ACCPROV_NUM_DS; ControlRightsValid = TRUE; break;
case SE_WINDOW_OBJECT: cStart = ACCPROV_WIN_ACCESS; cItems = ACCPROV_NUM_WIN; break;
default: dwErr = ERROR_INVALID_PARAMETER; }
if(dwErr == ERROR_SUCCESS && ControlRightsValid == FALSE && lpProperty != NULL) { dwErr = ERROR_INVALID_PARAMETER; }
if(dwErr == ERROR_SUCCESS) { //
// Ok, we go through and size all of the strings that we need to add
//
ULONG cSize = 0; WCHAR wszBuff[ACCPROV_LONGEST_STRING + 1]; for(ULONG iIndex = 0; iIndex < cItems; iIndex++) { LoadString(ghDll, cStart + iIndex, wszBuff, ACCPROV_LONGEST_STRING);
cSize += SIZE_PWSTR(wszBuff); }
//
// Always return the standard rights, as well...
//
for(iIndex = 0; iIndex < ACCPROV_NUM_STD; iIndex++) { LoadString(ghDll, ACCPROV_STD_ACCESS + iIndex, wszBuff, ACCPROV_LONGEST_STRING); cSize += SIZE_PWSTR(wszBuff); }
//
// Make sure to return the proper count
//
*pcEntries = cItems + ACCPROV_NUM_STD;
//
// Ok, now we can allocate, and do the same thing again
//
*ppAccessInfoList = (PACTRL_ACCESS_INFO)AccAlloc( (cItems + ACCPROV_NUM_STD) * sizeof(ACTRL_ACCESS_INFO) + cSize); if(*ppAccessInfoList == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
if(*ppAccessInfoList == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { PWSTR pwszStart = (PWSTR)((PBYTE)(*ppAccessInfoList) + (cItems + ACCPROV_NUM_STD) * sizeof(ACTRL_ACCESS_INFO)); //
// Start with the standard items
//
ULONG iLst = 0; for(iIndex = 0; iIndex < ACCPROV_NUM_STD; iIndex++) { LoadString(ghDll, ACCPROV_STD_ACCESS + iIndex, wszBuff, ACCPROV_LONGEST_STRING); cSize = SIZE_PWSTR(wszBuff);
memcpy(pwszStart, wszBuff, cSize);
//
// Handle STD_RIGTHS_ALL as a special case...
//
if(iIndex == ACCPROV_NUM_STD - 1) { (*ppAccessInfoList)[iLst].fAccessPermission = ACTRL_STD_RIGHTS_ALL; } else { (*ppAccessInfoList)[iLst].fAccessPermission = ACTRL_SYSTEM_ACCESS << iIndex; } (*ppAccessInfoList)[iLst].lpAccessPermissionName = pwszStart; pwszStart = (PWSTR)Add2Ptr(pwszStart,cSize); iLst++; }
for(ULONG iIndex = 0; iIndex < cItems; iIndex++) { LoadString(ghDll, cStart + iIndex, wszBuff, ACCPROV_LONGEST_STRING);
cSize = SIZE_PWSTR(wszBuff);
memcpy(pwszStart, wszBuff, cSize); (*ppAccessInfoList)[iLst].fAccessPermission = ACTRL_PERM_1 << iIndex; (*ppAccessInfoList)[iLst].lpAccessPermissionName = pwszStart; pwszStart = (PWSTR)Add2Ptr(pwszStart,cSize); iLst++; }
//
// Now, add extra control rights
//
if(ObjectType == SE_DS_OBJECT || ObjectType == SE_DS_OBJECT_ALL ) { dwErr = AccctrlLookupRightsByName( NULL, pwszDsPath, lpProperty, pcControlRights, ppControlRights);
//
// If we can't find the entry we want, return 0 items...
//
if(dwErr == ERROR_NOT_FOUND) { *pcControlRights = 0; *ppControlRights = NULL; dwErr = ERROR_SUCCESS; } } } }
if(dwErr == ERROR_SUCCESS) { *pcEntries = cItems + ACCPROV_NUM_STD;
} else { if(*ppAccessInfoList != NULL) { AccFree(*ppAccessInfoList); *pcEntries = 0; } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvGetAccessInfoPerObjectType
//
// Synopsis: Returns the list of available access permissions for the
// specified object type
//
// Arguments: [IN lpObject] -- Full path to the object
// [IN ObjectType] -- Type of the object
// [IN lpProperty] -- Optional. If present, the name of
// the property to get the access
// rights for.
// [OUT pcEntries] -- Where the count of items is returned
// [OUT ppAccessInfo] -- Where the list of items is returned
// [OUT pfAccessFlags] -- Where the provider flags are
// returned.
//
// Returns: ERROR_SUCCESS -- The operation succeeded
// ERROR_INVALID_PARAMETER -- The operation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvGetAccessInfoPerObjectType(IN LPCWSTR lpObject, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR lpProperty, OUT PULONG pcEntries, OUT PACTRL_ACCESS_INFO *ppAccessInfoList, OUT PULONG pcControlRights, OUT PACTRL_CONTROL_INFOW *ppControlRights, OUT PULONG pfAccessFlags) { DWORD dwErr = ERROR_SUCCESS; BOOL fIsDir = FALSE;
if(ObjectType == SE_LMSHARE || ObjectType == SE_FILE_OBJECT) { //
// Check to see whether this is a file or a directory...
//
ULONG ulAttribs = GetFileAttributes((PWSTR)lpObject); if(FLAG_ON(ulAttribs, FILE_ATTRIBUTE_DIRECTORY)) { fIsDir = TRUE; } }
if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpGetAccessInfoPerObjectType(ObjectType, fIsDir, (LPWSTR)lpObject, (LPWSTR)lpProperty, pcEntries, ppAccessInfoList, pcControlRights, ppControlRights, pfAccessFlags); } return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AccProvHandleGetAccessInfoPerObjectType
//
// Synopsis: Returns the list of available access permissions for the
// specified object type
//
// Arguments: [IN hObject] -- Handle to the open object
// [IN ObjectType] -- Type of the object
// [IN lpProperty] -- Optional. If present, the name of
// the property to get the access
// rights for.
// [OUT pcEntries] -- Where the count of items is returned
// [OUT ppAccessInfo] -- Where the list of items is returned
// [OUT pfAccessFlags] -- Where the provider flags are
// returned.
//
// Returns: ERROR_SUCCESS -- The operation succeeded
// ERROR_INVALID_PARAMETER -- The operation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD WINAPI AccProvHandleGetAccessInfoPerObjectType(IN HANDLE hObject, IN SE_OBJECT_TYPE ObjectType, IN LPCWSTR lpProperty, OUT PULONG pcEntries, OUT PACTRL_ACCESS_INFO *ppAccessInfoList, OUT PULONG pcControlRights, OUT PACTRL_CONTROL_INFOW *ppControlRights, OUT PULONG pfAccessFlags) { DWORD dwErr = ERROR_SUCCESS; BOOL fIsDir = FALSE;
if(ObjectType == SE_LMSHARE || ObjectType == SE_FILE_OBJECT) { BY_HANDLE_FILE_INFORMATION BHFI; //
// Check to see whether this is a file or a directory...
//
if(GetFileInformationByHandle(hObject, &BHFI) == FALSE) { dwErr = GetLastError(); } else { if(FLAG_ON(BHFI.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) fIsDir = TRUE; } }
if(dwErr == ERROR_SUCCESS) { dwErr = AccProvpGetAccessInfoPerObjectType(ObjectType, fIsDir, NULL, (LPWSTR)lpProperty, pcEntries, ppAccessInfoList, pcControlRights, ppControlRights, pfAccessFlags); }
return(dwErr); }
|