mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
Thomas Weidenmueller <w3seek@reactos.com>
- Implement support for vectored exception handlers. - Add code for querying process cookie. svn path=/trunk/; revision=13962
This commit is contained in:
parent
724d399a3f
commit
57787bb881
8 changed files with 288 additions and 27 deletions
|
@ -770,6 +770,13 @@ NTSTATUS
|
|||
STDCALL
|
||||
RtlDeleteTimerQueue(HANDLE TimerQueue);
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
RtlEncodePointer(IN PVOID Pointer);
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
RtlDecodePointer(IN PVOID Pointer);
|
||||
|
||||
#ifndef __NTDRIVER__
|
||||
|
||||
|
|
|
@ -1219,9 +1219,17 @@ extern IMPORTED ULONG NtBuildNumber;
|
|||
#define ProcessSessionInformation 24
|
||||
#define ProcessForegroundInformation 25
|
||||
#define ProcessWow64Information 26
|
||||
/* ReactOS private. */
|
||||
#define ProcessImageFileName 27
|
||||
#define MaxProcessInfoClass 28
|
||||
#define ProcessLUIDDeviceMapsEnabled 28
|
||||
#define ProcessBreakOnTermination 29
|
||||
#define ProcessDebugObjectHandle 30
|
||||
#define ProcessDebugFlags 31
|
||||
#define ProcessHandleTracing 32
|
||||
#define ProcessUnknown33 33
|
||||
#define ProcessUnknown34 34
|
||||
#define ProcessUnknown35 35
|
||||
#define ProcessCookie 36
|
||||
#define MaxProcessInfoClass 36
|
||||
|
||||
/*
|
||||
* thread query / set information class
|
||||
|
|
|
@ -225,7 +225,6 @@ NtSetEaFile@16
|
|||
NtSetEvent@8
|
||||
NtSetHighEventPair@4
|
||||
NtSetHighWaitLowEventPair@4
|
||||
NtSetHighWaitLowThread@0
|
||||
NtSetInformationFile@20
|
||||
NtSetInformationJobObject@16
|
||||
NtSetInformationKey@16
|
||||
|
@ -238,7 +237,6 @@ NtSetIoCompletion@20
|
|||
NtSetLdtEntries@24
|
||||
NtSetLowEventPair@4
|
||||
NtSetLowWaitHighEventPair@4
|
||||
NtSetLowWaitHighThread@0
|
||||
NtSetSecurityObject@12
|
||||
NtSetSystemEnvironmentValue@8
|
||||
NtSetSystemInformation@12
|
||||
|
@ -298,6 +296,7 @@ RtlAddAuditAccessAce@24
|
|||
RtlAddAuditAccessAceEx@28
|
||||
;RtlAddCompoundAce
|
||||
RtlAddRange@36
|
||||
RtlAddVectoredExceptionHandler@8
|
||||
RtlAdjustPrivilege@16
|
||||
RtlAllocateAndInitializeSid@44
|
||||
RtlAllocateHandle@8
|
||||
|
@ -364,6 +363,7 @@ RtlCreateUserThread@40
|
|||
RtlCustomCPToUnicodeN@24
|
||||
RtlCutoverTimeToSystemTime@16
|
||||
RtlDeNormalizeProcessParams@4
|
||||
RtlDecodePointer=RtlEncodePointer@4
|
||||
RtlDecompressBuffer@24
|
||||
RtlDecompressFragment@32
|
||||
RtlDelete@4
|
||||
|
@ -396,6 +396,7 @@ RtlDowncaseUnicodeString@12
|
|||
RtlDumpResource@4
|
||||
RtlDuplicateUnicodeString@12
|
||||
RtlEmptyAtomTable@8
|
||||
RtlEncodePointer@4
|
||||
RtlEnlargedIntegerMultiply@8
|
||||
RtlEnlargedUnsignedDivide@16
|
||||
RtlEnlargedUnsignedMultiply@8
|
||||
|
@ -593,6 +594,7 @@ RtlRealSuccessor@4
|
|||
RtlReleasePebLock@0
|
||||
RtlReleaseResource@4
|
||||
;RtlRemoteCall
|
||||
RtlRemoveVectoredExceptionHandler@4
|
||||
RtlResetRtlTranslations@4
|
||||
RtlRestoreLastWin32Error@4=RtlSetLastWin32Error@4
|
||||
RtlRunDecodeUnicodeString@8
|
||||
|
@ -849,7 +851,6 @@ ZwSetEaFile@16
|
|||
ZwSetEvent@8
|
||||
ZwSetHighEventPair@4
|
||||
ZwSetHighWaitLowEventPair@4
|
||||
ZwSetHighWaitLowThread@0
|
||||
ZwSetInformationFile@20
|
||||
ZwSetInformationKey@16
|
||||
ZwSetInformationObject@16
|
||||
|
@ -861,7 +862,6 @@ ZwSetIoCompletion@20
|
|||
ZwSetLdtEntries@24
|
||||
ZwSetLowEventPair@4
|
||||
ZwSetLowWaitHighEventPair@4
|
||||
ZwSetLowWaitHighThread@0
|
||||
ZwSetSecurityObject@12
|
||||
ZwSetSystemEnvironmentValue@8
|
||||
ZwSetSystemInformation@12
|
||||
|
|
|
@ -39,6 +39,8 @@ PLDR_MODULE ExeModule;
|
|||
|
||||
NTSTATUS LdrpAttachThread (VOID);
|
||||
|
||||
VOID RtlpInitializeVectoredExceptionHandling(VOID);
|
||||
|
||||
|
||||
#define VALUE_BUFFER_SIZE 256
|
||||
|
||||
|
@ -306,6 +308,9 @@ __true_LdrInitializeThunk (ULONG Unknown1,
|
|||
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/* initialized vectored exception handling */
|
||||
RtlpInitializeVectoredExceptionHandling();
|
||||
|
||||
/* initalize peb lock support */
|
||||
RtlInitializeCriticalSection (&PebLock);
|
||||
Peb->FastPebLock = &PebLock;
|
||||
|
|
|
@ -22,6 +22,19 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
static CRITICAL_SECTION RtlpVectoredExceptionLock;
|
||||
static LIST_ENTRY RtlpVectoredExceptionHead;
|
||||
|
||||
typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PVECTORED_EXCEPTION_HANDLER VectoredHandler;
|
||||
} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;
|
||||
|
||||
/* FIXME - stupid ld won't resolve RtlDecodePointer! Since their implementation
|
||||
is the same just use RtlEncodePointer for now! */
|
||||
#define RtlDecodePointer RtlEncodePointer
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
VOID STDCALL
|
||||
|
@ -35,6 +48,41 @@ ULONG
|
|||
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||
IN PCONTEXT Context);
|
||||
|
||||
EXCEPTION_DISPOSITION
|
||||
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||
IN PCONTEXT Context)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PRTL_VECTORED_EXCEPTION_HANDLER veh;
|
||||
PVECTORED_EXCEPTION_HANDLER VectoredHandler;
|
||||
EXCEPTION_POINTERS ExceptionInfo;
|
||||
|
||||
ExceptionInfo.ExceptionRecord = ExceptionRecord;
|
||||
ExceptionInfo.ContextRecord = Context;
|
||||
|
||||
if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead)
|
||||
{
|
||||
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
|
||||
for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
|
||||
CurrentEntry != &RtlpVectoredExceptionHead;
|
||||
CurrentEntry = CurrentEntry->Flink)
|
||||
{
|
||||
veh = CONTAINING_RECORD(CurrentEntry,
|
||||
RTL_VECTORED_EXCEPTION_HANDLER,
|
||||
ListEntry);
|
||||
VectoredHandler = RtlDecodePointer(veh->VectoredHandler);
|
||||
if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
||||
PCONTEXT Context)
|
||||
|
@ -42,13 +90,21 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
|||
EXCEPTION_RECORD NestedExceptionRecord;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
|
||||
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
|
||||
Context) != ExceptionContinueExecution)
|
||||
{
|
||||
Status = NtContinue(Context, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
|
||||
if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
|
||||
{
|
||||
Status = NtContinue(Context, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NestedExceptionRecord.ExceptionCode = Status;
|
||||
|
@ -87,4 +143,83 @@ RtlBaseProcessStart(PTHREAD_START_ROUTINE StartAddress,
|
|||
NtTerminateProcess(NtCurrentProcess(), ExitStatus);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
RtlpInitializeVectoredExceptionHandling(VOID)
|
||||
{
|
||||
InitializeListHead(&RtlpVectoredExceptionHead);
|
||||
RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
|
||||
IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
|
||||
{
|
||||
PRTL_VECTORED_EXCEPTION_HANDLER veh;
|
||||
|
||||
veh = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
sizeof(RTL_VECTORED_EXCEPTION_HANDLER));
|
||||
if(veh != NULL)
|
||||
{
|
||||
veh->VectoredHandler = RtlEncodePointer(VectoredHandler);
|
||||
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
|
||||
if(FirstHandler != 0)
|
||||
{
|
||||
InsertHeadList(&RtlpVectoredExceptionHead,
|
||||
&veh->ListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertTailList(&RtlpVectoredExceptionHead,
|
||||
&veh->ListEntry);
|
||||
}
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
|
||||
return veh;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG STDCALL
|
||||
RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
|
||||
ULONG Removed = FALSE;
|
||||
|
||||
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
|
||||
for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
|
||||
CurrentEntry != &RtlpVectoredExceptionHead;
|
||||
CurrentEntry = CurrentEntry->Flink)
|
||||
{
|
||||
veh = CONTAINING_RECORD(CurrentEntry,
|
||||
RTL_VECTORED_EXCEPTION_HANDLER,
|
||||
ListEntry);
|
||||
if(veh == VectoredHandlerHandle)
|
||||
{
|
||||
RemoveEntryList(&veh->ListEntry);
|
||||
Removed = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
|
||||
if(Removed)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
veh);
|
||||
}
|
||||
|
||||
return Removed;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include <ddk/ntddk.h>
|
||||
#include <ntdll/rtl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <ntdll/ntdll.h>
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* RtlGetNtProductType
|
||||
|
@ -107,3 +110,30 @@ RtlGetNtGlobalFlags(VOID)
|
|||
PPEB pPeb = NtCurrentPeb();
|
||||
return pPeb->NtGlobalFlag;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
RtlEncodePointer(IN PVOID Pointer)
|
||||
{
|
||||
ULONG Cookie;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = NtQueryInformationProcess(NtCurrentProcess(),
|
||||
ProcessCookie,
|
||||
&Cookie,
|
||||
sizeof(Cookie),
|
||||
NULL);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to receive the process cookie! Status: 0x%x\n", Status);
|
||||
return Pointer;
|
||||
}
|
||||
|
||||
return (PVOID)((ULONG_PTR)Pointer ^ Cookie);
|
||||
}
|
||||
|
||||
|
|
|
@ -416,6 +416,7 @@ struct _EPROCESS
|
|||
PRTL_BITMAP VadPhysicalPagesBitMap;
|
||||
ULONG VadPhysicalPages;
|
||||
KSPIN_LOCK AweLock;
|
||||
ULONG Cookie;
|
||||
|
||||
/*
|
||||
* FIXME - ReactOS specified - remove the following fields ASAP!!!
|
||||
|
|
|
@ -67,6 +67,18 @@ static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
|
|||
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 */
|
||||
|
||||
/* FIXME */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessLUIDDeviceMapsEnabled */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessBreakOnTermination */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugObjectHandle */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugFlags */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessHandleTracing */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown33 */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown34 */
|
||||
ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown35 */
|
||||
|
||||
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY), /* ProcessCookie */
|
||||
};
|
||||
|
||||
#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
|
||||
|
@ -1339,21 +1351,26 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Here we should probably check that ProcessInformationLength
|
||||
* bytes indeed are writable at address ProcessInformation.
|
||||
*/
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
if(ProcessInformationClass != ProcessCookie)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else if(ProcessHandle != NtCurrentProcess())
|
||||
{
|
||||
/* retreiving the process cookie is only allowed for the calling process
|
||||
itself! XP only allowes NtCurrentProcess() as process handles even if a
|
||||
real handle actually represents the current process. */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
switch (ProcessInformationClass)
|
||||
{
|
||||
|
@ -1732,6 +1749,60 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
|||
break;
|
||||
}
|
||||
|
||||
case ProcessCookie:
|
||||
{
|
||||
ULONG Cookie;
|
||||
|
||||
/* receive the process cookie, this is only allowed for the current
|
||||
process! */
|
||||
|
||||
Process = PsGetCurrentProcess();
|
||||
|
||||
Cookie = Process->Cookie;
|
||||
if(Cookie == 0)
|
||||
{
|
||||
LARGE_INTEGER SystemTime;
|
||||
ULONG NewCookie;
|
||||
PKPRCB Prcb;
|
||||
|
||||
/* generate a new cookie */
|
||||
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
|
||||
Prcb = &KeGetCurrentKPCR()->PrcbData;
|
||||
|
||||
NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
|
||||
SystemTime.u.LowPart ^ SystemTime.u.HighPart;
|
||||
|
||||
/* try to set the new cookie, return the current one if another thread
|
||||
set it in the meanwhile */
|
||||
Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
|
||||
NewCookie,
|
||||
Cookie);
|
||||
if(Cookie == 0)
|
||||
{
|
||||
/* successfully set the cookie */
|
||||
Cookie = NewCookie;
|
||||
}
|
||||
}
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
*(PULONG)ProcessInformation = Cookie;
|
||||
if (ReturnLength)
|
||||
{
|
||||
*ReturnLength = sizeof(ULONG);
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: The following 10 information classes are verified to not be
|
||||
* implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
|
||||
|
@ -1750,7 +1821,11 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
|||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
}
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
if(ProcessInformationClass != ProcessCookie)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue