mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Correct implementation of user-mode APCs
svn path=/trunk/; revision=1401
This commit is contained in:
parent
e7214e13b1
commit
9ab512dafc
29 changed files with 518 additions and 442 deletions
|
@ -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
|
||||
|
|
|
@ -92,7 +92,6 @@ int main(int argc, char* argv[])
|
|||
printf("Returned from wait\n");
|
||||
ZwClose(FileHandle);
|
||||
printf("Program finished\n");
|
||||
for(;;);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
CFLAGS = -g
|
||||
|
||||
OBJECTS= ../common/crt0.o apc.o
|
||||
PROGS= apc.exe
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
RPC_STATUS RpcBindingFromStringBindingW(PWCHAR Binding,
|
||||
handle_t* BindingHandle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RPC_STATUS RpcBindingFromStringBindingA(PUCHAR Binding,
|
||||
handle_t BindingHandle)
|
||||
{
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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()
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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 ***************************************************************/
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ typedef struct _KTRAP_FRAME
|
|||
PVOID DebugEbp;
|
||||
PVOID DebugEip;
|
||||
PVOID DebugArgMark;
|
||||
PVOID DebugPointer;
|
||||
PVOID TempCs;
|
||||
PVOID TempEip;
|
||||
PVOID Dr0;
|
||||
|
|
|
@ -36,9 +36,9 @@ LdrpMapSystemDll (
|
|||
PVOID * LdrStartupAddress
|
||||
);
|
||||
PVOID
|
||||
LdrpGetSystemDllEntryPoint (
|
||||
VOID
|
||||
);
|
||||
LdrpGetSystemDllEntryPoint (VOID);
|
||||
PVOID
|
||||
LdrpGetSystemDllApcDispatcher(VOID);
|
||||
NTSTATUS
|
||||
LdrpMapImage (
|
||||
HANDLE ProcessHandle,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue