mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +00:00
Simplify buffer checks for NtQueryInformation...() and NtSetInformation...() using universal macros and information class tables
svn path=/trunk/; revision=13196
This commit is contained in:
parent
52fadec1ee
commit
81fd53f09d
2 changed files with 230 additions and 54 deletions
|
@ -339,5 +339,169 @@ ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttribut
|
|||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN BOOLEAN CaptureIfKernel);
|
||||
|
||||
/* object information classes */
|
||||
|
||||
#define ICIF_QUERY 0x1
|
||||
#define ICIF_SET 0x2
|
||||
#define ICIF_QUERY_SIZE_VARIABLE 0x4
|
||||
#define ICIF_SET_SIZE_VARIABLE 0x8
|
||||
#define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE)
|
||||
|
||||
typedef struct _INFORMATION_CLASS_INFO
|
||||
{
|
||||
ULONG RequiredSizeQUERY;
|
||||
ULONG RequiredSizeSET;
|
||||
ULONG AlignmentSET;
|
||||
ULONG AlignmentQUERY;
|
||||
ULONG Flags;
|
||||
} INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO;
|
||||
|
||||
#define ICI_SQ_SAME(Size, Alignment, Flags) \
|
||||
{ Size, Size, Alignment, Alignment, Flags }
|
||||
|
||||
#define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \
|
||||
{ SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags }
|
||||
|
||||
#define CheckInfoClass(Class, BufferLen, ClassList, StatusVar, Mode) \
|
||||
do { \
|
||||
if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
|
||||
{ \
|
||||
if(!(ClassList[Class].Flags & ICIF_##Mode)) \
|
||||
{ \
|
||||
*(StatusVar) = STATUS_INVALID_INFO_CLASS; \
|
||||
} \
|
||||
else if(ClassList[Class].RequiredSize##Mode > 0 && \
|
||||
(BufferLen) != ClassList[Class].RequiredSize##Mode) \
|
||||
{ \
|
||||
if(!(ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) || \
|
||||
((ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \
|
||||
(BufferLen) < ClassList[Class].RequiredSize##Mode)) \
|
||||
{ \
|
||||
*(StatusVar) = STATUS_INFO_LENGTH_MISMATCH; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*(StatusVar) = STATUS_INVALID_INFO_CLASS; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define GetInfoClassAlignment(Class, ClassList, AlignmentVar, Mode) \
|
||||
do { \
|
||||
if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
|
||||
{ \
|
||||
*(AlignmentVar) = ClassList[Class].Alignment##Mode; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*(AlignmentVar) = sizeof(ULONG); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ProbeQueryInfoBuffer(Buffer, BufferLen, Alignment, RetLen, PrevMode, StatusVar) \
|
||||
do { \
|
||||
if(PrevMode == UserMode) \
|
||||
{ \
|
||||
_SEH_TRY \
|
||||
{ \
|
||||
ProbeForWrite(Buffer, \
|
||||
BufferLen, \
|
||||
Alignment); \
|
||||
if(RetLen != NULL) \
|
||||
{ \
|
||||
ProbeForWrite(RetLen, \
|
||||
sizeof(ULONG), \
|
||||
1); \
|
||||
} \
|
||||
} \
|
||||
_SEH_HANDLE \
|
||||
{ \
|
||||
*(StatusVar) = _SEH_GetExceptionCode(); \
|
||||
} \
|
||||
_SEH_END; \
|
||||
\
|
||||
if(!NT_SUCCESS(*(StatusVar))) \
|
||||
{ \
|
||||
DPRINT1("ProbeQueryInfoBuffer failed: 0x%x\n", *(StatusVar)); \
|
||||
return *(StatusVar); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ProbeSetInfoBuffer(Buffer, BufferLen, Alignment, PrevMode, StatusVar) \
|
||||
do { \
|
||||
if(PrevMode == UserMode) \
|
||||
{ \
|
||||
_SEH_TRY \
|
||||
{ \
|
||||
ProbeForRead(Buffer, \
|
||||
BufferLen, \
|
||||
Alignment); \
|
||||
} \
|
||||
_SEH_HANDLE \
|
||||
{ \
|
||||
*(StatusVar) = _SEH_GetExceptionCode(); \
|
||||
} \
|
||||
_SEH_END; \
|
||||
\
|
||||
if(!NT_SUCCESS(*(StatusVar))) \
|
||||
{ \
|
||||
DPRINT1("ProbeAllInfoBuffer failed: 0x%x\n", *(StatusVar)); \
|
||||
return *(StatusVar); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define DefaultSetInfoBufferCheck(Class, ClassList, Buffer, BufferLen, PrevMode, StatusVar) \
|
||||
do { \
|
||||
ULONG _Alignment; \
|
||||
/* get the preferred alignment for the information class or return */ \
|
||||
/* default alignment in case the class doesn't exist */ \
|
||||
GetInfoClassAlignment(Class, \
|
||||
ClassList, \
|
||||
&_Alignment, \
|
||||
SET); \
|
||||
\
|
||||
/* probe the ENTIRE buffers and return on failure */ \
|
||||
ProbeSetInfoBuffer(Buffer, \
|
||||
BufferLen, \
|
||||
_Alignment, \
|
||||
PrevMode, \
|
||||
StatusVar); \
|
||||
\
|
||||
/* validate information class index and check buffer size */ \
|
||||
CheckInfoClass(Class, \
|
||||
BufferLen, \
|
||||
ClassList, \
|
||||
StatusVar, \
|
||||
SET); \
|
||||
} while(0)
|
||||
|
||||
#define DefaultQueryInfoBufferCheck(Class, ClassList, Buffer, BufferLen, RetLen, PrevMode, StatusVar) \
|
||||
do { \
|
||||
ULONG _Alignment; \
|
||||
/* get the preferred alignment for the information class or return */ \
|
||||
/* alignment in case the class doesn't exist */ \
|
||||
GetInfoClassAlignment(Class, \
|
||||
ClassList, \
|
||||
&_Alignment, \
|
||||
QUERY); \
|
||||
\
|
||||
/* probe the ENTIRE buffers and return on failure */ \
|
||||
ProbeQueryInfoBuffer(Buffer, \
|
||||
BufferLen, \
|
||||
_Alignment, \
|
||||
RetLen, \
|
||||
PrevMode, \
|
||||
StatusVar); \
|
||||
\
|
||||
/* validate information class index and check buffer size */ \
|
||||
CheckInfoClass(Class, \
|
||||
BufferLen, \
|
||||
ClassList, \
|
||||
StatusVar, \
|
||||
QUERY); \
|
||||
} while(0)
|
||||
|
||||
#endif /* __INCLUDE_INTERNAL_OBJMGR_H */
|
||||
|
|
|
@ -33,6 +33,44 @@ static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_
|
|||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
PROCESS_ALL_ACCESS};
|
||||
|
||||
static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
|
||||
{
|
||||
ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* ProcessBasicInformation */
|
||||
ICI_SQ_SAME( sizeof(QUOTA_LIMITS), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessQuotaLimits */
|
||||
ICI_SQ_SAME( sizeof(IO_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessIoCounters */
|
||||
ICI_SQ_SAME( sizeof(VM_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessVmCounters */
|
||||
ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES), sizeof(ULONG), ICIF_QUERY ), /* ProcessTimes */
|
||||
ICI_SQ_SAME( sizeof(KPRIORITY), sizeof(ULONG), ICIF_SET ), /* ProcessBasePriority */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET ), /* ProcessRaisePriority */
|
||||
ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDebugPort */
|
||||
ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_SET ), /* ProcessExceptionPort */
|
||||
ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN), sizeof(ULONG), ICIF_SET ), /* ProcessAccessToken */
|
||||
ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessLdtInformation */
|
||||
ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessLdtSize */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDefaultHardErrorMode */
|
||||
ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessIoPortHandlers */
|
||||
ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS), sizeof(ULONG), ICIF_QUERY ), /* ProcessPooledUsageAndLimits */
|
||||
ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessWorkingSetWatch */
|
||||
ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessUserModeIOPL */
|
||||
ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessEnableAlignmentFaultFixup */
|
||||
ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS), sizeof(ULONG), ICIF_SET ), /* ProcessPriorityClass */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWx86Information */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessHandleCount */
|
||||
ICI_SQ_SAME( sizeof(KAFFINITY), sizeof(ULONG), ICIF_SET ), /* ProcessAffinityMask */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityBoost */
|
||||
|
||||
ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query), /* ProcessDeviceMap */
|
||||
/*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set),
|
||||
/*Q*/ sizeof(ULONG),
|
||||
/*S*/ sizeof(ULONG),
|
||||
ICIF_QUERY | ICIF_SET ),
|
||||
|
||||
ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessSessionInformation */
|
||||
ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessForegroundInformation */
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWow64Information */
|
||||
ICI_SQ_SAME( sizeof(UNICODE_STRING), sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */
|
||||
};
|
||||
|
||||
#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
|
||||
#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
|
||||
|
||||
|
@ -1133,39 +1171,22 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
|||
OUT PULONG ReturnLength OPTIONAL)
|
||||
{
|
||||
PEPROCESS Process;
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
DefaultQueryInfoBufferCheck(ProcessInformationClass,
|
||||
PsProcessInfoClass,
|
||||
ProcessInformation,
|
||||
ProcessInformationLength,
|
||||
ReturnLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForWrite(ProcessInformation,
|
||||
ProcessInformationLength,
|
||||
sizeof(ULONG));
|
||||
if(ReturnLength)
|
||||
{
|
||||
ProbeForWrite(ReturnLength,
|
||||
sizeof(ULONG),
|
||||
1);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1669,45 +1690,36 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
IN ULONG ProcessInformationLength)
|
||||
{
|
||||
PEPROCESS Process;
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
ACCESS_MASK Access;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
DefaultSetInfoBufferCheck(ProcessInformationClass,
|
||||
PsProcessInfoClass,
|
||||
ProcessInformation,
|
||||
ProcessInformationLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForRead(ProcessInformation,
|
||||
ProcessInformationLength,
|
||||
sizeof(ULONG));
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
DPRINT1("NtSetInformationProcess() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Access = PROCESS_SET_INFORMATION;
|
||||
|
||||
switch(ProcessInformationClass)
|
||||
{
|
||||
case ProcessSessionInformation:
|
||||
Access |= PROCESS_SET_SESSIONID;
|
||||
Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID;
|
||||
break;
|
||||
case ProcessExceptionPort:
|
||||
case ProcessDebugPort:
|
||||
Access |= PROCESS_SET_PORT;
|
||||
Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT;
|
||||
break;
|
||||
|
||||
default:
|
||||
Access = PROCESS_SET_INFORMATION;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue