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:
Filip Navara 2005-03-12 08:54:41 +00:00
parent 724d399a3f
commit 57787bb881
8 changed files with 288 additions and 27 deletions

View file

@ -770,6 +770,13 @@ NTSTATUS
STDCALL
RtlDeleteTimerQueue(HANDLE TimerQueue);
PVOID
STDCALL
RtlEncodePointer(IN PVOID Pointer);
PVOID
STDCALL
RtlDecodePointer(IN PVOID Pointer);
#ifndef __NTDRIVER__

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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 */

View file

@ -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);
}

View file

@ -416,6 +416,7 @@ struct _EPROCESS
PRTL_BITMAP VadPhysicalPagesBitMap;
ULONG VadPhysicalPages;
KSPIN_LOCK AweLock;
ULONG Cookie;
/*
* FIXME - ReactOS specified - remove the following fields ASAP!!!

View file

@ -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;
}