mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Correct NtW32call to call correct kernel function, add placeholder for SEH, implement KeUserModeCallback (right now a copy of the old code). Part I of an incomplete W32Callback rewrite, just to set up the groundwork to make testing easier. Might look ugly/messy now but it'll be clean soon
svn path=/trunk/; revision=14199
This commit is contained in:
parent
52a70e745d
commit
396ff5690c
9 changed files with 297 additions and 165 deletions
|
@ -111,6 +111,7 @@ OBJECTS_KE = \
|
||||||
ke/sem.o \
|
ke/sem.o \
|
||||||
ke/spinlock.o \
|
ke/spinlock.o \
|
||||||
ke/timer.o \
|
ke/timer.o \
|
||||||
|
ke/usercall.o \
|
||||||
ke/wait.o
|
ke/wait.o
|
||||||
|
|
||||||
# Memory Manager (Mm)
|
# Memory Manager (Mm)
|
||||||
|
@ -230,8 +231,7 @@ OBJECTS_PS = \
|
||||||
ps/security.o \
|
ps/security.o \
|
||||||
ps/suspend.o \
|
ps/suspend.o \
|
||||||
ps/thread.o \
|
ps/thread.o \
|
||||||
ps/win32.o \
|
ps/win32.o
|
||||||
ps/w32call.o
|
|
||||||
|
|
||||||
# Executive Subsystem (Ex)
|
# Executive Subsystem (Ex)
|
||||||
OBJECTS_EX = \
|
OBJECTS_EX = \
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
||||||
#define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
#define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
||||||
|
|
||||||
|
#define FN_CONTROL_WORD 0x0
|
||||||
|
#define FN_STATUS_WORD 0x4
|
||||||
|
#define FN_TAG_WORD 0x8
|
||||||
|
#define FN_DATA_SELECTOR 0x18
|
||||||
|
#define FN_CR0_NPX_STATE 0x20C
|
||||||
#define SIZEOF_FX_SAVE_AREA 528
|
#define SIZEOF_FX_SAVE_AREA 528
|
||||||
|
|
||||||
#ifndef __ASM__
|
#ifndef __ASM__
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#define KPCR_BASE 0xFF000000
|
#define KPCR_BASE 0xFF000000
|
||||||
|
|
||||||
#define KPCR_EXCEPTION_LIST 0x0
|
#define KPCR_EXCEPTION_LIST 0x0
|
||||||
|
#define KPCR_INITIAL_STACK 0x4
|
||||||
#define KPCR_SELF 0x1C
|
#define KPCR_SELF 0x1C
|
||||||
#define KPCR_TSS 0x40
|
#define KPCR_TSS 0x40
|
||||||
#define KPCR_CURRENT_THREAD 0x124
|
#define KPCR_CURRENT_THREAD 0x124
|
||||||
|
|
|
@ -66,6 +66,6 @@ VOID KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define MM_STACK_SIZE (3*4096)
|
#define MM_STACK_SIZE (12*4096)
|
||||||
|
|
||||||
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
|
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
|
||||||
|
|
59
reactos/ntoskrnl/ke/i386/usercall.S
Normal file
59
reactos/ntoskrnl/ke/i386/usercall.S
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/ke/i386s/usercall.S
|
||||||
|
* PURPOSE: User-Mode callbacks and return.
|
||||||
|
*
|
||||||
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include <roscfg.h>
|
||||||
|
#include <internal/i386/segment.h>
|
||||||
|
#include <internal/i386/ke.h>
|
||||||
|
#include <internal/i386/fpu.h>
|
||||||
|
#include <internal/ps.h>
|
||||||
|
#include <ntos/tss.h>
|
||||||
|
#include <internal/ntoskrnl.h>
|
||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
/* GLOBALS ****************************************************************/
|
||||||
|
.extern PVOID _SystemDllCallbackDispatcher
|
||||||
|
|
||||||
|
#define CBSTACK_BUFFER_ADDRESS 0x20
|
||||||
|
#define CBSTACK_BUFFER_LENGTH 0x24
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
/*++
|
||||||
|
* KiSwitchToUserMode
|
||||||
|
*
|
||||||
|
* The KiSwitchToUserMode routine sets up a Trap Frame and a Callback stack
|
||||||
|
* for the purpose of switching to user mode. The actual final jump is done
|
||||||
|
* by KiServiceExit which will treat this as a syscall return.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* OutputBuffer - Pointer to a caller-allocated buffer where to receive
|
||||||
|
* the return data from the user-mode function
|
||||||
|
*
|
||||||
|
* OutputLength - Size of the Output Buffer described above.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Jumps into KiServiceExit.
|
||||||
|
*
|
||||||
|
* Remarks:
|
||||||
|
* If there is not enough Kernel Stack space, the routine will increase the
|
||||||
|
* Kernel Stack.
|
||||||
|
*
|
||||||
|
* User mode execution resumes at ntdll!KiUserCallbackDispatcher.
|
||||||
|
*
|
||||||
|
* This call MUST be paired by interrupt 0x2B or NtCallbackReturn.
|
||||||
|
*
|
||||||
|
*--*/
|
||||||
|
.globl _KiSwitchToUserMode@8
|
||||||
|
.func KiSwitchToUserMode@8
|
||||||
|
_KiSwitchToUserMode@8:
|
||||||
|
|
||||||
|
.endfunc
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS kernel
|
|
||||||
* FILE: ntoskrnl/ke/i386/usercall.c
|
|
||||||
* PURPOSE: 2E interrupt handler
|
|
||||||
*
|
|
||||||
* PROGRAMMERS: David Welch (david.welch@seh.ox.ac.uk)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
|
||||||
#define NDEBUG
|
|
||||||
#include <internal/debug.h>
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
STDCALL
|
|
||||||
KeUserModeCallback(
|
|
||||||
IN ULONG FunctionID,
|
|
||||||
IN PVOID InputBuffer,
|
|
||||||
IN ULONG InputLength,
|
|
||||||
OUT PVOID *OutputBuffer,
|
|
||||||
OUT PULONG OutputLength
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -1,37 +1,28 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ps/w32call.c
|
* FILE: ntoskrnl/ke/usercall.c
|
||||||
* PURPOSE: Thread managment
|
* PURPOSE: User-Mode callbacks. Portable part.
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
* Phillip Susi
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* INCLUDES ******************************************************************/
|
||||||
* NOTE:
|
|
||||||
*
|
|
||||||
* All of the routines that manipulate the thread queue synchronize on
|
|
||||||
* a single spinlock
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* void * alloca(size_t size); */
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
void* _alloca(size_t size);
|
|
||||||
#else
|
|
||||||
#error Unknown compiler for alloca intrinsic stack allocation "function"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TYPES *******************************************************************/
|
#if ALEX_CB_REWRITE
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
KiSwitchToUserMode(IN PVOID *OutputBuffer,
|
||||||
|
IN PULONG OutputLength);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
typedef struct _NTW32CALL_SAVED_STATE
|
typedef struct _NTW32CALL_SAVED_STATE
|
||||||
{
|
{
|
||||||
|
@ -55,8 +46,6 @@ typedef struct
|
||||||
KSPIN_LOCK CallbackStackListLock;
|
KSPIN_LOCK CallbackStackListLock;
|
||||||
static LIST_ENTRY CallbackStackListHead;
|
static LIST_ENTRY CallbackStackListHead;
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
PsInitialiseW32Call(VOID)
|
PsInitialiseW32Call(VOID)
|
||||||
{
|
{
|
||||||
|
@ -64,90 +53,6 @@ PsInitialiseW32Call(VOID)
|
||||||
KeInitializeSpinLock(&CallbackStackListLock);
|
KeInitializeSpinLock(&CallbackStackListLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtCallbackReturn (PVOID Result,
|
|
||||||
ULONG ResultLength,
|
|
||||||
NTSTATUS Status)
|
|
||||||
{
|
|
||||||
PULONG OldStack;
|
|
||||||
PETHREAD Thread;
|
|
||||||
PNTSTATUS CallbackStatus;
|
|
||||||
PULONG CallerResultLength;
|
|
||||||
PVOID* CallerResult;
|
|
||||||
PVOID InitialStack;
|
|
||||||
PVOID StackBase;
|
|
||||||
ULONG_PTR StackLimit;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
PNTW32CALL_SAVED_STATE State;
|
|
||||||
PKTRAP_FRAME SavedTrapFrame;
|
|
||||||
PVOID SavedCallbackStack;
|
|
||||||
PVOID SavedExceptionStack;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
Thread = PsGetCurrentThread();
|
|
||||||
if (Thread->Tcb.CallbackStack == NULL)
|
|
||||||
{
|
|
||||||
return(STATUS_NO_CALLBACK_ACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
OldStack = (PULONG)Thread->Tcb.CallbackStack;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the values that NtW32Call left on the inactive stack for us.
|
|
||||||
*/
|
|
||||||
State = (PNTW32CALL_SAVED_STATE)OldStack[0];
|
|
||||||
CallbackStatus = State->CallbackStatus;
|
|
||||||
CallerResultLength = State->CallerResultLength;
|
|
||||||
CallerResult = State->CallerResult;
|
|
||||||
InitialStack = State->SavedInitialStack;
|
|
||||||
StackBase = State->SavedStackBase;
|
|
||||||
StackLimit = State->SavedStackLimit;
|
|
||||||
SavedTrapFrame = State->SavedTrapFrame;
|
|
||||||
SavedCallbackStack = State->SavedCallbackStack;
|
|
||||||
SavedExceptionStack = State->SavedExceptionStack;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the callback status and the callback result to NtW32Call
|
|
||||||
*/
|
|
||||||
*CallbackStatus = Status;
|
|
||||||
if (CallerResult != NULL && CallerResultLength != NULL)
|
|
||||||
{
|
|
||||||
if (Result == NULL)
|
|
||||||
{
|
|
||||||
*CallerResultLength = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*CallerResultLength = min(ResultLength, *CallerResultLength);
|
|
||||||
RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restore the old stack.
|
|
||||||
*/
|
|
||||||
KeRaiseIrql(HIGH_LEVEL, &oldIrql);
|
|
||||||
if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
|
|
||||||
ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
|
|
||||||
{
|
|
||||||
RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
|
|
||||||
(char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
|
|
||||||
sizeof(FX_SAVE_AREA));
|
|
||||||
}
|
|
||||||
Thread->Tcb.InitialStack = InitialStack;
|
|
||||||
Thread->Tcb.StackBase = StackBase;
|
|
||||||
Thread->Tcb.StackLimit = StackLimit;
|
|
||||||
Thread->Tcb.TrapFrame = SavedTrapFrame;
|
|
||||||
Thread->Tcb.CallbackStack = SavedCallbackStack;
|
|
||||||
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
|
|
||||||
KeStackSwitchAndRet((PVOID)(OldStack + 1));
|
|
||||||
|
|
||||||
/* Should never return. */
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID STATIC
|
VOID STATIC
|
||||||
PsFreeCallbackStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
PsFreeCallbackStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
PFN_TYPE Page, SWAPENTRY SwapEntry,
|
PFN_TYPE Page, SWAPENTRY SwapEntry,
|
||||||
|
@ -244,14 +149,19 @@ PsAllocateCallbackStack(ULONG StackSize)
|
||||||
}
|
}
|
||||||
return(KernelStack);
|
return(KernelStack);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
/*
|
||||||
NtW32Call (IN ULONG RoutineIndex,
|
* @implemented
|
||||||
IN PVOID Argument,
|
*/
|
||||||
IN ULONG ArgumentLength,
|
NTSTATUS
|
||||||
OUT PVOID* Result OPTIONAL,
|
STDCALL
|
||||||
OUT PULONG ResultLength OPTIONAL)
|
KeUserModeCallback(IN ULONG RoutineIndex,
|
||||||
{
|
IN PVOID Argument,
|
||||||
|
IN ULONG ArgumentLength,
|
||||||
|
OUT PVOID *Result,
|
||||||
|
OUT PULONG ResultLength)
|
||||||
|
{
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
PVOID NewStack;
|
PVOID NewStack;
|
||||||
ULONG_PTR StackSize;
|
ULONG_PTR StackSize;
|
||||||
|
@ -264,7 +174,7 @@ NtW32Call (IN ULONG RoutineIndex,
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
|
DPRINT("KeUserModeCallback(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
|
||||||
RoutineIndex, Argument, ArgumentLength);
|
RoutineIndex, Argument, ArgumentLength);
|
||||||
|
|
||||||
Thread = PsGetCurrentThread();
|
Thread = PsGetCurrentThread();
|
||||||
|
@ -338,6 +248,6 @@ NtW32Call (IN ULONG RoutineIndex,
|
||||||
InsertTailList(&CallbackStackListHead, &AssignedStack->ListEntry);
|
InsertTailList(&CallbackStackListHead, &AssignedStack->ListEntry);
|
||||||
KeReleaseSpinLock(&CallbackStackListLock, PASSIVE_LEVEL);
|
KeReleaseSpinLock(&CallbackStackListLock, PASSIVE_LEVEL);
|
||||||
return(CallbackStatus);
|
return(CallbackStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
|
@ -18,11 +18,11 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
static PVOID SystemDllEntryPoint = NULL;
|
PVOID SystemDllEntryPoint = NULL;
|
||||||
static PVOID SystemDllApcDispatcher = NULL;
|
PVOID SystemDllApcDispatcher = NULL;
|
||||||
static PVOID SystemDllCallbackDispatcher = NULL;
|
PVOID SystemDllCallbackDispatcher = NULL;
|
||||||
static PVOID SystemDllExceptionDispatcher = NULL;
|
PVOID SystemDllExceptionDispatcher = NULL;
|
||||||
static PVOID SystemDllRaiseExceptionDispatcher = NULL;
|
PVOID SystemDllRaiseExceptionDispatcher = NULL;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
|
#define NDEBUG
|
||||||
/* TYPES *******************************************************************/
|
#include <internal/debug.h>
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
|
@ -28,6 +28,21 @@ extern OBJECT_FIND_ROUTINE ExpWindowStationObjectFind;
|
||||||
extern OBJECT_CREATE_ROUTINE ExpDesktopObjectCreate;
|
extern OBJECT_CREATE_ROUTINE ExpDesktopObjectCreate;
|
||||||
extern OBJECT_DELETE_ROUTINE ExpDesktopObjectDelete;
|
extern OBJECT_DELETE_ROUTINE ExpDesktopObjectDelete;
|
||||||
|
|
||||||
|
#ifndef ALEX_CB_REWRITE
|
||||||
|
typedef struct _NTW32CALL_SAVED_STATE
|
||||||
|
{
|
||||||
|
ULONG_PTR SavedStackLimit;
|
||||||
|
PVOID SavedStackBase;
|
||||||
|
PVOID SavedInitialStack;
|
||||||
|
PVOID CallerResult;
|
||||||
|
PULONG CallerResultLength;
|
||||||
|
PNTSTATUS CallbackStatus;
|
||||||
|
PKTRAP_FRAME SavedTrapFrame;
|
||||||
|
PVOID SavedCallbackStack;
|
||||||
|
PVOID SavedExceptionStack;
|
||||||
|
} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
PW32THREAD STDCALL
|
PW32THREAD STDCALL
|
||||||
|
@ -162,4 +177,182 @@ PsTerminateWin32Thread (PETHREAD Thread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
DumpEspData(ULONG Esp, ULONG ThLimit, ULONG ThStack, ULONG PcrLimit, ULONG PcrStack, ULONG Esp0)
|
||||||
|
{
|
||||||
|
DPRINT1("Current Esp: %p\n Thread Stack Limit: %p\n Thread Stack: %p\n Pcr Limit: %p, Pcr Stack: %p\n Esp0 :%p\n",Esp, ThLimit, ThStack, PcrLimit, PcrStack, Esp0) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
STDCALL
|
||||||
|
PsAllocateCallbackStack(ULONG StackSize)
|
||||||
|
{
|
||||||
|
PVOID KernelStack = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PMEMORY_AREA StackArea;
|
||||||
|
ULONG i, j;
|
||||||
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||||
|
PPFN_TYPE Pages = alloca(sizeof(PFN_TYPE) * (StackSize /PAGE_SIZE));
|
||||||
|
|
||||||
|
DPRINT1("PsAllocateCallbackStack\n");
|
||||||
|
BoundaryAddressMultiple.QuadPart = 0;
|
||||||
|
StackSize = PAGE_ROUND_UP(StackSize);
|
||||||
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
Status = MmCreateMemoryArea(NULL,
|
||||||
|
MmGetKernelAddressSpace(),
|
||||||
|
MEMORY_AREA_KERNEL_STACK,
|
||||||
|
&KernelStack,
|
||||||
|
StackSize,
|
||||||
|
0,
|
||||||
|
&StackArea,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
BoundaryAddressMultiple);
|
||||||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create thread stack\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
for (i = 0; i < (StackSize / PAGE_SIZE); i++)
|
||||||
|
{
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pages[i]);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[j]);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
|
KernelStack,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
Pages,
|
||||||
|
StackSize / PAGE_SIZE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
for (i = 0; i < (StackSize / PAGE_SIZE); i++)
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[i]);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
DPRINT1("PsAllocateCallbackStack %x\n", KernelStack);
|
||||||
|
return(KernelStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
NtW32Call(IN ULONG RoutineIndex,
|
||||||
|
IN PVOID Argument,
|
||||||
|
IN ULONG ArgumentLength,
|
||||||
|
OUT PVOID* Result OPTIONAL,
|
||||||
|
OUT PULONG ResultLength OPTIONAL)
|
||||||
|
{
|
||||||
|
NTSTATUS CallbackStatus;
|
||||||
|
|
||||||
|
DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
|
||||||
|
RoutineIndex, Argument, ArgumentLength);
|
||||||
|
|
||||||
|
/* FIXME: SEH!!! */
|
||||||
|
|
||||||
|
/* Call kernel function */
|
||||||
|
CallbackStatus = KeUserModeCallback(RoutineIndex,
|
||||||
|
Argument,
|
||||||
|
ArgumentLength,
|
||||||
|
Result,
|
||||||
|
ResultLength);
|
||||||
|
|
||||||
|
/* Return the result */
|
||||||
|
return(CallbackStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ALEX_CB_REWRITE
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtCallbackReturn (PVOID Result,
|
||||||
|
ULONG ResultLength,
|
||||||
|
NTSTATUS Status)
|
||||||
|
{
|
||||||
|
PULONG OldStack;
|
||||||
|
PETHREAD Thread;
|
||||||
|
PNTSTATUS CallbackStatus;
|
||||||
|
PULONG CallerResultLength;
|
||||||
|
PVOID* CallerResult;
|
||||||
|
PVOID InitialStack;
|
||||||
|
PVOID StackBase;
|
||||||
|
ULONG_PTR StackLimit;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
PNTW32CALL_SAVED_STATE State;
|
||||||
|
PKTRAP_FRAME SavedTrapFrame;
|
||||||
|
PVOID SavedCallbackStack;
|
||||||
|
PVOID SavedExceptionStack;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
Thread = PsGetCurrentThread();
|
||||||
|
if (Thread->Tcb.CallbackStack == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_NO_CALLBACK_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
OldStack = (PULONG)Thread->Tcb.CallbackStack;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the values that NtW32Call left on the inactive stack for us.
|
||||||
|
*/
|
||||||
|
State = (PNTW32CALL_SAVED_STATE)OldStack[0];
|
||||||
|
CallbackStatus = State->CallbackStatus;
|
||||||
|
CallerResultLength = State->CallerResultLength;
|
||||||
|
CallerResult = State->CallerResult;
|
||||||
|
InitialStack = State->SavedInitialStack;
|
||||||
|
StackBase = State->SavedStackBase;
|
||||||
|
StackLimit = State->SavedStackLimit;
|
||||||
|
SavedTrapFrame = State->SavedTrapFrame;
|
||||||
|
SavedCallbackStack = State->SavedCallbackStack;
|
||||||
|
SavedExceptionStack = State->SavedExceptionStack;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the callback status and the callback result to NtW32Call
|
||||||
|
*/
|
||||||
|
*CallbackStatus = Status;
|
||||||
|
if (CallerResult != NULL && CallerResultLength != NULL)
|
||||||
|
{
|
||||||
|
if (Result == NULL)
|
||||||
|
{
|
||||||
|
*CallerResultLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*CallerResultLength = min(ResultLength, *CallerResultLength);
|
||||||
|
RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the old stack.
|
||||||
|
*/
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &oldIrql);
|
||||||
|
if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
|
||||||
|
ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
|
||||||
|
{
|
||||||
|
RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
|
||||||
|
(char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
|
||||||
|
sizeof(FX_SAVE_AREA));
|
||||||
|
}
|
||||||
|
Thread->Tcb.InitialStack = InitialStack;
|
||||||
|
Thread->Tcb.StackBase = StackBase;
|
||||||
|
Thread->Tcb.StackLimit = StackLimit;
|
||||||
|
Thread->Tcb.TrapFrame = SavedTrapFrame;
|
||||||
|
Thread->Tcb.CallbackStack = SavedCallbackStack;
|
||||||
|
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
|
||||||
|
KeStackSwitchAndRet((PVOID)(OldStack + 1));
|
||||||
|
|
||||||
|
/* Should never return. */
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue