- Remove KiServiceCheck and implement PsConvertToGuiThread in its place. Has support for detecting and returning errors in case of invalid cases, currently disabled code for doing the required 4kb->12kb stack conversion, and handling certain failures.

svn path=/trunk/; revision=20779
This commit is contained in:
Alex Ionescu 2006-01-11 05:42:32 +00:00
parent c193938e1b
commit 7816643eb5
3 changed files with 94 additions and 96 deletions

View file

@ -614,7 +614,7 @@ KiBBTUnexpectedRange:
/* Set up Win32K Table */
push edx
push ebx
call _KiServiceCheck@0
call _PsConvertToGuiThread@0
/* FIXME: Handle failure */
pop eax

View file

@ -1466,21 +1466,6 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
return OldState;
}
VOID
NTAPI
KiServiceCheck(VOID)
{
PKTHREAD Thread = KeGetCurrentThread();
/* Check if we need to inialize Win32 for this Thread */
if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
/* We do. Initialize it and save the new table */
Thread->ServiceTable = KeServiceDescriptorTableShadow;
PsInitWin32Thread((PETHREAD)Thread);
}
}
/*
*
* NOT EXPORTED

View file

@ -41,6 +41,13 @@ typedef struct _NTW32CALL_SAVED_STATE
} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
#endif
PVOID
STDCALL
KeSwitchKernelStack(
IN PVOID StackBase,
IN PVOID StackLimit
);
/* FUNCTIONS ***************************************************************/
/*
@ -62,33 +69,105 @@ PsEstablishWin32Callouts(PW32_CALLOUT_DATA CalloutData)
NTSTATUS
NTAPI
PsInitWin32Thread (PETHREAD Thread)
PsConvertToGuiThread(VOID)
{
PEPROCESS Process;
NTSTATUS Status = STATUS_SUCCESS;
//PVOID NewStack, OldStack;
PETHREAD Thread = PsGetCurrentThread();
PEPROCESS Process = PsGetCurrentProcess();
NTSTATUS Status;
PAGED_CODE();
Process = Thread->ThreadsProcess;
/* Validate the previous mode */
if (KeGetPreviousMode() == KernelMode)
{
DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
return STATUS_INVALID_PARAMETER;
}
if (Process->Win32Process == NULL)
/* Make sure win32k is here */
if (!PspWin32ProcessCallback)
{
if (PspWin32ProcessCallback != NULL)
DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
return STATUS_ACCESS_DENIED;
}
/* Make sure it's not already win32 */
if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
{
DPRINT1("Danger: Thread is already a win32 thread. Limit bypassed?\n");
return STATUS_ALREADY_WIN32;
}
/* Check if we don't already have a kernel-mode stack */
#if 0
if (!Thread->Tcb.LargeStack)
{
/* We don't create one */
DPRINT1("Creating large stack\n");
NewStack = MmCreateKernelStack(TRUE);
if (!NewStack)
{
/* Panic in user-mode */
NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
return STATUS_NO_MEMORY;
}
/* We're about to switch stacks. Enter a critical region */
KeEnterCriticalRegion();
/* Switch stacks */
DPRINT1("Switching stacks. NS IT, SL, SB, KS %p %p %p %p %p\n",
NewStack,
Thread->Tcb.InitialStack,
Thread->Tcb.StackLimit,
Thread->Tcb.StackBase,
Thread->Tcb.KernelStack);
OldStack = KeSwitchKernelStack((PVOID)((ULONG_PTR)NewStack + 0x3000),
NewStack);
/* Leave the critical region */
KeLeaveCriticalRegion();
DPRINT1("We made it!\n");
/* Delete the old stack */
//MmDeleteKernelStack(OldStack, FALSE);
DPRINT1("Old stack deleted. IT, SL, SB, KS %p %p %p %p\n",
Thread->Tcb.InitialStack,
Thread->Tcb.StackLimit,
Thread->Tcb.StackBase,
Thread->Tcb.KernelStack);
}
#endif
/* This check is bizare. Check out win32k later */
if (!Process->Win32Process)
{
/* Now tell win32k about us */
Status = PspWin32ProcessCallback(Process, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Danger: Win32k wasn't happy about us!\n");
return Status;
}
}
if (Thread->Tcb.Win32Thread == NULL)
{
if (PspWin32ThreadCallback != NULL)
{
/* Set the new service table */
Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
ASSERT(Thread->Tcb.Win32Thread == 0);
/* Tell Win32k about our thread */
Status = PspWin32ThreadCallback(Thread, TRUE);
}
if (!NT_SUCCESS(Status))
{
/* Revert our table */
DPRINT1("Danger: Win32k wasn't happy about us!\n");
Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
}
/* Return status */
return Status;
}
VOID
NTAPI
PsTerminateWin32Process (PEPROCESS Process)
@ -122,72 +201,6 @@ 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(MmGetKernelAddressSpace(),
MEMORY_AREA_KERNEL_STACK,
&KernelStack,
StackSize,
PAGE_READWRITE,
&StackArea,
FALSE,
0,
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,