Correct implementation of user-mode APCs
authorDavid Welch <welch@cwcom.net>
Wed, 11 Oct 2000 20:50:35 +0000 (20:50 +0000)
committerDavid Welch <welch@cwcom.net>
Wed, 11 Oct 2000 20:50:35 +0000 (20:50 +0000)
svn path=/trunk/; revision=1401

29 files changed:
reactos/.gdbinit
reactos/apps/tests/apc/apc.c
reactos/apps/tests/apc/makefile
reactos/include/ddk/ketypes.h
reactos/include/ntos/types.h
reactos/lib/kernel32/file/rw.c
reactos/lib/kernel32/thread/thread.c
reactos/lib/ntdll/def/ntdll.def
reactos/lib/ntdll/def/ntdll.edf
reactos/lib/ntdll/rtl/apc.c
reactos/lib/rpcrt4/clnt/binding.c [deleted file]
reactos/lib/rpcrt4/clnt/string.c [deleted file]
reactos/lib/rpcrt4/midl/Makefile
reactos/lib/rpcrt4/srv/ep.c [deleted file]
reactos/lib/rpcrt4/srv/impersonate.c [deleted file]
reactos/lib/rpcrt4/srv/listen.c [deleted file]
reactos/ntoskrnl/hal/x86/udelay.c
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/ldr.h
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/io/cleanup.c
reactos/ntoskrnl/io/irp.c
reactos/ntoskrnl/io/rw.c
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/ke/i386/usercall.c
reactos/ntoskrnl/ke/wait.c
reactos/ntoskrnl/ldr/sysdll.c
reactos/ntoskrnl/ps/thread.c

index 57774ea..8acbe5f 100644 (file)
@@ -1,5 +1,5 @@
 file ntoskrnl/ntoskrnl.nostrip.exe
 add-symbol-file lib/ntdll/ntdll.dll 0x77f61000
-add-symbol-file subsys/smss/smss.exe 0x401000
+add-symbol-file apps/apc/apc.exe 0x401000
 #add-symbol-file subsys/csrss/csrss.exe 0x401000
 break exp.c:156
index b9297ac..6bbcfba 100644 (file)
@@ -92,7 +92,6 @@ int main(int argc, char* argv[])
    printf("Returned from wait\n");
    ZwClose(FileHandle);
    printf("Program finished\n");
-   for(;;);
    return 0;
 }
 
index a662ec0..773cfb1 100644 (file)
@@ -3,6 +3,8 @@
 #
 PATH_TO_TOP = ../..
 
+CFLAGS = -g
+
 OBJECTS= ../common/crt0.o apc.o
 PROGS= apc.exe
 
index 332052e..9825017 100644 (file)
@@ -98,9 +98,9 @@ typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(PVOID SynchronizeContext);
 
 struct _KAPC;
 
-typedef VOID (*PKNORMAL_ROUTINE)(PVOID NormalContext,
-                                PVOID SystemArgument1,
-                                PVOID SystemArgument2);
+typedef VOID STDCALL (*PKNORMAL_ROUTINE)(PVOID NormalContext,
+                                        PVOID SystemArgument1,
+                                        PVOID SystemArgument2);
 typedef VOID (*PKKERNEL_ROUTINE)(struct _KAPC* Apc,
                                PKNORMAL_ROUTINE* NormalRoutine,
                                PVOID* NormalContext,
index 70df4de..04515bc 100644 (file)
@@ -68,11 +68,13 @@ typedef union _LARGE_INTEGER
     DWORD LowPart;
     LONG  HighPart;
   } u;
+#ifdef ANONYMOUSUNIONS   
   struct
   {
     DWORD LowPart;
     LONG  HighPart;
   };
+#endif /* ANONYMOUSUNIONS */
   LONGLONG QuadPart;
 } LARGE_INTEGER, *PLARGE_INTEGER;
 
@@ -83,11 +85,13 @@ typedef union _ULARGE_INTEGER
     DWORD LowPart;
     DWORD HighPart;
   } u;
+#ifdef ANONYMOUSUNIONS   
   struct
   {
     DWORD LowPart;
     DWORD HighPart;
   };
+#endif /* ANONYMOUSUNIONS */   
   ULONGLONG QuadPart;
 } ULARGE_INTEGER, *PULARGE_INTEGER;
 
@@ -119,6 +123,34 @@ typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
 
 typedef unsigned short *PWCHAR;
 
+#ifdef __PPC__
+#define CONTEXT_CONTROL         1L
+#define CONTEXT_FLOATING_POINT  2L
+#define CONTEXT_INTEGER         4L
+#define CONTEXT_DEBUG_REGISTERS        8L
+
+#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER)
+#define CONTEXT_DEBUGGER (CONTEXT_FULL)
+
+#else /* x86 */
+/* The doc refered me to winnt.h, so I had to look... */
+#define SIZE_OF_80387_REGISTERS      80
+
+/* Values for contextflags */
+#define CONTEXT_i386    0x10000
+#define CONTEXT_CONTROL         (CONTEXT_i386 | 1)     
+#define CONTEXT_INTEGER         (CONTEXT_i386 | 2)     
+#define CONTEXT_SEGMENTS        (CONTEXT_i386 | 4)     
+#define CONTEXT_FLOATING_POINT  (CONTEXT_i386 | 8)     
+#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10)
+#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
+
+/* our own invention */
+#define FLAG_TRACE_BIT 0x100
+#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
+
+#endif
+
 #ifdef __i386__
 
 typedef struct _FLOATING_SAVE_AREA {
index 5ff63ca..f7f8d26 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rw.c,v 1.13 2000/06/03 14:47:32 ea Exp $
+/* $Id: rw.c,v 1.14 2000/10/11 20:50:31 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -165,12 +165,12 @@ VOID ApcRoutine(PVOID ApcContext,
 }
 
 
-WINBOOL STDCALL WriteFileEx (HANDLE                            hFile,
-                            LPCVOID                            lpBuffer,
-                            DWORD                              nNumberOfBytesToWrite,
-                            LPOVERLAPPED                       lpOverLapped,
-                            LPOVERLAPPED_COMPLETION_ROUTINE    lpCompletionRoutine
-                            )
+WINBOOL STDCALL 
+WriteFileEx (HANDLE                            hFile,
+            LPCVOID                            lpBuffer,
+            DWORD                              nNumberOfBytesToWrite,
+            LPOVERLAPPED                       lpOverLapped,
+            LPOVERLAPPED_COMPLETION_ROUTINE    lpCompletionRoutine)
 {
 
    LARGE_INTEGER Offset;
index 905393e..9fd64f0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.21 2000/10/08 16:32:52 dwelch Exp $
+/* $Id: thread.c,v 1.22 2000/10/11 20:50:32 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -344,12 +344,9 @@ DWORD STDCALL ResumeThread(HANDLE hThread)
 }
 
 
-WINBOOL
-STDCALL
-TerminateThread (
-       HANDLE  hThread,
-       DWORD   dwExitCode
-       )
+WINBOOL STDCALL
+TerminateThread (HANDLE        hThread,
+                DWORD  dwExitCode)
 {
    NTSTATUS errCode;
 
index ddcca28..4034fe2 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.def,v 1.64 2000/09/01 17:04:47 ekohl Exp $
+; $Id: ntdll.def,v 1.65 2000/10/11 20:50:32 dwelch Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -29,7 +29,7 @@ DbgUiContinue@8
 DbgUiWaitStateChange@8
 DbgUserBreakPoint@0
 ;KiRaiseUserExceptionDispatcher
-;KiUserApcDispatcher
+KiUserApcDispatcher
 ;KiUserCallbackDispatcher
 ;KiUserExceptionDispatcher
 LdrAccessResource@16
index 9e53872..2a543cd 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.edf,v 1.53 2000/09/01 17:04:47 ekohl Exp $
+; $Id: ntdll.edf,v 1.54 2000/10/11 20:50:32 dwelch Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -29,7 +29,7 @@ DbgUiContinue=DbgUiContinue@8
 DbgUiWaitStateChange=DbgUiWaitStateChange@8
 DbgUserBreakPoint=DbgUserBreakPoint@0
 ;KiRaiseUserExceptionDispatcher
-;KiUserApcDispatcher
+KiUserApcDispatcher=KiUserApcDispatcher@20
 ;KiUserCallbackDispatcher
 ;KiUserExceptionDispatcher
 LdrAccessResource=LdrAccessResource@16
index 99ef246..d909cfd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: apc.c,v 1.3 2000/06/29 23:35:29 dwelch Exp $
+/* $Id: apc.c,v 1.4 2000/10/11 20:50:32 dwelch Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
@@ -20,9 +20,14 @@ VOID STDCALL KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine,
                                 ULONG Reserved,
                                 PCONTEXT Context)
 {
+   DbgPrint("KiUserApcDispatcher(ApcRoutine %x, ApcContext %x, Context %x)\n",
+           ApcRoutine, ApcContext, Context);
    ApcRoutine(ApcContext,
              Iosb,
-             Reserved);;
+             Reserved);
+   DbgPrint("Done ApcRoutine, Context %x, Context->Eip %x\n",
+           Context, Context->Eip);
    NtContinue(Context, 1);
+   DbgPrint("Returned from NtContinue, aargh\n");
 }
 
diff --git a/reactos/lib/rpcrt4/clnt/binding.c b/reactos/lib/rpcrt4/clnt/binding.c
deleted file mode 100644 (file)
index 17bc181..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-RPC_STATUS RpcBindingFromStringBindingW(PWCHAR Binding,
-                                       handle_t* BindingHandle)
-{
-   
-}
-
-RPC_STATUS RpcBindingFromStringBindingA(PUCHAR Binding,
-                                       handle_t BindingHandle)
-{
-}
diff --git a/reactos/lib/rpcrt4/clnt/string.c b/reactos/lib/rpcrt4/clnt/string.c
deleted file mode 100644 (file)
index 31091a8..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 
- */
-
-RPC_STATUS RpcStringBindingComposeA(PUCHAR Uuid,
-                                   PUCHAR Protocol,
-                                   PUCHAR Address,
-                                   PUCHAR Endpoint,
-                                   PUCHAR Options,
-                                   PUCHAR* Binding)
-{
-   ULONG Len;
-   
-   
-   Len = strlen(Protocol) + 1 + strlen(Address) +
-     1 + strlen(Endpoint) + 1 + 1;
-   (*Binding) = HeapAlloc(GetProcessHeap(),
-                         HEAP_ZERO_MEMORY,
-                         Len);
-   strcpy(*Binding, Protocol);
-   strcat(*Binding, ":");
-   strcat(*Binding, Address);
-   strcat(*Binding, "[");
-   strcat(*Binding, Endpoint);
-   strcat(*Binding, "]");
-   
-   return(STATUS_SUCCESS);
-}
-
-RPC_STATUS RpcStringBindingComposeW(PWCHAR Uuid,
-                                   PWCHAR Protocol,
-                                   PWCHAR Address,
-                                   PWCHAR Endpoint,
-                                   WCHAR Options,
-                                   PWCHAR* Binding)
-{
-   ULONG Len;
-   
-   
-   Len = wcslen(Protocol) + 1 + wcslen(Address) +
-     1 + wcslen(Endpoint) + 1 + 1;
-   (*Binding) = HeapAlloc(GetProcessHeap(),
-                         HEAP_ZERO_MEMORY,
-                         Len * 2);
-   wcscpy(*Binding, Protocol);
-   wcscat(*Binding, ":");
-   wcscat(*Binding, Address);
-   wcscat(*Binding, "[");
-   wcscat(*Binding, Endpoint);
-   wcscat(*Binding, "]");
-   
-   return(STATUS_SUCCESS);
-}
index ad5cf6e..067d5ca 100644 (file)
@@ -1,12 +1,10 @@
-# $Id: Makefile,v 1.1 2000/03/26 22:00:08 dwelch Exp $
+# $Id: Makefile,v 1.2 2000/10/11 20:50:33 dwelch Exp $
 #
 # ReactOS Operating System
 #
 TARGET=midl
 
-BASE_CFLAGS = -I../../include
-
-CFLAGS = $(CFLAGS) 
+CFLAGS = 
 
 all: midl$(EXE_POSTFIX)
 
diff --git a/reactos/lib/rpcrt4/srv/ep.c b/reactos/lib/rpcrt4/srv/ep.c
deleted file mode 100644 (file)
index fd2c327..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <windows.h>
-
-/* FUNCTIONS *****************************************************************/
-
-RPC_STATUS RpcServerUseProtseqA(unsigned char* Protseq,
-                               unsigned int MaxCalls,
-                               void* SecurityDescriptor)
-{
-   return(RpcServerUseProtseqEpA(Protseq,
-                                MaxCalls,
-                                SecuritDescriptor));
-}
-
-RPC_STATUS RpcServerUseProtseqW(unsigned wchar_t* Protseq,
-                               unsigned int MaxCalls,
-                               void* SecurityDescriptor)
-{
-   return(RpcServerUseProtseqEpW(Protseq,
-                                MaxCalls,
-                                SecuritDescriptor));
-}
-
-RPC_STATUS RpcServerUseProtseqEpA(unsigned char* Protseq,
-                                 unsigned int MaxCalls,
-                                 unsigned char* Endpoint,
-                                 void* SecurityDescriptor)
-{
-   unsigned wchar_t* ProtseqW;
-   UNICODE_STRING ProtseqU;
-   ANSI_STRING ProtseqA;
-   unsigned wchar_t* EndpointW;
-   UNICODE_STRING EndpointU;
-   ANSI_STRING EndpointA;
-   RPC_STATUS Status;
-   
-   if (Protseq != NULL)
-     {
-       RtlInitAnsiString(&ProtseqA, Protseq);
-       RtlAnsiStringToUnicodeString(&ProtseqU, &ProtseqA, TRUE);
-       ProtseqW = ProtseqU.Buffer;
-     }
-   else
-     {
-       ProtseqW = NULL;
-     }
-   if (Endpoint != NULL)
-     {
-       RtlInitAnsiString(&EndpointA, Endpoint);
-       RtlAnsiStringToUnicodeString(&EndpointU, &EndpointA, TRUE);
-       EndpointW = EndpointU.Buffer;
-     }
-   else
-     {
-       EndpointW = NULL;
-     }
-   
-   Status = RpcServerUseProtseqEpW(ProtseqW,
-                                  MaxCalls,
-                                  EndpointW,
-                                  SecurityDescriptor);
-   
-   RtlFreeUnicodeString(&EndpointU);
-   RtlFreeUnicodeString(&ProtseqU);
-   return(Status);
-}
-
-RPC_STATUS RpcServerUseProtseqEpW(unsigned wchar_t* Protseq,
-                                 unsigned int MaxCalls,
-                                 unsigned wchar_t* Endpoint,
-                                 void* SecurityDescriptor)
-{
-}
-
-RPC_STATUS RpcServerRegisterIf(RPC_IF_HANDLE IfSpec,
-                              UUID* MgrTypeUuid,
-                              RPC_MGR_EPV* MgrEpv)
-{
-   
-}
-
-
diff --git a/reactos/lib/rpcrt4/srv/impersonate.c b/reactos/lib/rpcrt4/srv/impersonate.c
deleted file mode 100644 (file)
index cb2843e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <windows.h>
-
-/* FUNCTIONS *****************************************************************/
-
-RPC_STATUS RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
-{
-}
-
-RPC_STATUS RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
-{
-}
-
-RPC_STATUS RpcRevertToSelf()
-{
-}
diff --git a/reactos/lib/rpcrt4/srv/listen.c b/reactos/lib/rpcrt4/srv/listen.c
deleted file mode 100644 (file)
index a1b551d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * COPYRIGHT:  See COPYING in the top level directory
- * PROJECT:    DCE/RPC for Reactos
- * FILE:       lib/rpcrt4/srv/listen.c
- * PURPOSE:    Listener functions
- * PROGRAMMER: David Welch <welch@cwcom.net>
- */
-
-/* INCLUDES ******************************************************************/
-
-/* TYPES *********************************************************************/
-
-typedef struct
-{
-} listener_socket;
-
-/* GLOBALS *******************************************************************/
-
-#define NR_MAX_LISTENERS              (255)
-
-static HANDLE ListenerMutex;
-static ULONG InServerListen;
-
-/* FUNCTIONS *****************************************************************/
-
-static DWORD RpcListenerThread(PVOID Param)
-{
-   
-}
-
-BOOL RpcInitListenModule(VOID)
-{
-   ListenerMutex = CreateMutex(NULL,
-                              FALSE,
-                              NULL);
-   if (ListenMutex == NULL)
-     {
-       return(FALSE);
-     }
-   
-   InServerListen = 0;
-}
-
-RPC_STATUS RpcServerListen(unsigned int MinimumCallThreads,
-                          unsigned int MaxCalls,
-                          unsigned int DontWait)
-{
-}
index 60b1523..b60cb71 100644 (file)
@@ -1,11 +1,8 @@
-/* $Id: udelay.c,v 1.3 2000/10/07 13:41:50 dwelch Exp $
- *
- * PROJECT:        ReactOS kernel
- * FILE:           ntoskrnl/hal/x86/udelay.c
- * PURPOSE:        Busy waiting
- * PROGRAMMER:     David Welch (david.welch@seh.ox.ac.uk)
- * UPDATE HISTORY:
- *                 06/11/99 Created
+/*
+ * ReactOS kernel
+ * Copyright (C) 2000 David Welch <welch@cwcom.net>
+ * Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
+ * Copyright (C) 1991, 1992 Linus Torvalds
  * 
  * This software is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * MA 02139, USA.  
  *
  */
+/* $Id: udelay.c,v 1.4 2000/10/11 20:50:33 dwelch Exp $
+ *
+ * PROJECT:        ReactOS kernel
+ * FILE:           ntoskrnl/hal/x86/udelay.c
+ * PURPOSE:        Busy waiting
+ * PROGRAMMER:     David Welch (david.welch@seh.ox.ac.uk)
+ * UPDATE HISTORY:
+ *                 06/11/99 Created
+ */
 
 /* INCLUDES ***************************************************************/
 
index 3f03ace..b56babc 100644 (file)
@@ -20,6 +20,7 @@ typedef struct _KTRAP_FRAME
    PVOID DebugEbp;
    PVOID DebugEip;
    PVOID DebugArgMark;
+   PVOID DebugPointer;
    PVOID TempCs;
    PVOID TempEip;
    PVOID Dr0;
index b8d5225..b67355e 100644 (file)
@@ -36,9 +36,9 @@ LdrpMapSystemDll (
        PVOID   * LdrStartupAddress
        );
 PVOID
-LdrpGetSystemDllEntryPoint (
-       VOID
-       );
+LdrpGetSystemDllEntryPoint (VOID);
+PVOID 
+LdrpGetSystemDllApcDispatcher(VOID);
 NTSTATUS
 LdrpMapImage (
        HANDLE  ProcessHandle, 
index bd2ff4e..12907eb 100644 (file)
@@ -30,6 +30,7 @@
 /*
  * Defines for accessing KPCR and KTHREAD structure members
  */
+#define KTHREAD_KERNEL_STACK      0x28
 #define KTHREAD_PREVIOUS_MODE     0x137
 #define KTHREAD_TRAP_FRAME        0x128
 
index a02e01f..4ed2c41 100644 (file)
@@ -30,13 +30,38 @@ VOID IopCompleteRequest1(struct _KAPC* Apc,
                         PVOID* SystemArgument2)
 {
    PIRP Irp;
+   CCHAR PriorityBoost;
+   PIO_STACK_LOCATION IoStack;
+   PFILE_OBJECT FileObject;
    
    DPRINT("IopCompleteRequest1()\n");
    
    Irp = (PIRP)(*SystemArgument1);
+   PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
+   
+   IoStack = IoGetCurrentIrpStackLocation(Irp);
+   
    (*SystemArgument1) = (PVOID)Irp->UserIosb;
    (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
-   IoFreeIrp((PIRP)(*SystemArgument1));
+   
+   if (Irp->UserIosb!=NULL)
+     {
+       *Irp->UserIosb=Irp->IoStatus;
+     }
+   if (Irp->UserEvent!=NULL)
+     {
+       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
+     }
+
+   FileObject = IoStack->FileObject;
+   
+   if (FileObject != NULL && IoStack->MajorFunction != IRP_MJ_CLOSE)
+     {
+       ObDereferenceObject(FileObject);
+     }
+   
+   IoFreeIrp(Irp);
+
 }
 
 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
@@ -196,7 +221,7 @@ VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
        UserApcRoutine = (PKNORMAL_ROUTINE)
          Irp->Overlay.AsynchronousParameters.UserApcRoutine;
        UserApcContext = (PVOID)
-         Irp->Overlay.AsynchronousParameters.UserApcRoutine;
+         Irp->Overlay.AsynchronousParameters.UserApcContext;
        KeInitializeApc(&Irp->Tail.Apc,
                        Thread,
                        0,
@@ -207,7 +232,7 @@ VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
                        UserApcContext);
        KeInsertQueueApc(&Irp->Tail.Apc,
                         Irp,
-                        NULL,
+                        (PVOID)(LONG)PriorityBoost,
                         KernelMode);
        return;
      }
index 2d3d46c..6321846 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: irp.c,v 1.29 2000/07/04 08:52:38 dwelch Exp $
+/* $Id: irp.c,v 1.30 2000/10/11 20:50:34 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -40,8 +40,7 @@
 
 /* FUNCTIONS ****************************************************************/
 
-PDEVICE_OBJECT
-STDCALL
+PDEVICE_OBJECT STDCALL
 IoGetDeviceToVerify (PETHREAD Thread)
 /*
  * FUNCTION: Returns a pointer to the device, representing a removable-media
@@ -52,8 +51,7 @@ IoGetDeviceToVerify (PETHREAD Thread)
 }
 
 
-VOID
-STDCALL
+VOID STDCALL
 IoFreeIrp (PIRP Irp)
 /*
  * FUNCTION: Releases a caller allocated irp
@@ -65,8 +63,7 @@ IoFreeIrp (PIRP Irp)
 }
 
 
-PIRP
-STDCALL
+PIRP STDCALL
 IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
 /*
  * FUNCTION: Allocates and initializes an irp to associated with a master irp
@@ -83,8 +80,7 @@ IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
 }
 
 
-VOID
-STDCALL
+VOID STDCALL
 IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
 /*
  * FUNCTION: Initalizes an irp allocated by the caller
@@ -104,8 +100,7 @@ IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
 }
 
 
-NTSTATUS
-FASTCALL
+NTSTATUS FASTCALL
 IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 /*
   * FUNCTION: Sends an IRP to the next lower driver
@@ -248,10 +243,9 @@ IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
                        IopCompleteRequest,
                        NULL,
                        (PKNORMAL_ROUTINE)
-                       Irp->Overlay.AsynchronousParameters.UserApcRoutine,
-                       UserMode,
-                       (PVOID)
-                          Irp->Overlay.AsynchronousParameters.UserApcContext);
+                       NULL,
+                       KernelMode,
+                       NULL);
        KeInsertQueueApc(&Irp->Tail.Apc,
                         (PVOID)Irp,
                         (PVOID)(ULONG)PriorityBoost,
index 7bb5b67..3390372 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rw.c,v 1.31 2000/07/07 00:42:58 phreak Exp $
+/* $Id: rw.c,v 1.32 2000/10/11 20:50:34 dwelch Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -88,16 +88,21 @@ NTSTATUS STDCALL NtReadFile(HANDLE                  FileHandle,
                                           NULL);
        if (!NT_SUCCESS(Status))
          {
+            ObDereferenceObject(FileObject);
             return Status;
          }
      }
-   else
-     {
+   else if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+     { 
        KeInitializeEvent(&Event,
                          NotificationEvent,
                          FALSE);
        ptrEvent = &Event;
      }
+   else
+     {
+       ptrEvent = NULL;
+     }
    
    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
                                      FileObject->DeviceObject,
@@ -126,10 +131,21 @@ NTSTATUS STDCALL NtReadFile(HANDLE                        FileHandle,
    if ((Status == STATUS_PENDING) && 
        (FileObject->Flags & FO_SYNCHRONOUS_IO))
      {
+       BOOLEAN Alertable;
+       
+       if (FileObject->Flags & FO_ALERTABLE_IO)
+         {
+            Alertable = TRUE;
+         }
+       else
+         {
+            Alertable = FALSE;
+         } 
+       
        KeWaitForSingleObject(&Event,
                              Executive,
                              KernelMode,
-                             FALSE,
+                             Alertable,
                              NULL);
        Status = IoStatusBlock->Status;
      }
@@ -166,6 +182,7 @@ NTSTATUS STDCALL NtWriteFile(HANDLE                 FileHandle,
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    KEVENT Event;
+   PKEVENT ptrEvent;
    
    DPRINT("NtWriteFile(FileHandle %x, Buffer %x, Length %d)\n",
          FileHandle, Buffer, Length);
@@ -185,7 +202,33 @@ NTSTATUS STDCALL NtWriteFile(HANDLE                        FileHandle,
      {
        ByteOffset = &FileObject->CurrentByteOffset;
      }
-   
+
+   if (EventHandle != NULL)
+     {
+       Status = ObReferenceObjectByHandle(EventHandle,
+                                          SYNCHRONIZE,
+                                          ExEventObjectType,
+                                          UserMode,
+                                          (PVOID*)&ptrEvent,
+                                          NULL);
+       if (!NT_SUCCESS(Status))
+         {
+            ObDereferenceObject(FileObject);
+            return(Status);
+         }
+     }
+   else if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+     { 
+       KeInitializeEvent(&Event,
+                         NotificationEvent,
+                         FALSE);
+       ptrEvent = &Event;
+     }
+   else
+     {
+       ptrEvent = NULL;
+     }
+
    KeInitializeEvent(&Event,
                     NotificationEvent,
                     FALSE);
@@ -194,7 +237,7 @@ NTSTATUS STDCALL NtWriteFile(HANDLE                 FileHandle,
                                      Buffer,
                                      Length,
                                      ByteOffset,
-                                     &Event,
+                                     ptrEvent,
                                      IoStatusBlock);
    
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
index 9b1a742..32e66f0 100644 (file)
 #include <internal/i386/segment.h>
 #include <internal/ps.h>
 #include <internal/ke.h>
+#include <internal/ldr.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
+/* NOTES *********************************************************************/
+
+
+
 /* GLOBALS *******************************************************************/
 
 KSPIN_LOCK PiApcLock;
@@ -45,9 +50,16 @@ VOID KeCallKernelRoutineApc(PKAPC Apc)
    DPRINT("Finished KeCallKernelRoutineApc()\n");
 }
 
+VOID KiRundownThread(VOID)
+/*
+ * FUNCTION: 
+ */
+{
+}
+
 BOOLEAN KiTestAlert(VOID)
 /*
- * FUNCTION: Tests whether there are any pending APCs for the curren thread
+ * FUNCTION: Tests whether there are any pending APCs for the current thread
  * and if so the APCs will be delivered on exit from kernel mode
  */
 {
@@ -73,61 +85,98 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
  *        UserContext = The user context saved on entry to kernel mode
  */
 {
-#if 0   
    PLIST_ENTRY current_entry;
    PKAPC Apc;
    PULONG Esp;
+   PCONTEXT Context;
    KIRQL oldlvl;
-   CONTEXT SavedContext;
-   ULONG Top;
-   BOOL ret = FALSE;
-   PETHREAD EThread;
    PKTHREAD Thread;
    
-   DPRINT("KiDeliverUserApc(TrapFrame %x)\n", TrapFrame);
+   DPRINT("KiDeliverUserApc(TrapFrame %x/%x)\n", TrapFrame,
+         KeGetCurrentThread()->TrapFrame);
    Thread = KeGetCurrentThread();
-   while(1)
+   KeAcquireSpinLock(&PiApcLock, &oldlvl);
+   current_entry = Thread->ApcState.ApcListHead[1].Flink;
+   
+   /*
+    * Shouldn't happen but check anyway.
+    */
+   if (current_entry == &Thread->ApcState.ApcListHead[1])
      {
-       KeAcquireSpinLock(&PiApcLock, &oldlvl);
-       current_entry = Thread->ApcState.ApcListHead[1].Flink;
-       
-       if (current_entry == &Thread->ApcState.ApcListHead[1])
-        {
-          KeReleaseSpinLock(&PiApcLock, oldlvl);
-          break;
-        }
-       ret = TRUE;
-       current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]);
-       Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
-       
-       DPRINT("Esp %x\n", Esp);
-       DPRINT("Apc->NormalContext %x\n", Apc->NormalContext);
-       DPRINT("Apc->SystemArgument1 %x\n", Apc->SystemArgument1);
-       DPRINT("Apc->SystemArgument2 %x\n", Apc->SystemArgument2);
-       DPRINT("UserContext->Eip %x\n", UserContext->Eip);
-       
-       Esp = (PULONG)UserContext->Esp;
-       
-       memcpy(&SavedContext, UserContext, sizeof(CONTEXT));
-       
-       Esp = Esp - (sizeof(CONTEXT) + (5 * sizeof(ULONG)));
-       memcpy(Esp, &SavedContext, sizeof(CONTEXT));
-       Top = sizeof(CONTEXT) / 4;
-       Esp[Top] = (ULONG)Apc->NormalRoutine;
-       Esp[Top + 1] = (ULONG)Apc->NormalContext;
-       Esp[Top + 2] = (ULONG)Apc->SystemArgument1;
-       Esp[Top + 3] = (ULONG)Apc->SystemArgument2;
-       Esp[Top + 4] = (ULONG)Esp - sizeof(CONTEXT);
-       UserContext->Eip = 0;  // KiUserApcDispatcher
-       
-       KeReleaseSpinLock(&PiApcLock, oldlvl);
-       
-       /*
-       * Now call for the kernel routine for the APC, which will free
-       * the APC data structure
-       */
-       KeCallKernelRoutineApc(Apc);
+       KeReleaseSpinLock(&PiApcLock, oldlvl);
+       DbgPrint("KiDeliverUserApc called but no APC was pending\n");
+       return(FALSE);
      }
+   
+   current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]);
+   Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
+   
+   /*
+    * Save the thread's current context (in other words the registers
+    * that will be restored when it returns to user mode) so the
+    * APC dispatcher can restore them later
+    */
+   Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
+   memset(Context, 0, sizeof(CONTEXT));
+   Context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | 
+     CONTEXT_SEGMENTS | CONTEXT_i386;
+   Context->SegGs = TrapFrame->Gs;
+   Context->SegFs = TrapFrame->Fs;
+   Context->SegEs = TrapFrame->Es;
+   Context->SegDs = TrapFrame->Ds;
+   Context->Edi = TrapFrame->Edi;
+   Context->Esi = TrapFrame->Esi;
+   Context->Ebx = TrapFrame->Ebx;
+   Context->Edx = TrapFrame->Edx;
+   Context->Ecx = TrapFrame->Ecx;
+   Context->Eax = TrapFrame->Eax;
+   Context->Ebp = TrapFrame->Ebp;
+   Context->Eip = TrapFrame->Eip;
+   Context->SegCs = TrapFrame->Cs;
+   Context->EFlags = TrapFrame->Eflags;
+   Context->Esp = TrapFrame->Esp;
+   Context->SegSs = TrapFrame->Ss;
+   
+   /*
+    * Setup the trap frame so the thread will start executing at the
+    * APC Dispatcher when it returns to user-mode
+    */
+   Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - 
+                 (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
+   
+   Esp[0] = 0xdeadbeef;
+   Esp[1] = (ULONG)Apc->NormalRoutine;
+   Esp[2] = (ULONG)Apc->NormalContext;
+   Esp[3] = (ULONG)Apc->SystemArgument1;
+   Esp[4] = (ULONG)Apc->SystemArgument2;
+   Esp[5] = (ULONG)Context;
+   TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
+   TrapFrame->Esp = (ULONG)Esp;     
+   
+   /*
+    * We've dealt with one pending user-mode APC
+    */
+   Thread->ApcState.UserApcPending--;
+   
+   /*
+    * FIXME: Give some justification for this
+    */
+   KeReleaseSpinLock(&PiApcLock, oldlvl);
+       
+   /*
+    * Now call for the kernel routine for the APC, which will free
+    * the APC data structure, we can't do this ourselves because
+    * the APC may be embedded in some larger structure e.g. an IRP
+    * We also give the kernel routine a last chance to modify the arguments to 
+    * the user APC routine.
+    */
+   Apc->KernelRoutine(Apc,
+                     (PKNORMAL_ROUTINE*)&Esp[1],
+                     (PVOID*)&Esp[2],
+                     (PVOID*)&Esp[3],
+                     (PVOID*)&Esp[4]);
+
+#if 0   
    KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
    EThread = CONTAINING_RECORD(Thread, ETHREAD, Tcb);
    if (EThread->DeadThread)
@@ -147,6 +196,14 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
 VOID STDCALL KiDeliverApc(ULONG Unknown1,
                          ULONG Unknown2,
                          ULONG Unknown3)
+/*
+ * FUNCTION: Deliver an APC to the current thread.
+ * NOTES: This is called from the IRQL switching code if the current thread
+ * is returning from an IRQL greater than or equal to APC_LEVEL to 
+ * PASSIVE_LEVEL and there are kernel-mode APCs pending. This means any
+ * pending APCs will be delivered after a thread gets a new quantum and
+ * after it wakes from a wait. 
+ */
 {
    PETHREAD Thread = PsGetCurrentThread();
    PLIST_ENTRY current;
@@ -217,8 +274,6 @@ VOID STDCALL KeInsertQueueApc (PKAPC        Apc,
      {
        InsertTailList(&TargetThread->ApcState.ApcListHead[1],
                       &Apc->ApcListEntry);
-       TargetThread->ApcState.KernelApcPending++;
-       TargetThread->ApcState.UserApcPending++;
      }
    Apc->Inserted = TRUE;
    
@@ -235,6 +290,7 @@ VOID STDCALL KeInsertQueueApc (PKAPC        Apc,
        
        DPRINT("Resuming thread for user APC\n");
        
+       TargetThread->ApcState.UserApcPending++;
        Status = STATUS_USER_APC;
        KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
                               STATUS_USER_APC);
@@ -289,6 +345,19 @@ KeInitializeApc (PKAPC                     Apc,
      }
 }
 
+VOID NtQueueApcRundownRoutine(PKAPC Apc)
+{
+   ExFreePool(Apc);
+}
+
+VOID NtQueueApcKernelRoutine(PKAPC Apc,
+                            PKNORMAL_ROUTINE* NormalRoutine,
+                            PVOID* NormalContext,
+                            PVOID* SystemArgument1,
+                            PVOID* SystemArgument2)
+{
+   ExFreePool(Apc);
+}
 
 NTSTATUS STDCALL NtQueueApcThread(HANDLE                       ThreadHandle,
                                  PKNORMAL_ROUTINE      ApcRoutine,
@@ -321,8 +390,8 @@ NTSTATUS STDCALL NtQueueApcThread(HANDLE                    ThreadHandle,
    KeInitializeApc(Apc,
                   &Thread->Tcb,
                   0,
-                  NULL,
-                  NULL,
+                  NtQueueApcKernelRoutine,
+                  NtQueueApcRundownRoutine,
                   ApcRoutine,
                   UserMode,
                   NormalContext);
index 47c3654..d700a98 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: trap.s,v 1.3 2000/10/07 13:41:52 dwelch Exp $
+/* $Id: trap.s,v 1.4 2000/10/11 20:50:34 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -170,7 +170,7 @@ new_serviceInRange:
            movl %ebp,%esp
 
           /* Call the post system call hook and deliver any pending APCs */
-          pushl %esp
+          pushl %ebp
           pushl %eax
           call _KiAfterSystemCallHook
           addl $8,%esp
@@ -251,9 +251,7 @@ new_done:
           popl %ebx
           movl %ebx, %fs:KPCR_EXCEPTION_LIST
        
-          popl %ebx
-          movl %ebx, %fs
-/*        popl %fs */
+          popl %fs 
           popl %edi
           popl %esi
           popl %ebx
index f74178c..6cdaaf3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: usercall.c,v 1.15 2000/10/07 13:41:52 dwelch Exp $
+/* $Id: usercall.c,v 1.16 2000/10/11 20:50:34 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -44,7 +44,8 @@ VOID KiSystemCallHook(ULONG Nr, ...)
 
 ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
 {
-   if (KeGetCurrentThread()->ApcState.UserApcPending == 0)
+   if (KeGetCurrentThread()->ApcState.UserApcPending == 0 ||
+       TrapFrame->Cs == KERNEL_CS)
      {
        return(NtStatus);
      }
index 33a4242..ec09986 100644 (file)
@@ -397,6 +397,7 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID               Object,
    if (Alertable && !IsListEmpty(&CurrentThread->ApcState.ApcListHead[1]))
      {
        DPRINT("Thread is alertable and user APCs are pending\n");
+       KiTestAlert();
        return(STATUS_USER_APC);
      }
    
@@ -445,6 +446,10 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID              Object,
      {
        KeCancelTimer(&KeGetCurrentThread()->Timer);
      }
+   if (Status == STATUS_USER_APC)
+     {
+       KiTestAlert();
+     }
    
    DPRINT("Returning from KeWaitForSingleObject()\n");
    return Status;
index bda0264..b29e859 100644 (file)
@@ -246,13 +246,12 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle,
    /*
     * FIXME: retrieve the offset of the APC dispatcher from NTDLL
     */
-/*
    RtlInitAnsiString (&ProcedureName,
                      "KiUserApcDispatcher");
    Status = LdrGetProcedureAddress ((PVOID)ImageBase,
                                    &ProcedureName,
                                    0,
-                                   (PULONG)&SystemDllApcDispatcher);
+                                   &SystemDllApcDispatcher);
    if (!NT_SUCCESS(Status))
      {
        DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status);
@@ -261,8 +260,6 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle,
        ZwClose(NTDllSectionHandle);
        return (Status);
      }
-*/
-   SystemDllApcDispatcher = NULL;
 
    KeDetachProcess();
    ObDereferenceObject(Process);
index 2a115c7..124f326 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.57 2000/10/08 16:32:53 dwelch Exp $
+/* $Id: thread.c,v 1.58 2000/10/11 20:50:35 dwelch Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -53,56 +53,6 @@ static PETHREAD CurrentThread = NULL;
 
 /* FUNCTIONS ***************************************************************/
 
-VOID PsFreezeProcessThreads(PEPROCESS Process)
-{
-   KIRQL oldIrql;
-   PLIST_ENTRY current_entry;
-   PETHREAD current;
-   
-   KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
-   current_entry = PiThreadListHead.Flink;
-   
-   while (current_entry != &PiThreadListHead)
-     {
-       current = CONTAINING_RECORD(current_entry, ETHREAD, 
-                                   Tcb.ThreadListEntry);
-       
-       current_entry = current_entry->Flink;
-       
-       if (current->ThreadsProcess == Process &&
-           current != PsGetCurrentThread())
-         {
-            PsFreezeOtherThread(current);
-         }
-     }
-   KeReleaseSpinLock(&PiThreadListLock, oldIrql);
-}
-
-VOID PsUnfreezeProcessThreads(PEPROCESS Process)
-{
-   KIRQL oldIrql;
-   PLIST_ENTRY current_entry;
-   PETHREAD current;
-   
-   KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
-   current_entry = PiThreadListHead.Flink;
-   
-   while (current_entry != &PiThreadListHead)
-     {
-       current = CONTAINING_RECORD(current_entry, ETHREAD, 
-                                   Tcb.ThreadListEntry);
-       
-       current_entry = current_entry->Flink;
-       
-       if (current->ThreadsProcess == Process &&
-           current != PsGetCurrentThread())
-         {
-            PsUnfreezeOtherThread(current);
-         }
-     }
-   KeReleaseSpinLock(&PiThreadListLock, oldIrql);
-}
-
 PKTHREAD STDCALL KeGetCurrentThread(VOID)
 {
    return(&(CurrentThread->Tcb));
@@ -300,25 +250,6 @@ VOID PsUnfreezeOtherThread(PETHREAD Thread)
      }
 }
 
-VOID PsFreezeOtherThread(PETHREAD Thread)
-{
-   ULONG r;
-   
-   Thread->Tcb.FreezeCount++;
-   r = Thread->Tcb.FreezeCount;
-   
-   if (r == 0)
-     {
-       return;
-     }
-   
-   if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
-     {
-       RemoveEntryList(&Thread->Tcb.QueueListEntry);
-     }
-   Thread->Tcb.State = THREAD_STATE_FROZEN;   
-}
-
 ULONG PsFreezeThread(PETHREAD Thread, 
                     PNTSTATUS Status, 
                     UCHAR Alertable,
@@ -346,13 +277,8 @@ ULONG PsFreezeThread(PETHREAD Thread,
    
    if (PsGetCurrentThread() != Thread)
      {
-       DPRINT("Suspending other\n");
-       if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
-         {
-            RemoveEntryList(&Thread->Tcb.QueueListEntry);
-         }
-       Thread->Tcb.State = THREAD_STATE_FROZEN;
-       KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+       DbgPrint("Suspending other\n");
+       KeBugCheck(0);
      }
    else
      {
@@ -495,14 +421,6 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
    return(STATUS_SUCCESS);   
 }
 
-
-NTSTATUS STDCALL NtGetContextThread (IN        HANDLE          ThreadHandle, 
-                                    OUT        PCONTEXT        Context)
-{
-       UNIMPLEMENTED;
-}
-
-
 NTSTATUS STDCALL NtOpenThread(OUT      PHANDLE ThreadHandle,
                              IN        ACCESS_MASK DesiredAccess,
                              IN        POBJECT_ATTRIBUTES ObjectAttributes,
@@ -511,6 +429,214 @@ NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle,
        UNIMPLEMENTED;
 }
 
+VOID KeContextToTrapFrame(PCONTEXT Context,
+                         PKTRAP_FRAME TrapFrame)
+{
+      if (Context->ContextFlags & CONTEXT_CONTROL)
+     {
+       TrapFrame->Esp = Context->Esp;
+       TrapFrame->Ss = Context->SegSs;
+       TrapFrame->Cs = Context->SegCs;
+       TrapFrame->Eip = Context->Eip;
+       TrapFrame->Eflags = Context->EFlags;    
+       TrapFrame->Ebp = Context->Ebp;
+     }
+   if (Context->ContextFlags & CONTEXT_INTEGER)
+     {
+       TrapFrame->Eax = Context->Eax;
+       TrapFrame->Ebx = Context->Ebx;
+       TrapFrame->Ecx = Context->Ecx;
+       /*
+        * Edx is used in the TrapFrame to hold the old trap frame pointer
+        * so we don't want to overwrite it here
+        */
+/*     TrapFrame->Edx = Context->Edx; */
+       TrapFrame->Esi = Context->Esi;
+       TrapFrame->Edx = Context->Edi;
+     }
+   if (Context->ContextFlags & CONTEXT_SEGMENTS)
+     {
+       TrapFrame->Ds = Context->SegDs;
+       TrapFrame->Es = Context->SegEs;
+       TrapFrame->Fs = Context->SegFs;
+       TrapFrame->Gs = Context->SegGs;
+     }
+   if (Context->ContextFlags & CONTEXT_FLOATING_POINT)
+     {
+       /*
+        * Not handled
+        */
+     }
+   if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS)
+     {
+       /*
+        * Not handled
+        */
+     }
+}
+
+VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
+                         PCONTEXT Context)
+{
+   if (Context->ContextFlags & CONTEXT_CONTROL)
+     {
+       Context->SegSs = TrapFrame->Ss;
+       Context->Esp = TrapFrame->Esp;
+       Context->SegCs = TrapFrame->Cs;
+       Context->Eip = TrapFrame->Eip;
+       Context->EFlags = TrapFrame->Eflags;
+       Context->Ebp = TrapFrame->Ebp;
+     }
+   if (Context->ContextFlags & CONTEXT_INTEGER)
+     {
+       Context->Eax = TrapFrame->Eax;
+       Context->Ebx = TrapFrame->Ebx;
+       Context->Ecx = TrapFrame->Ecx;
+       /*
+        * NOTE: In the trap frame which is built on entry to a system
+        * call TrapFrame->Edx will actually hold the address of the
+        * previous TrapFrame. I don't believe leaking this information
+        * has security implications
+        */
+       Context->Edx = TrapFrame->Edx;
+       Context->Esi = TrapFrame->Esi;
+       Context->Edi = TrapFrame->Edi;
+     }
+   if (Context->ContextFlags & CONTEXT_SEGMENTS)
+     {
+       Context->SegDs = TrapFrame->Ds;
+       Context->SegEs = TrapFrame->Es;
+       Context->SegFs = TrapFrame->Fs;
+       Context->SegGs = TrapFrame->Gs;
+     }
+   if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS)
+     {
+       /*
+        * FIXME: Implement this case
+        */     
+     }
+   if (Context->ContextFlags & CONTEXT_FLOATING_POINT)
+     {
+       /*
+        * FIXME: Implement this case
+        */
+     }
+#if 0   
+   if (Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS)
+     {
+       /*
+        * FIXME: Investigate this
+        */
+     }
+#endif
+}
+
+VOID KeGetContextRundownRoutine(PKAPC Apc)
+{
+   PKEVENT Event;
+   PNTSTATUS Status;
+   
+   Event = (PKEVENT)Apc->SystemArgument1;
+   Status = (PNTSTATUS)Apc->SystemArgument2;
+   (*Status) = STATUS_THREAD_IS_TERMINATING;
+   KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+}
+
+VOID KeGetContextKernelRoutine(PKAPC Apc,
+                              PKNORMAL_ROUTINE* NormalRoutine,
+                              PVOID* NormalContext,
+                              PVOID* SystemArgument1,
+                              PVOID* SystemArgument2)
+{
+   PKEVENT Event;
+   PCONTEXT Context;
+   PNTSTATUS Status;
+   
+   Context = (PCONTEXT)(*NormalContext);
+   Event = (PKEVENT)(*SystemArgument1);
+   Status = (PNTSTATUS)(*SystemArgument2);
+   
+   KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
+   
+   *Status = STATUS_SUCCESS;
+   KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+}
+
+NTSTATUS STDCALL NtGetContextThread (IN        HANDLE ThreadHandle, 
+                                    OUT PCONTEXT Context)
+{
+   PETHREAD Thread;
+   NTSTATUS Status;
+   
+   Status = ObReferenceObjectByHandle(ThreadHandle,
+                                     THREAD_GET_CONTEXT,
+                                     PsThreadType,
+                                     UserMode,
+                                     (PVOID*)&Thread,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+   if (Thread == PsGetCurrentThread())
+     {
+       /*
+        * I don't know if trying to get your own context makes much
+        * sense but we can handle it more efficently.
+        */
+       
+       KeTrapFrameToContext(Thread->Tcb.TrapFrame, Context);
+       ObDereferenceObject(Thread);
+       return(STATUS_SUCCESS);
+     }
+   else
+     {
+       KAPC Apc;
+       KEVENT Event;
+       NTSTATUS AStatus;
+       CONTEXT KContext;
+       
+       KContext.ContextFlags = Context->ContextFlags;
+       KeInitializeEvent(&Event,
+                         NotificationEvent,
+                         FALSE);       
+       AStatus = STATUS_SUCCESS;
+       
+       KeInitializeApc(&Apc,
+                       &Thread->Tcb,
+                       0,
+                       KeGetContextKernelRoutine,
+                       KeGetContextRundownRoutine,
+                       NULL,
+                       KernelMode,
+                       (PVOID)&KContext);
+       KeInsertQueueApc(&Apc,
+                        (PVOID)&Event,
+                        (PVOID)&AStatus,
+                        0);
+       Status = KeWaitForSingleObject(&Event,
+                                      0,
+                                      UserMode,
+                                      FALSE,
+                                      NULL);
+       if (!NT_SUCCESS(Status))
+         {
+            return(Status);
+         }
+       if (!NT_SUCCESS(AStatus))
+         {
+            return(AStatus);
+         }
+       memcpy(Context, &KContext, sizeof(CONTEXT));
+       return(STATUS_SUCCESS);
+     }
+}
+
+NTSTATUS STDCALL NtSetContextThread (IN        HANDLE          ThreadHandle,
+                                    IN PCONTEXT        Context)
+{
+   UNIMPLEMENTED;
+}
 
 NTSTATUS STDCALL NtResumeThread (IN    HANDLE  ThreadHandle,
                                 IN     PULONG  SuspendCount)
@@ -530,13 +656,6 @@ NTSTATUS STDCALL NtResumeThread (IN        HANDLE  ThreadHandle,
 }
 
 
-NTSTATUS STDCALL NtSetContextThread (IN        HANDLE          ThreadHandle,
-                                    IN PCONTEXT        Context)
-{
-   UNIMPLEMENTED;
-}
-
-
 NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
                                  IN PULONG PreviousSuspendCount)
 /*
@@ -561,12 +680,15 @@ NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
 NTSTATUS STDCALL NtContinue(IN PCONTEXT        Context,
                            IN BOOLEAN TestAlert)
 {
-   PULONG StackTop;
-   
-   StackTop = KeGetStackTopThread(PsGetCurrentThread());
-   
-   memcpy(StackTop, Context, sizeof(CONTEXT));
+   PKTRAP_FRAME TrapFrame;
    
+   TrapFrame = KeGetCurrentThread()->TrapFrame;
+   if (TrapFrame == NULL)
+     {
+       DbgPrint("NtContinue called but TrapFrame was NULL\n");
+       KeBugCheck(0);
+     }   
+   KeContextToTrapFrame(Context, TrapFrame);
    return(STATUS_SUCCESS);
 }