#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
+#include <win32k/callout.h>
/* GLOBALS ******************************************************************/
-static PW32_PROCESS_CALLBACK PspWin32ProcessCallback = NULL;
-static PW32_THREAD_CALLBACK PspWin32ThreadCallback = NULL;
-static ULONG PspWin32ProcessSize = 0;
-static ULONG PspWin32ThreadSize = 0;
+static PKWIN32_PROCESS_CALLOUT PspWin32ProcessCallback = NULL;
+static PKWIN32_THREAD_CALLOUT PspWin32ThreadCallback = NULL;
-extern OBJECT_CREATE_ROUTINE ExpWindowStationObjectCreate;
-extern OBJECT_PARSE_ROUTINE ExpWindowStationObjectParse;
-extern OBJECT_DELETE_ROUTINE ExpWindowStationObjectDelete;
-extern OBJECT_FIND_ROUTINE ExpWindowStationObjectFind;
-extern OBJECT_CREATE_ROUTINE ExpDesktopObjectCreate;
-extern OBJECT_DELETE_ROUTINE ExpDesktopObjectDelete;
+extern OB_OPEN_METHOD ExpWindowStationObjectOpen;
+extern OB_ROS_PARSE_METHOD ExpWindowStationObjectParse;
+extern OB_DELETE_METHOD ExpWindowStationObjectDelete;
+extern OB_ROS_FIND_METHOD ExpWindowStationObjectFind;
+extern OB_ROS_CREATE_METHOD ExpDesktopObjectCreate;
+extern OB_DELETE_METHOD ExpDesktopObjectDelete;
#ifndef ALEX_CB_REWRITE
typedef struct _NTW32CALL_SAVED_STATE
} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
#endif
-/* FUNCTIONS ***************************************************************/
-
-PW32THREAD STDCALL
-PsGetWin32Thread(VOID)
-{
- return(PsGetCurrentThread()->Tcb.Win32Thread);
-}
-
-PW32PROCESS STDCALL
-PsGetWin32Process(VOID)
-{
- return(PsGetCurrentProcess()->Win32Process);
-}
-
-NTSTATUS STDCALL
-PsCreateWin32Process(PEPROCESS Process)
-{
- if (Process->Win32Process != NULL)
- return(STATUS_SUCCESS);
-
- Process->Win32Process = ExAllocatePool(NonPagedPool,
- PspWin32ProcessSize);
- if (Process->Win32Process == NULL)
- return(STATUS_NO_MEMORY);
-
- RtlZeroMemory(Process->Win32Process,
- PspWin32ProcessSize);
-
- return(STATUS_SUCCESS);
-}
+PVOID
+STDCALL
+KeSwitchKernelStack(
+ IN PVOID StackBase,
+ IN PVOID StackLimit
+);
+/* FUNCTIONS ***************************************************************/
/*
* @implemented
*/
-VOID STDCALL
-PsEstablishWin32Callouts (PW32_PROCESS_CALLBACK W32ProcessCallback,
- PW32_THREAD_CALLBACK W32ThreadCallback,
- PW32_OBJECT_CALLBACK W32ObjectCallback,
- PVOID Param4,
- ULONG W32ThreadSize,
- ULONG W32ProcessSize)
+VOID
+STDCALL
+PsEstablishWin32Callouts(PWIN32_CALLOUTS_FPNS calloutData)
{
- PspWin32ProcessCallback = W32ProcessCallback;
- PspWin32ThreadCallback = W32ThreadCallback;
-
- PspWin32ProcessSize = W32ProcessSize;
- PspWin32ThreadSize = W32ThreadSize;
-
- ExpWindowStationObjectCreate = W32ObjectCallback->WinStaCreate;
- ExpWindowStationObjectParse = W32ObjectCallback->WinStaParse;
- ExpWindowStationObjectDelete = W32ObjectCallback->WinStaDelete;
- ExpWindowStationObjectFind = W32ObjectCallback->WinStaFind;
- ExpDesktopObjectCreate = W32ObjectCallback->DesktopCreate;
- ExpDesktopObjectDelete = W32ObjectCallback->DesktopDelete;
+ PW32_CALLOUT_DATA CalloutData = (PW32_CALLOUT_DATA)calloutData;
+ PspWin32ProcessCallback = CalloutData->W32ProcessCallout;
+ PspWin32ThreadCallback = CalloutData->W32ThreadCallout;
+ ExpWindowStationObjectOpen = CalloutData->WinStaOpen;
+ ExpWindowStationObjectParse = CalloutData->WinStaParse;
+ ExpWindowStationObjectDelete = CalloutData->WinStaDelete;
+ ExpWindowStationObjectFind = CalloutData->WinStaFind;
+ ExpDesktopObjectCreate = CalloutData->DesktopCreate;
+ ExpDesktopObjectDelete = CalloutData->DesktopDelete;
}
NTSTATUS
-PsInitWin32Thread (PETHREAD Thread)
+NTAPI
+PsConvertToGuiThread(VOID)
{
- PEPROCESS Process;
-
- Process = Thread->ThreadsProcess;
+ ULONG_PTR NewStack;
+ PVOID OldStack;
+ PETHREAD Thread = PsGetCurrentThread();
+ PEPROCESS Process = PsGetCurrentProcess();
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* 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)
{
- /* FIXME - lock the process */
- Process->Win32Process = ExAllocatePool (NonPagedPool,
- PspWin32ProcessSize);
+ DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
+ return STATUS_ACCESS_DENIED;
+ }
- if (Process->Win32Process == NULL)
- return STATUS_NO_MEMORY;
+ /* 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;
+ }
- RtlZeroMemory (Process->Win32Process,
- PspWin32ProcessSize);
- /* FIXME - unlock the process */
+ /* Check if we don't already have a kernel-mode stack */
+ if (!Thread->Tcb.LargeStack)
+ {
+ /* We don't create one */
+ NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE) + KERNEL_LARGE_STACK_SIZE;
+ 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 */
+ OldStack = KeSwitchKernelStack((PVOID)NewStack,
+ (PVOID)(NewStack - KERNEL_STACK_SIZE));
+
+ /* Leave the critical region */
+ KeLeaveCriticalRegion();
+
+ /* Delete the old stack */
+ MmDeleteKernelStack(OldStack, FALSE);
+ }
- if (PspWin32ProcessCallback != NULL)
- {
- PspWin32ProcessCallback (Process, TRUE);
- }
+ /* 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)
+ /* Set the new service table */
+ Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
+ ASSERT(Thread->Tcb.Win32Thread == 0);
+
+ /* Tell Win32k about our thread */
+ Status = PspWin32ThreadCallback(Thread, PsW32ThreadCalloutInitialize);
+ if (!NT_SUCCESS(Status))
{
- Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool,
- PspWin32ThreadSize);
- if (Thread->Tcb.Win32Thread == NULL)
- return STATUS_NO_MEMORY;
-
- RtlZeroMemory (Thread->Tcb.Win32Thread,
- PspWin32ThreadSize);
-
- if (PspWin32ThreadCallback != NULL)
- {
- PspWin32ThreadCallback (Thread, TRUE);
- }
+ /* Revert our table */
+ DPRINT1("Danger: Win32k wasn't happy about us!\n");
+ Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
}
- return(STATUS_SUCCESS);
+ /* Return status */
+ return Status;
}
-
VOID
+NTAPI
PsTerminateWin32Process (PEPROCESS Process)
{
if (Process->Win32Process == NULL)
VOID
+NTAPI
PsTerminateWin32Thread (PETHREAD Thread)
{
if (Thread->Tcb.Win32Thread != NULL)
{
if (PspWin32ThreadCallback != NULL)
{
- PspWin32ThreadCallback (Thread, FALSE);
+ PspWin32ThreadCallback (Thread, PsW32ThreadCalloutExit);
}
/* don't delete the W32THREAD structure at this point, wait until the
}
}
-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
+NTSTATUS
STDCALL
NtW32Call(IN ULONG RoutineIndex,
IN PVOID Argument,
IN ULONG ArgumentLength,
- OUT PVOID* Result OPTIONAL,
- OUT PULONG ResultLength OPTIONAL)
+ OUT PVOID* Result,
+ OUT PULONG ResultLength)
{
- NTSTATUS CallbackStatus;
-
- DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
+ PVOID RetResult;
+ ULONG RetResultLength;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("NtW32Call(RoutineIndex %d, Argument %p, 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();
+ /* must not be called as KernelMode! */
+ ASSERT(KeGetPreviousMode() != KernelMode);
- Thread = PsGetCurrentThread();
- if (Thread->Tcb.CallbackStack == NULL)
+ _SEH_TRY
{
- return(STATUS_NO_CALLBACK_ACTIVE);
+ ProbeForWritePointer(Result);
+ ProbeForWriteUlong(ResultLength);
}
-
- 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)
+ _SEH_HANDLE
{
- if (Result == NULL)
- {
- *CallerResultLength = 0;
- }
- else
- {
- *CallerResultLength = min(ResultLength, *CallerResultLength);
- RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
- }
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
- /*
- * Restore the old stack.
- */
- KeRaiseIrql(HIGH_LEVEL, &oldIrql);
- if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
- ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
+ if (NT_SUCCESS(Status))
{
- RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
- (char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
- sizeof(FX_SAVE_AREA));
+ /* Call kernel function */
+ Status = KeUserModeCallback(RoutineIndex,
+ Argument,
+ ArgumentLength,
+ &RetResult,
+ &RetResultLength);
+
+ if (NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *Result = RetResult;
+ *ResultLength = RetResultLength;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
}
- 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
+
+ /* Return the result */
+ return Status;
}
+
/* EOF */