From 793bbe04550b8231cdd93c2e5910cbf46dba3f3a Mon Sep 17 00:00:00 2001 From: David Welch Date: Tue, 15 Jan 2002 02:51:32 +0000 Subject: [PATCH] Implemented NtW32Call and NtCallbackReturn Updated some .cvsignore files svn path=/trunk/; revision=2515 --- reactos/apps/utils/net/ping/.cvsignore | 1 + .../apps/utils/net/roshttpd/common/.cvsignore | 1 + reactos/drivers/fs/vfat/.cvsignore | 1 + reactos/lib/oleaut32/.cvsignore | 1 + reactos/lib/shell32/.cvsignore | 1 + reactos/ntoskrnl/Makefile.i386 | 3 +- reactos/ntoskrnl/include/internal/ke.h | 5 + reactos/ntoskrnl/include/internal/ldr.h | 2 + reactos/ntoskrnl/include/internal/ps.h | 3 +- reactos/ntoskrnl/ke/i386/stkswitch.S | 81 ++++++++++ reactos/ntoskrnl/ke/i386/syscall.S | 11 +- reactos/ntoskrnl/ke/i386/tskswitch.S | 2 +- reactos/ntoskrnl/ke/main.c | 3 +- reactos/ntoskrnl/ps/thread.c | 145 +++++++++++++++++- reactos/tools/.cvsignore | 9 +- 15 files changed, 255 insertions(+), 14 deletions(-) create mode 100644 reactos/apps/utils/net/ping/.cvsignore create mode 100644 reactos/apps/utils/net/roshttpd/common/.cvsignore create mode 100644 reactos/ntoskrnl/ke/i386/stkswitch.S diff --git a/reactos/apps/utils/net/ping/.cvsignore b/reactos/apps/utils/net/ping/.cvsignore new file mode 100644 index 00000000000..0707518b9b0 --- /dev/null +++ b/reactos/apps/utils/net/ping/.cvsignore @@ -0,0 +1 @@ +ping.coff \ No newline at end of file diff --git a/reactos/apps/utils/net/roshttpd/common/.cvsignore b/reactos/apps/utils/net/roshttpd/common/.cvsignore new file mode 100644 index 00000000000..0267f61cb66 --- /dev/null +++ b/reactos/apps/utils/net/roshttpd/common/.cvsignore @@ -0,0 +1 @@ +roshttpd.coff \ No newline at end of file diff --git a/reactos/drivers/fs/vfat/.cvsignore b/reactos/drivers/fs/vfat/.cvsignore index da6f9849e8b..4f613ad377a 100644 --- a/reactos/drivers/fs/vfat/.cvsignore +++ b/reactos/drivers/fs/vfat/.cvsignore @@ -3,3 +3,4 @@ junk.tmp temp.exp vfatfs.coff vfatfs.sys.unstripped +*.d \ No newline at end of file diff --git a/reactos/lib/oleaut32/.cvsignore b/reactos/lib/oleaut32/.cvsignore index 05f7a103468..ec7bd126c98 100644 --- a/reactos/lib/oleaut32/.cvsignore +++ b/reactos/lib/oleaut32/.cvsignore @@ -1,2 +1,3 @@ oleaut32.coff oleaut32.dll +oleaut32.nostrip.dll \ No newline at end of file diff --git a/reactos/lib/shell32/.cvsignore b/reactos/lib/shell32/.cvsignore index 425ddafeb9e..65d5e6dfbb8 100644 --- a/reactos/lib/shell32/.cvsignore +++ b/reactos/lib/shell32/.cvsignore @@ -1,2 +1,3 @@ shell32.coff shell32.dll +shell32.nostrip.dll \ No newline at end of file diff --git a/reactos/ntoskrnl/Makefile.i386 b/reactos/ntoskrnl/Makefile.i386 index 7def5974eaa..cc65ecebfb7 100644 --- a/reactos/ntoskrnl/Makefile.i386 +++ b/reactos/ntoskrnl/Makefile.i386 @@ -31,7 +31,8 @@ OBJECTS_KE_I386 := \ ke/i386/kernel.o \ ke/i386/fpu.o \ ke/i386/tss.o \ - ke/i386/usertrap.o + ke/i386/usertrap.o \ + ke/i386/stkswitch.o OBJECTS_MM_I386 := \ mm/i386/memsafe.o \ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index e1440571eea..19604a2d104 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -207,6 +207,11 @@ VOID Ki386InitializeLdt(VOID); ULONG KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2); +VOID STDCALL +KePushAndStackSwitchAndSysRet(ULONG A, ULONG B, ULONG C, ULONG D, ULONG E, + ULONG F, PVOID NewStack); +VOID STDCALL +KeStackSwitchAndRet(PVOID NewStack); #endif /* not __ASM__ */ diff --git a/reactos/ntoskrnl/include/internal/ldr.h b/reactos/ntoskrnl/include/internal/ldr.h index 089cce2f877..8dec2b69318 100644 --- a/reactos/ntoskrnl/include/internal/ldr.h +++ b/reactos/ntoskrnl/include/internal/ldr.h @@ -48,6 +48,8 @@ PVOID LdrpGetSystemDllApcDispatcher(VOID); PVOID LdrpGetSystemDllExceptionDispatcher(VOID); +PVOID +LdrpGetSystemDllCallbackDispatcher(VOID); NTSTATUS LdrpMapImage ( HANDLE ProcessHandle, diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 63aea96d79a..c8fa367a35d 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: ps.h,v 1.27 2001/11/24 14:08:54 jfilby Exp $ +/* $Id: ps.h,v 1.28 2002/01/15 02:51:32 dwelch Exp $ * * FILE: ntoskrnl/ke/kthread.c * PURPOSE: Process manager definitions @@ -36,6 +36,7 @@ #define KTHREAD_KERNEL_STACK 0x28 #define KTHREAD_PREVIOUS_MODE 0x137 #define KTHREAD_TRAP_FRAME 0x128 +#define KTHREAD_CALLBACK_STACK 0x120 #define ETHREAD_THREADS_PROCESS 0x258 diff --git a/reactos/ntoskrnl/ke/i386/stkswitch.S b/reactos/ntoskrnl/ke/i386/stkswitch.S new file mode 100644 index 00000000000..d87aafd7a23 --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/stkswitch.S @@ -0,0 +1,81 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/ke/i386/tskswitch.S + * PURPOSE: Microkernel thread support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 09/10/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS ****************************************************************/ + +.globl _KeStackSwitchAndRet@4 +_KeStackSwitchAndRet@4: + pushl %ebp + movl %esp, %ebp + + cli + + movl 8(%ebp), %esp + + sti + + popl %edi + popl %esi + popl %ebx + + popl %ebp + ret $28 + +.globl _KePushAndStackSwitchAndSysRet@28 +_KePushAndStackSwitchAndSysRet@28: + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %esi + pushl %edi + + cli + + pushl 8(%ebp) + pushl 12(%ebp) + pushl 16(%ebp) + pushl 20(%ebp) + pushl 24(%ebp) + pushl 28(%ebp) + + movl %ebx, %fs:KPCR_CURRENT_THREAD + movl %esp, KTHREAD_CALLBACK_STACK(%ebx) + movl 32(%ebp), %esp + + sti + + push $0 + call _KeLowerIrql@4 + + jmp KeReturnFromSystemCall + \ No newline at end of file diff --git a/reactos/ntoskrnl/ke/i386/syscall.S b/reactos/ntoskrnl/ke/i386/syscall.S index 6b3ff86a031..3f4b95383a7 100644 --- a/reactos/ntoskrnl/ke/i386/syscall.S +++ b/reactos/ntoskrnl/ke/i386/syscall.S @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: syscall.S,v 1.3 2001/09/24 00:51:17 chorns Exp $ +/* $Id: syscall.S,v 1.4 2002/01/15 02:51:32 dwelch Exp $ * * FILE: ntoskrnl/hal/x86/syscall.s * PURPOSE: 2E trap handler @@ -33,6 +33,7 @@ /* * */ +.globl KeReturnFromSystemCall .globl _interrupt_handler2e _interrupt_handler2e: @@ -124,7 +125,7 @@ L3: cmpl %es:_KeServiceDescriptorTable + 8, %eax jbe new_serviceInRange movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - jmp new_done + jmp KeReturnFromSystemCall new_serviceInRange: @@ -163,7 +164,7 @@ new_serviceInRange: call _KiAfterSystemCallHook addl $8,%esp - jmp new_done + jmp KeReturnFromSystemCall new_useShadowTable: @@ -173,7 +174,7 @@ new_useShadowTable: cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax jbe new_shadowServiceInRange movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - jmp new_done + jmp KeReturnFromSystemCall new_shadowServiceInRange: @@ -212,7 +213,7 @@ new_shadowServiceInRange: call _KiAfterSystemCallHook addl $8,%esp -new_done: +KeReturnFromSystemCall: /* Restore the user context */ /* Get a pointer to the current thread */ diff --git a/reactos/ntoskrnl/ke/i386/tskswitch.S b/reactos/ntoskrnl/ke/i386/tskswitch.S index 3a8eef725e8..a8fcabb52fd 100644 --- a/reactos/ntoskrnl/ke/i386/tskswitch.S +++ b/reactos/ntoskrnl/ke/i386/tskswitch.S @@ -80,7 +80,7 @@ _Ki386ContextSwitch: /* * Set the current thread information in the PCR. */ - movl %ebx, %fs:KPCR_CURRENT_THREAD + movl %ebx, %fs:KPCR_CURRENT_THREAD /* * FIXME: Save debugging state. diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 504c5b3aad8..169e7c94bec 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.110 2001/12/27 23:56:42 dwelch Exp $ +/* $Id: main.c,v 1.111 2002/01/15 02:51:32 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -922,6 +922,7 @@ ExpInitializeExecutive(VOID) assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK); assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE); assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME); + assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK); assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS); assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE); diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 08a6f9ba62f..9a8bf11b144 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.86 2002/01/15 01:42:57 phreak Exp $ +/* $Id: thread.c,v 1.87 2002/01/15 02:51:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -26,6 +26,8 @@ #include #include #include +#include +#include #define NDEBUG #include @@ -498,9 +500,92 @@ NtCallbackReturn (PVOID Result, ULONG ResultLength, NTSTATUS Status) { - UNIMPLEMENTED; + PULONG OldStack; + PETHREAD Thread; + PNTSTATUS CallbackStatus; + PULONG CallerResultLength; + PVOID* CallerResult; + PVOID InitialStack; + PVOID StackBase; + ULONG StackLimit; + KIRQL oldIrql; + + Thread = PsGetCurrentThread(); + OldStack = (PULONG)Thread->Tcb.CallbackStack; + Thread->Tcb.CallbackStack = NULL; + + CallbackStatus = (PNTSTATUS)OldStack[0]; + CallerResultLength = (PULONG)OldStack[1]; + CallerResult = (PVOID*)OldStack[2]; + InitialStack = (PVOID)OldStack[3]; + StackBase = (PVOID)OldStack[4]; + StackLimit = OldStack[5]; + + *CallbackStatus = Status; + if (CallerResult != NULL && CallerResultLength != NULL) + { + if (Result == NULL) + { + *CallerResultLength = 0; + } + else + { + *CallerResultLength = min(ResultLength, *CallerResultLength); + memcpy(*CallerResult, Result, *CallerResultLength); + } + } + + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + Thread->Tcb.InitialStack = InitialStack; + Thread->Tcb.StackBase = StackBase; + Thread->Tcb.StackLimit = StackLimit; + KeStackSwitchAndRet((PVOID)(OldStack + 6)); + + /* Should never return. */ + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); } +PVOID STATIC +PsAllocateCallbackStack(ULONG StackSize) +{ + PVOID KernelStack; + NTSTATUS Status; + PMEMORY_AREA StackArea; + ULONG i; + + StackSize = PAGE_ROUND_UP(StackSize); + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_KERNEL_STACK, + &KernelStack, + StackSize, + 0, + &StackArea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create thread stack\n"); + return(NULL); + } + for (i = 0; i < (StackSize / PAGESIZE); i++) + { + PVOID Page; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + Status = MmCreateVirtualMapping(NULL, + KernelStack + (i * PAGESIZE), + PAGE_EXECUTE_READWRITE, + (ULONG)Page, + TRUE); + } + return(KernelStack); +} NTSTATUS STDCALL NtW32Call (IN ULONG RoutineIndex, @@ -509,8 +594,60 @@ NtW32Call (IN ULONG RoutineIndex, OUT PVOID* Result OPTIONAL, OUT PULONG ResultLength OPTIONAL) { - UNIMPLEMENTED; -} + PETHREAD Thread; + PVOID NewStack; + ULONG StackSize; + PKTRAP_FRAME NewFrame; + PULONG UserEsp; + KIRQL oldIrql; + ULONG SavedStackLimit; + PVOID SavedStackBase; + PVOID SavedInitialStack; + NTSTATUS CallbackStatus; + + Thread = PsGetCurrentThread(); + if (Thread->Tcb.CallbackStack != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + /* Set up the new kernel and user environment. */ + StackSize = (ULONG)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit); + NewStack = PsAllocateCallbackStack(StackSize); + memcpy(NewStack + StackSize - sizeof(KTRAP_FRAME), Thread->Tcb.TrapFrame, + sizeof(KTRAP_FRAME)); + NewFrame = (PKTRAP_FRAME)(NewStack + StackSize - sizeof(KTRAP_FRAME)); + NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG))); + NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher(); + UserEsp = (PULONG)NewFrame->Esp; + UserEsp[0] = 0; /* Return address. */ + UserEsp[1] = RoutineIndex; + UserEsp[2] = (ULONG)&UserEsp[4]; + UserEsp[3] = ArgumentLength; + memcpy((PVOID)&UserEsp[4], Argument, ArgumentLength); + + /* Switch to the new environment and return to user-mode. */ + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + SavedStackLimit = Thread->Tcb.StackLimit; + SavedStackBase = Thread->Tcb.StackBase; + SavedInitialStack = Thread->Tcb.InitialStack; + Thread->Tcb.InitialStack = Thread->Tcb.StackBase = NewStack + StackSize; + Thread->Tcb.StackLimit = (ULONG)NewStack; + Thread->Tcb.KernelStack = NewStack + StackSize - sizeof(KTRAP_FRAME); + KePushAndStackSwitchAndSysRet(SavedStackLimit, + (ULONG)SavedStackBase, + (ULONG)SavedInitialStack, (ULONG)Result, + (ULONG)ResultLength, (ULONG)&CallbackStatus, + Thread->Tcb.KernelStack); + + /* + * The callback return will have already restored most of the state we + * modified. + */ + KeLowerIrql(PASSIVE_LEVEL); + ExFreePool(NewStack); + return(CallbackStatus); +} NTSTATUS STDCALL NtContinue(IN PCONTEXT Context, diff --git a/reactos/tools/.cvsignore b/reactos/tools/.cvsignore index adb36c82196..e4749b8a36c 100644 --- a/reactos/tools/.cvsignore +++ b/reactos/tools/.cvsignore @@ -1 +1,8 @@ -*.exe \ No newline at end of file +*.exe +buildno +depends +rcopy +rmkdir +rrmdir +mkconfig +rdel \ No newline at end of file