1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ps/win32.c 5 * PURPOSE: Process Manager: Win32K Initialization and Support 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ****************************************************************/ 10 11 #include <ntoskrnl.h> 12 #include <winerror.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS ******************************************************************/ 17 18 PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout = NULL; 19 PKWIN32_THREAD_CALLOUT PspW32ThreadCallout = NULL; 20 PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch = NULL; 21 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectParse; 22 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectDelete; 23 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectOkToClose; 24 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOkToClose; 25 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectDelete; 26 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOpen; 27 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectClose; 28 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout; 29 30 /* PRIVATE FUNCTIONS *********************************************************/ 31 32 NTSTATUS 33 NTAPI PsConvertToGuiThread(VOID)34PsConvertToGuiThread(VOID) 35 { 36 ULONG_PTR NewStack; 37 PVOID OldStack; 38 PETHREAD Thread = PsGetCurrentThread(); 39 PEPROCESS Process = PsGetCurrentProcess(); 40 NTSTATUS Status; 41 PAGED_CODE(); 42 43 /* Validate the previous mode */ 44 if (KeGetPreviousMode() == KernelMode) return STATUS_INVALID_PARAMETER; 45 46 /* If no win32k, crashes later */ 47 ASSERT(PspW32ProcessCallout != NULL); 48 49 /* Make sure win32k is here */ 50 if (!PspW32ProcessCallout) return STATUS_ACCESS_DENIED; 51 52 /* Make sure it's not already win32 */ 53 if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable) 54 { 55 /* We're already a win32 thread */ 56 return STATUS_ALREADY_WIN32; 57 } 58 59 /* Check if we don't already have a kernel-mode stack */ 60 if (!Thread->Tcb.LargeStack) 61 { 62 /* We don't create one */ 63 NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE, 0); 64 if (!NewStack) 65 { 66 /* Panic in user-mode */ 67 NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY; 68 return STATUS_NO_MEMORY; 69 } 70 71 /* We're about to switch stacks. Enter a guarded region */ 72 KeEnterGuardedRegion(); 73 74 /* Switch stacks */ 75 OldStack = KeSwitchKernelStack((PVOID)NewStack, 76 (PVOID)(NewStack - KERNEL_STACK_SIZE)); 77 78 /* Leave the guarded region */ 79 KeLeaveGuardedRegion(); 80 81 /* Delete the old stack */ 82 MmDeleteKernelStack(OldStack, FALSE); 83 } 84 85 /* Always do the process callout! */ 86 Status = PspW32ProcessCallout(Process, TRUE); 87 if (!NT_SUCCESS(Status)) return Status; 88 89 /* Set the new service table */ 90 Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; 91 ASSERT(Thread->Tcb.Win32Thread == 0); 92 93 /* Tell Win32k about our thread */ 94 Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize); 95 if (!NT_SUCCESS(Status)) 96 { 97 /* Revert our table */ 98 Thread->Tcb.ServiceTable = KeServiceDescriptorTable; 99 } 100 101 /* Return status */ 102 return Status; 103 } 104 105 /* PUBLIC FUNCTIONS **********************************************************/ 106 107 /* 108 * @implemented 109 */ 110 VOID 111 NTAPI PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData)112PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData) 113 { 114 /* Setup the callback pointers */ 115 PspW32ProcessCallout = CalloutData->ProcessCallout; 116 PspW32ThreadCallout = CalloutData->ThreadCallout; 117 ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure; 118 ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure; 119 ExpWindowStationObjectOkToClose = CalloutData->WindowStationOkToCloseProcedure; 120 ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure; 121 ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure; 122 ExpDesktopObjectOpen = CalloutData->DesktopOpenProcedure; 123 ExpDesktopObjectClose = CalloutData->DesktopCloseProcedure; 124 PopEventCallout = CalloutData->PowerEventCallout; 125 KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine; 126 } 127 128 /* EOF */ 129