Thomas Weidenmueller <w3seek(a)reactos.com>
- Implement support for vectored exception handlers.
- Add code for querying process cookie.
Modified: trunk/reactos/include/ntdll/rtl.h
Modified: trunk/reactos/include/ntos/zwtypes.h
Modified: trunk/reactos/lib/ntdll/def/ntdll.def
Modified: trunk/reactos/lib/ntdll/ldr/startup.c
Modified: trunk/reactos/lib/ntdll/rtl/exception.c
Modified: trunk/reactos/lib/ntdll/rtl/misc.c
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
Modified: trunk/reactos/ntoskrnl/ps/process.c
_____
Modified: trunk/reactos/include/ntdll/rtl.h
--- trunk/reactos/include/ntdll/rtl.h 2005-03-12 07:52:16 UTC (rev
13961)
+++ trunk/reactos/include/ntdll/rtl.h 2005-03-12 08:54:41 UTC (rev
13962)
@@ -770,7 +770,14 @@
STDCALL
RtlDeleteTimerQueue(HANDLE TimerQueue);
+PVOID
+STDCALL
+RtlEncodePointer(IN PVOID Pointer);
+PVOID
+STDCALL
+RtlDecodePointer(IN PVOID Pointer);
+
#ifndef __NTDRIVER__
#ifndef __INTERLOCKED_DECLARED
_____
Modified: trunk/reactos/include/ntos/zwtypes.h
--- trunk/reactos/include/ntos/zwtypes.h 2005-03-12 07:52:16 UTC
(rev 13961)
+++ trunk/reactos/include/ntos/zwtypes.h 2005-03-12 08:54:41 UTC
(rev 13962)
@@ -1219,9 +1219,17 @@
#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
_____
Modified: trunk/reactos/lib/ntdll/def/ntdll.def
--- trunk/reactos/lib/ntdll/def/ntdll.def 2005-03-12 07:52:16 UTC
(rev 13961)
+++ trunk/reactos/lib/ntdll/def/ntdll.def 2005-03-12 08:54:41 UTC
(rev 13962)
@@ -225,7 +225,6 @@
NtSetEvent@8
NtSetHighEventPair@4
NtSetHighWaitLowEventPair@4
-NtSetHighWaitLowThread@0
NtSetInformationFile@20
NtSetInformationJobObject@16
NtSetInformationKey@16
@@ -238,7 +237,6 @@
NtSetLdtEntries@24
NtSetLowEventPair@4
NtSetLowWaitHighEventPair@4
-NtSetLowWaitHighThread@0
NtSetSecurityObject@12
NtSetSystemEnvironmentValue@8
NtSetSystemInformation@12
@@ -298,6 +296,7 @@
RtlAddAuditAccessAceEx@28
;RtlAddCompoundAce
RtlAddRange@36
+RtlAddVectoredExceptionHandler@8
RtlAdjustPrivilege@16
RtlAllocateAndInitializeSid@44
RtlAllocateHandle@8
@@ -364,6 +363,7 @@
RtlCustomCPToUnicodeN@24
RtlCutoverTimeToSystemTime@16
RtlDeNormalizeProcessParams@4
+RtlDecodePointer=RtlEncodePointer@4
RtlDecompressBuffer@24
RtlDecompressFragment@32
RtlDelete@4
@@ -396,6 +396,7 @@
RtlDumpResource@4
RtlDuplicateUnicodeString@12
RtlEmptyAtomTable@8
+RtlEncodePointer@4
RtlEnlargedIntegerMultiply@8
RtlEnlargedUnsignedDivide@16
RtlEnlargedUnsignedMultiply@8
@@ -593,6 +594,7 @@
RtlReleasePebLock@0
RtlReleaseResource@4
;RtlRemoteCall
+RtlRemoveVectoredExceptionHandler@4
RtlResetRtlTranslations@4
RtlRestoreLastWin32Error@4=RtlSetLastWin32Error@4
RtlRunDecodeUnicodeString@8
@@ -849,7 +851,6 @@
ZwSetEvent@8
ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair@4
-ZwSetHighWaitLowThread@0
ZwSetInformationFile@20
ZwSetInformationKey@16
ZwSetInformationObject@16
@@ -861,7 +862,6 @@
ZwSetLdtEntries@24
ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair@4
-ZwSetLowWaitHighThread@0
ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation@12
_____
Modified: trunk/reactos/lib/ntdll/ldr/startup.c
--- trunk/reactos/lib/ntdll/ldr/startup.c 2005-03-12 07:52:16 UTC
(rev 13961)
+++ trunk/reactos/lib/ntdll/ldr/startup.c 2005-03-12 08:54:41 UTC
(rev 13962)
@@ -39,7 +39,9 @@
NTSTATUS LdrpAttachThread (VOID);
+VOID RtlpInitializeVectoredExceptionHandling(VOID);
+
#define VALUE_BUFFER_SIZE 256
BOOLEAN FASTCALL
@@ -306,6 +308,9 @@
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
+ /* initialized vectored exception handling */
+ RtlpInitializeVectoredExceptionHandling();
+
/* initalize peb lock support */
RtlInitializeCriticalSection (&PebLock);
Peb->FastPebLock = &PebLock;
_____
Modified: trunk/reactos/lib/ntdll/rtl/exception.c
--- trunk/reactos/lib/ntdll/rtl/exception.c 2005-03-12 07:52:16 UTC
(rev 13961)
+++ trunk/reactos/lib/ntdll/rtl/exception.c 2005-03-12 08:54:41 UTC
(rev 13962)
@@ -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,20 +48,63 @@
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)
{
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 @@
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 */
_____
Modified: trunk/reactos/lib/ntdll/rtl/misc.c
--- trunk/reactos/lib/ntdll/rtl/misc.c 2005-03-12 07:52:16 UTC (rev
13961)
+++ trunk/reactos/lib/ntdll/rtl/misc.c 2005-03-12 08:54:41 UTC (rev
13962)
@@ -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 @@
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);
+}
+
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
--- trunk/reactos/ntoskrnl/include/internal/ps.h 2005-03-12
07:52:16 UTC (rev 13961)
+++ trunk/reactos/ntoskrnl/include/internal/ps.h 2005-03-12
08:54:41 UTC (rev 13962)
@@ -416,6 +416,7 @@
PRTL_BITMAP VadPhysicalPagesBitMap;
ULONG VadPhysicalPages;
KSPIN_LOCK AweLock;
+ ULONG Cookie;
/*
* FIXME - ReactOS specified - remove the following fields ASAP!!!
_____
Modified: trunk/reactos/ntoskrnl/ps/process.c
--- trunk/reactos/ntoskrnl/ps/process.c 2005-03-12 07:52:16 UTC (rev
13961)
+++ trunk/reactos/ntoskrnl/ps/process.c 2005-03-12 08:54:41 UTC (rev
13962)
@@ -67,6 +67,18 @@
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
@@ -1338,23 +1350,28 @@
DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n",
Status);
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)
{
case ProcessBasicInformation:
@@ -1731,7 +1748,61 @@
}
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 @@
Status = STATUS_INVALID_INFO_CLASS;
}
- ObDereferenceObject(Process);
+ if(ProcessInformationClass != ProcessCookie)
+ {
+ ObDereferenceObject(Process);
+ }
+
return Status;
}