Correct implementation of user-mode APCs

svn path=/trunk/; revision=1401
This commit is contained in:
David Welch 2000-10-11 20:50:35 +00:00
parent e7214e13b1
commit 9ab512dafc
29 changed files with 518 additions and 442 deletions

View 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

View 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;
}

View file

@ -3,6 +3,8 @@
#
PATH_TO_TOP = ../..
CFLAGS = -g
OBJECTS= ../common/crt0.o apc.o
PROGS= apc.exe

View 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,

View 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 {

View 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;

View 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;

View 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

View 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

View 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");
}

View file

@ -1,10 +0,0 @@
RPC_STATUS RpcBindingFromStringBindingW(PWCHAR Binding,
handle_t* BindingHandle)
{
}
RPC_STATUS RpcBindingFromStringBindingA(PUCHAR Binding,
handle_t BindingHandle)
{
}

View file

@ -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);
}

View 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)

View file

@ -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)
{
}

View file

@ -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()
{
}

View file

@ -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)
{
}

View 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
@ -23,6 +20,15 @@
* 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 ***************************************************************/

View file

@ -20,6 +20,7 @@ typedef struct _KTRAP_FRAME
PVOID DebugEbp;
PVOID DebugEip;
PVOID DebugArgMark;
PVOID DebugPointer;
PVOID TempCs;
PVOID TempEip;
PVOID Dr0;

View file

@ -36,9 +36,9 @@ LdrpMapSystemDll (
PVOID * LdrStartupAddress
);
PVOID
LdrpGetSystemDllEntryPoint (
VOID
);
LdrpGetSystemDllEntryPoint (VOID);
PVOID
LdrpGetSystemDllApcDispatcher(VOID);
NTSTATUS
LdrpMapImage (
HANDLE ProcessHandle,

View 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

View 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;
}

View 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,

View 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);
@ -186,6 +203,32 @@ 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;

View file

@ -17,10 +17,15 @@
#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);

View 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

View 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);
}

View 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;

View 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);

View 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);
}