windows-nt/Source/XPSP1/NT/ds/security/ntmarta/newsrc/kernel.cxx
2020-09-26 16:20:57 +08:00

1103 lines
35 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1996.
//
// File: kernel.cxx
//
// Contents: Kernel support functions
//
// History: 8/94 davemont Created
//
//----------------------------------------------------------------------------
#include <aclpch.hxx>
#pragma hdrstop
#include <seopaque.h>
#include <sertlp.h>
#pragma warning(disable: 4200)
#include <wmistr.h>
#include <wmiumkm.h>
#define BASED_NAMED_OBJECTS_DIR L"\\BaseNamedObjects"
//
// Function prototypes
//
ULONG WmipOpenKernelGuid(
CONST GUID *Guid,
ACCESS_MASK DesiredAccess,
PHANDLE Handle
);
HANDLE WmiGuidHandle = NULL;
//+---------------------------------------------------------------------------
//
// Function: OpenKernelObject
//
// Synopsis: Gets a handle to the specified kernel object
//
// Arguments: [IN pwszObject] -- Object to open
// [IN AccessMask] -- Type of open to do
// [OUT pHandle] -- Where the handle to the object
// is returned
// [OUT KernelType] -- Type of the kernel object
//
// Returns: ERROR_SUCCESS -- Success
//
//----------------------------------------------------------------------------
DWORD
OpenKernelObject(IN LPWSTR pwszObject,
IN ACCESS_MASK AccessMask,
OUT PHANDLE pHandle,
OUT PMARTA_KERNEL_TYPE KernelType)
{
#define BUFFERSIZE 1024
HANDLE hRootDir;
NTSTATUS Status;
UNICODE_STRING UnicodeString;
OBJECT_ATTRIBUTES Attributes;
UCHAR Buffer[BUFFERSIZE];
BOOL fFound = FALSE;
ULONG Context = 0;
DWORD dwErr = ERROR_SUCCESS;
POBJECT_DIRECTORY_INFORMATION DirInfo = NULL;
//
// Get a handle to the base named and iterate through that directory
// to find the object name.
//
RtlInitUnicodeString(&UnicodeString,
BASED_NAMED_OBJECTS_DIR);
InitializeObjectAttributes(&Attributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenDirectoryObject(&hRootDir,
DIRECTORY_QUERY,
&Attributes);
if (!NT_SUCCESS(Status))
{
return(RtlNtStatusToDosError(Status));
}
//
// Get the entries in batches that will fit in a buffer of size
// BUFFERSIZE until we find the entry that we want
//
while (NT_SUCCESS(Status) && !fFound )
{
RtlZeroMemory(Buffer,
BUFFERSIZE);
Status = NtQueryDirectoryObject(hRootDir,
(PVOID)&Buffer,
BUFFERSIZE,
FALSE,
FALSE,
&Context,
NULL);
if(NT_SUCCESS(Status))
{
//
// Keep looking until we've examined all the entries in this
// batch or we find what we're looking for.
//
DirInfo = (POBJECT_DIRECTORY_INFORMATION)&Buffer[0];
while(!fFound && DirInfo->Name.Length != 0)
{
ULONG cChar;
cChar = DirInfo->Name.Length/sizeof(WCHAR);
if((cChar == wcslen(pwszObject)) &&
(!wcsncmp(pwszObject,
DirInfo->Name.Buffer,
cChar )) )
{
fFound = TRUE;
}
else
{
DirInfo++;
}
}
}
}
if (!fFound)
{
if(Status != STATUS_NO_MORE_ENTRIES)
{
dwErr = RtlNtStatusToDosError(Status);
}
else
{
dwErr = ERROR_RESOURCE_NAME_NOT_FOUND;
}
}
else
{
ASSERT( DirInfo != NULL );
ASSERT( DirInfo->Name.Length != 0 );
ASSERT( DirInfo->TypeName.Length != 0 );
RtlInitUnicodeString(&UnicodeString,
pwszObject);
InitializeObjectAttributes(&Attributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
hRootDir,
NULL);
//
// Open the object to get its handle based on its type
//
if (wcsncmp(L"Event",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenEvent(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_EVENT;
}
else if (wcsncmp( L"EventPair",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenEventPair(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_EVENT_PAIR;
}
else if (wcsncmp(L"Mutant",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenMutant(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_MUTANT;
}
else if (wcsncmp(L"Process",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenProcess(pHandle,
AccessMask,
&Attributes,
NULL);
*KernelType = MARTA_PROCESS;
}
else if (wcsncmp( L"Section",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenSection(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_SECTION;
}
else if (wcsncmp(L"Semaphore",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenSemaphore(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_SEMAPHORE;
}
else if (wcsncmp(L"SymbolicLink",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenSymbolicLinkObject(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_SYMBOLIC_LINK;
}
else if (wcsncmp(L"Thread",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenThread(pHandle,
AccessMask,
&Attributes,
NULL);
*KernelType = MARTA_THREAD;
}
else if (wcsncmp(L"Timer",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenTimer(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_TIMER;
}
else if (wcsncmp(L"Job",
DirInfo->TypeName.Buffer,
DirInfo->TypeName.Length/sizeof(WCHAR)) == 0)
{
Status = NtOpenJobObject(pHandle,
AccessMask,
&Attributes);
*KernelType = MARTA_JOB;
}
else
{
Status = STATUS_OBJECT_NAME_INVALID;
}
if(!NT_SUCCESS(Status))
{
dwErr = RtlNtStatusToDosError(Status);
}
}
NtClose(hRootDir);
return (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: ReadKernelPropertyRights
//
// Synopsis: Gets the specified rights from the kernel object
//
// Arguments: [IN pwszObject] -- The object to get the rights
// for
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was encountered
//
// Note: Kernel objects are assumed to be created through the
// Win32 APIs so they all reside in the \basenamedobjects
// directory.
//
//----------------------------------------------------------------------------
DWORD
ReadKernelPropertyRights(IN LPWSTR pwszObject,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in ReadKernelPropertyRights\n"));
DWORD dwErr = ERROR_SUCCESS;
HANDLE hObject = NULL;
MARTA_KERNEL_TYPE KernelType;
//
// Kernel objects don't have parents from whom they can inherit
//
ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
{
return(ERROR_INVALID_PARAMETER);
}
dwErr = OpenKernelObject(pwszObject,
GetDesiredAccess(READ_ACCESS_RIGHTS,
pRightsList[0].SeInfo),
&hObject,
&KernelType);
if(dwErr == ERROR_SUCCESS)
{
dwErr = GetKernelSecurityInfo(hObject,
pRightsList,
cRights,
AccessList);
NtClose(hObject);
}
acDebugOut((DEB_TRACE, "Out ReadKernelPropertyRights: %lu\n", dwErr));
return (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetKernelSecurityInfo
//
// Arguments: [IN hObject] -- The handle to the object to
// get the rights for
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
GetKernelSecurityInfo(IN HANDLE hObject,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in GetKernelSecurityInfo\n"));
UCHAR pSDBuff[PSD_BASE_LENGTH];
PISECURITY_DESCRIPTOR pSD;
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
ULONG cNeeded = 0;
for(ULONG iIndex = 0; iIndex < cRights && dwErr == ERROR_SUCCESS; iIndex++)
{
pSD = (PISECURITY_DESCRIPTOR)pSDBuff;
Status = NtQuerySecurityObject(hObject,
pRightsList[iIndex].SeInfo,
pSD,
PSD_BASE_LENGTH,
&cNeeded);
if(!NT_SUCCESS(Status))
{
if(Status == STATUS_BUFFER_TOO_SMALL)
{
//
// Fine.. Allocate a big enough buffer
//
pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
if(pSD == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
Status = NtQuerySecurityObject(hObject,
pRightsList[iIndex].SeInfo,
pSD,
cNeeded,
&cNeeded);
}
}
//
// Now, we've either got a failure or a valid SD...
//
if(NT_SUCCESS(Status))
{
dwErr = AccessList.AddSD(pSD,
pRightsList[iIndex].SeInfo,
pRightsList[iIndex].pwszProperty);
}
else
{
dwErr = RtlNtStatusToDosError(Status);
}
if(pSD != (PISECURITY_DESCRIPTOR)pSDBuff)
{
AccFree(pSD);
}
}
acDebugOut((DEB_TRACE, "Out GetKernelSecurityInfo: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetKernelParentRights
//
// Synopsis: Determines who the parent is, and gets the access rights
// for it. It is used to aid in determining what the approriate
// inheritance bits are.
//
// This operation does not make sense for kernel objects
//
// Arguments: [IN pwszObject] -- The object to get the parent
// for
// [IN pRightsList] -- The properties to get the
// rights for
// [IN cRights] -- Number of items in rights list
// [OUT ppDAcl] -- Where the DACL is returned
// [OUT ppSAcl] -- Where the SACL is returned
// [OUT ppSD] -- Where the Security Descriptor
// is returned
//
// Returns: ERROR_INVALID_FUNCTION -- Call doesn't make sense here
//
//----------------------------------------------------------------------------
DWORD
GetKernelParentRights(IN LPWSTR pwszObject,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
OUT PACL *ppDAcl,
OUT PACL *ppSAcl,
OUT PSECURITY_DESCRIPTOR *ppSD)
{
//
// This doesn't currently make sense for kernel objects, so simply
// return an error
//
return(ERROR_INVALID_FUNCTION);
}
//+---------------------------------------------------------------------------
//
// Function: SetKernelSecurityInfo
//
// Synopsis: Sets the specified security info for the handle's
// kernel object
//
// Arguments: [IN hKernel] -- The handle of the object
// [IN SeInfo] -- Flag indicating what security
// info to set
// [IN pwszProperty] -- The property on the object to
// set
// For kernel objects, this MBZ
// [IN pSD] -- The security descriptor to set
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was given
//
//----------------------------------------------------------------------------
DWORD
SetKernelSecurityInfo(IN HANDLE hKernel,
IN SECURITY_INFORMATION SeInfo,
IN PWSTR pwszProperty,
IN PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
acDebugOut((DEB_TRACE, "in SetNamedKernelSecurityInfo\n"));
DWORD dwErr = ERROR_SUCCESS;
if(pwszProperty != NULL)
{
dwErr = ERROR_INVALID_PARAMETER;
}
else
{
NTSTATUS Status = NtSetSecurityObject(hKernel,
SeInfo,
pSecurityDescriptor);
dwErr = RtlNtStatusToDosError(Status);
}
acDebugOut((DEB_TRACE, "Out SetKernelSecurityInfo %lu\n", dwErr));
return (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetKernelSecurityInfo
//
// Arguments: [IN hObject] -- The handle to the object to
// get the rights for
// [IN SeInfo] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
GetKernelSecurityInfo(IN HANDLE hObject,
IN SECURITY_INFORMATION SeInfo,
OUT PACL *ppDAcl,
OUT PACL *ppSAcl,
OUT PSECURITY_DESCRIPTOR *ppSD)
{
acDebugOut((DEB_TRACE, "in GetKernelSecurityInfo\n"));
PISECURITY_DESCRIPTOR pSD = NULL;
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
ULONG cNeeded = 0;
Status = NtQuerySecurityObject(hObject,
SeInfo,
pSD,
0,
&cNeeded);
if(!NT_SUCCESS(Status))
{
if(Status == STATUS_BUFFER_TOO_SMALL)
{
//
// Fine.. Allocate a big enough buffer
//
pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
if(pSD == NULL)
{
Status = STATUS_NO_MEMORY;
}
else
{
Status = NtQuerySecurityObject(hObject,
SeInfo,
pSD,
cNeeded,
&cNeeded);
}
}
}
//
// Now, we've either got a failure or a valid SD...
//
if(NT_SUCCESS(Status))
{
if (pSD != NULL)
{
if(ppDAcl != NULL)
{
*ppDAcl = RtlpDaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
}
if(ppSAcl != NULL)
{
*ppSAcl = RtlpSaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
}
*ppSD = pSD;
}
else
{
dwErr = ERROR_ACCESS_DENIED;
}
}
else
{
dwErr = RtlNtStatusToDosError(Status);
}
acDebugOut((DEB_TRACE, "Out GetKernelSecurityInfo: %lu\n", dwErr));
return(dwErr);
}
//
// Routines provided by AlanWar for accessind WmiGuid objects
//
_inline HANDLE WmipAllocEvent(
VOID
)
{
HANDLE EventHandle;
EventHandle = (HANDLE)InterlockedExchangePointer(( PVOID *)&WmiGuidHandle, NULL );
if ( EventHandle == NULL ) {
EventHandle = CreateEvent( NULL, FALSE, FALSE, NULL );
}
return( EventHandle );
}
_inline void WmipFreeEvent(
HANDLE EventHandle
)
{
if ( InterlockedCompareExchangePointer( &WmiGuidHandle,
EventHandle,
NULL) != NULL ) {
CloseHandle( EventHandle );
}
}
ULONG WmipSendWmiKMRequest(
ULONG Ioctl,
PVOID Buffer,
ULONG InBufferSize,
ULONG MaxBufferSize,
ULONG *ReturnSize
)
/*+++
Routine Description:
This routine does the work of sending WMI requests to the WMI kernel
mode device. Any retry errors returned by the WMI device are handled
in this routine.
Arguments:
Ioctl is the IOCTL code to send to the WMI device
Buffer is the input and output buffer for the call to the WMI device
InBufferSize is the size of the buffer passed to the device
MaxBufferSize is the maximum number of bytes that can be written
into the buffer
*ReturnSize on return has the actual number of bytes written in buffer
Return Value:
ERROR_SUCCESS or an error code
---*/
{
OVERLAPPED Overlapped;
ULONG Status;
BOOL IoctlSuccess;
HANDLE WmipKMHandle = NULL;
//
// If device is not open for then open it now. The
// handle is closed in the process detach dll callout (DlllMain)
WmipKMHandle = CreateFile(WMIDataDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED,
NULL);
if (WmipKMHandle == (HANDLE)-1)
{
WmipKMHandle = NULL;
return(GetLastError());
}
Overlapped.hEvent = WmipAllocEvent();
if (Overlapped.hEvent == NULL)
{
return(ERROR_NOT_ENOUGH_MEMORY);
}
do
{
IoctlSuccess = DeviceIoControl(WmipKMHandle,
Ioctl,
Buffer,
InBufferSize,
Buffer,
MaxBufferSize,
ReturnSize,
&Overlapped);
if (GetLastError() == ERROR_IO_PENDING)
{
IoctlSuccess = GetOverlappedResult(WmipKMHandle,
&Overlapped,
ReturnSize,
TRUE);
}
if (! IoctlSuccess)
{
Status = GetLastError();
} else {
Status = ERROR_SUCCESS;
}
} while (Status == ERROR_WMI_TRY_AGAIN);
NtClose( WmipKMHandle );
WmipFreeEvent(Overlapped.hEvent);
return(Status);
}
//+---------------------------------------------------------------------------
//
// Function: OpenWmiGuidObject
//
// Synopsis: Gets a handle to the specified WmiGuid object
//
// Arguments: [IN pwszObject] -- Object to open
// [IN AccessMask] -- Type of open to do
// [OUT pHandle] -- Where the handle to the object
// is returned
// [OUT KernelType] -- Type of the kernel object
//
// Returns: ERROR_SUCCESS -- Success
//
//----------------------------------------------------------------------------
DWORD
OpenWmiGuidObject(IN LPWSTR pwszObject,
IN ACCESS_MASK AccessMask,
OUT PHANDLE pHandle,
OUT PMARTA_KERNEL_TYPE KernelType)
{
DWORD dwErr;
UNICODE_STRING GuidString;
WMIOPENGUIDBLOCK WmiOpenGuidBlock;
WCHAR GuidObjectNameBuffer[WmiGuidObjectNameLength+1];
PWCHAR GuidObjectName = GuidObjectNameBuffer;
ULONG ReturnSize;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG Length;
acDebugOut((DEB_TRACE, "In OpenWmiGuidObject\n"));
Length = (wcslen(WmiGuidObjectDirectory) + wcslen(pwszObject) + 1) * sizeof(WCHAR);
if ( Length > sizeof(GuidObjectNameBuffer) )
{
GuidObjectName = (PWCHAR)LocalAlloc( LPTR, Length );
if ( GuidObjectName == NULL )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
}
wcscpy(GuidObjectName, WmiGuidObjectDirectory);
wcscat(GuidObjectName, pwszObject);
RtlInitUnicodeString(&GuidString, GuidObjectName);
memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.ObjectName = &GuidString;
WmiOpenGuidBlock.ObjectAttributes = &ObjectAttributes;
WmiOpenGuidBlock.DesiredAccess = AccessMask;
dwErr = WmipSendWmiKMRequest(IOCTL_WMI_OPEN_GUID,
(PVOID)&WmiOpenGuidBlock,
sizeof(WMIOPENGUIDBLOCK),
sizeof(WMIOPENGUIDBLOCK),
&ReturnSize);
if (dwErr == ERROR_SUCCESS)
{
*pHandle = WmiOpenGuidBlock.Handle.Handle;
*KernelType = MARTA_WMI_GUID;
}
else
{
*pHandle = NULL;
}
if ( GuidObjectName != GuidObjectNameBuffer )
{
LocalFree( GuidObjectName );
}
acDebugOut((DEB_TRACE, "Out OpenWmiGuidObject: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: ReadWmiGuidPropertyRights
//
// Synopsis: Gets the specified rights from the WmiGuids object
//
// Arguments: [IN pwszObject] -- The object to get the rights
// for
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was encountered
//
// Note: Kernel objects are assumed to be created through the
// Win32 APIs so they all reside in the \basenamedobjects
// directory.
//
//----------------------------------------------------------------------------
DWORD
ReadWmiGuidPropertyRights(IN LPWSTR pwszObject,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in ReadKernelPropertyRights\n"));
DWORD dwErr = ERROR_SUCCESS;
HANDLE hObject;
MARTA_KERNEL_TYPE KernelType;
//
// Kernel objects don't have parents from whom they can inherit
//
ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
{
return(ERROR_INVALID_PARAMETER);
}
dwErr = OpenWmiGuidObject(pwszObject,
GetDesiredAccess(READ_ACCESS_RIGHTS,
pRightsList[0].SeInfo),
&hObject,
&KernelType);
if(dwErr == ERROR_SUCCESS)
{
dwErr = GetWmiGuidSecurityInfo(hObject,
pRightsList,
cRights,
AccessList);
CloseWmiGuidObject(hObject);
}
acDebugOut((DEB_TRACE, "Out ReadKernelPropertyRights: %lu\n", dwErr));
return (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetKernelSecurityInfo
//
// Arguments: [IN hObject] -- The handle to the object to
// get the rights for
// [IN SeInfo] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
GetWmiGuidSecurityInfo(IN HANDLE hObject,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in GetWmiGuidSecurityInfo\n"));
UCHAR pSDBuff[PSD_BASE_LENGTH];
PISECURITY_DESCRIPTOR pSD;
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
ULONG cNeeded = 0;
for(ULONG iIndex = 0; iIndex < cRights && dwErr == ERROR_SUCCESS; iIndex++)
{
pSD = (PISECURITY_DESCRIPTOR)pSDBuff;
Status = NtQuerySecurityObject(hObject,
pRightsList[iIndex].SeInfo,
pSD,
PSD_BASE_LENGTH,
&cNeeded);
if(!NT_SUCCESS(Status))
{
if(Status == STATUS_BUFFER_TOO_SMALL)
{
//
// Fine.. Allocate a big enough buffer
//
pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
if(pSD == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
Status = NtQuerySecurityObject(hObject,
pRightsList[iIndex].SeInfo,
pSD,
cNeeded,
&cNeeded);
}
}
//
// Now, we've either got a failure or a valid SD...
//
if(NT_SUCCESS(Status))
{
dwErr = AccessList.AddSD(pSD,
pRightsList[iIndex].SeInfo,
pRightsList[iIndex].pwszProperty);
}
else
{
dwErr = RtlNtStatusToDosError(Status);
}
if(pSD != (PISECURITY_DESCRIPTOR)pSDBuff)
{
AccFree(pSD);
}
}
acDebugOut((DEB_TRACE, "Out GetWmiGuidSecurityInfo: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: SetWmiGuidSecurityInfo
//
// Synopsis: Sets the specified security info for the handle's
// WmiGuid object
//
// Arguments: [IN hKernel] -- The handle of the object
// [IN SeInfo] -- Flag indicating what security
// info to set
// [IN pwszProperty] -- The property on the object to
// set
// For kernel objects, this MBZ
// [IN pSD] -- The security descriptor to set
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was given
//
//----------------------------------------------------------------------------
DWORD
SetWmiGuidSecurityInfo(IN HANDLE hWmiGuid,
IN SECURITY_INFORMATION SeInfo,
IN PWSTR pwszProperty,
IN PSECURITY_DESCRIPTOR pSD)
{
acDebugOut((DEB_TRACE, "in SetWmiGuidSecurityInfo\n"));
DWORD dwErr = ERROR_SUCCESS;
if(pwszProperty != NULL)
{
dwErr = ERROR_INVALID_PARAMETER;
}
else
{
NTSTATUS Status = NtSetSecurityObject(hWmiGuid,
SeInfo,
pSD);
dwErr = RtlNtStatusToDosError(Status);
}
acDebugOut((DEB_TRACE, "Out SetWmiGuidSecurityInfo %lu\n", dwErr));
return (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetKernelSecurityInfo
//
// Arguments: [IN hObject] -- The handle to the object to
// get the rights for
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
GetWmiGuidSecurityInfo(IN HANDLE hObject,
IN SECURITY_INFORMATION SeInfo,
OUT PACL *ppDAcl,
OUT PACL *ppSAcl,
OUT PSECURITY_DESCRIPTOR *ppSD)
{
acDebugOut((DEB_TRACE, "in GetWmiGuidSecurityInfo\n"));
PISECURITY_DESCRIPTOR pSD = NULL;
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
ULONG cNeeded = 0;
Status = NtQuerySecurityObject(hObject,
SeInfo,
pSD,
0,
&cNeeded);
if(!NT_SUCCESS(Status))
{
if(Status == STATUS_BUFFER_TOO_SMALL)
{
//
// Fine.. Allocate a big enough buffer
//
pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cNeeded);
if(pSD == NULL)
{
Status = STATUS_NO_MEMORY;
}
else
{
Status = NtQuerySecurityObject(hObject,
SeInfo,
pSD,
cNeeded,
&cNeeded);
}
}
}
//
// Now, we've either got a failure or a valid SD...
//
if(NT_SUCCESS(Status))
{
if (pSD != NULL)
{
if(ppDAcl != NULL)
{
*ppDAcl = RtlpDaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
}
if(ppSAcl != NULL)
{
*ppSAcl = RtlpSaclAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)pSD);
}
*ppSD = pSD;
}
else
{
dwErr = ERROR_ACCESS_DENIED;
}
}
else
{
dwErr = RtlNtStatusToDosError(Status);
}
acDebugOut((DEB_TRACE, "Out GetWmiGuidSecurityInfo: %lu\n", dwErr));
return(dwErr);
}