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
|
file ntoskrnl/ntoskrnl.nostrip.exe
|
||||||
add-symbol-file lib/ntdll/ntdll.dll 0x77f61000
|
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
|
#add-symbol-file subsys/csrss/csrss.exe 0x401000
|
||||||
break exp.c:156
|
break exp.c:156
|
||||||
|
|
|
@ -92,7 +92,6 @@ int main(int argc, char* argv[])
|
||||||
printf("Returned from wait\n");
|
printf("Returned from wait\n");
|
||||||
ZwClose(FileHandle);
|
ZwClose(FileHandle);
|
||||||
printf("Program finished\n");
|
printf("Program finished\n");
|
||||||
for(;;);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#
|
#
|
||||||
PATH_TO_TOP = ../..
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
CFLAGS = -g
|
||||||
|
|
||||||
OBJECTS= ../common/crt0.o apc.o
|
OBJECTS= ../common/crt0.o apc.o
|
||||||
PROGS= apc.exe
|
PROGS= apc.exe
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,9 @@ typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(PVOID SynchronizeContext);
|
||||||
|
|
||||||
struct _KAPC;
|
struct _KAPC;
|
||||||
|
|
||||||
typedef VOID (*PKNORMAL_ROUTINE)(PVOID NormalContext,
|
typedef VOID STDCALL (*PKNORMAL_ROUTINE)(PVOID NormalContext,
|
||||||
PVOID SystemArgument1,
|
PVOID SystemArgument1,
|
||||||
PVOID SystemArgument2);
|
PVOID SystemArgument2);
|
||||||
typedef VOID (*PKKERNEL_ROUTINE)(struct _KAPC* Apc,
|
typedef VOID (*PKKERNEL_ROUTINE)(struct _KAPC* Apc,
|
||||||
PKNORMAL_ROUTINE* NormalRoutine,
|
PKNORMAL_ROUTINE* NormalRoutine,
|
||||||
PVOID* NormalContext,
|
PVOID* NormalContext,
|
||||||
|
|
|
@ -68,11 +68,13 @@ typedef union _LARGE_INTEGER
|
||||||
DWORD LowPart;
|
DWORD LowPart;
|
||||||
LONG HighPart;
|
LONG HighPart;
|
||||||
} u;
|
} u;
|
||||||
|
#ifdef ANONYMOUSUNIONS
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
DWORD LowPart;
|
DWORD LowPart;
|
||||||
LONG HighPart;
|
LONG HighPart;
|
||||||
};
|
};
|
||||||
|
#endif /* ANONYMOUSUNIONS */
|
||||||
LONGLONG QuadPart;
|
LONGLONG QuadPart;
|
||||||
} LARGE_INTEGER, *PLARGE_INTEGER;
|
} LARGE_INTEGER, *PLARGE_INTEGER;
|
||||||
|
|
||||||
|
@ -83,11 +85,13 @@ typedef union _ULARGE_INTEGER
|
||||||
DWORD LowPart;
|
DWORD LowPart;
|
||||||
DWORD HighPart;
|
DWORD HighPart;
|
||||||
} u;
|
} u;
|
||||||
|
#ifdef ANONYMOUSUNIONS
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
DWORD LowPart;
|
DWORD LowPart;
|
||||||
DWORD HighPart;
|
DWORD HighPart;
|
||||||
};
|
};
|
||||||
|
#endif /* ANONYMOUSUNIONS */
|
||||||
ULONGLONG QuadPart;
|
ULONGLONG QuadPart;
|
||||||
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
||||||
|
|
||||||
|
@ -119,6 +123,34 @@ typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
|
||||||
|
|
||||||
typedef unsigned short *PWCHAR;
|
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__
|
#ifdef __i386__
|
||||||
|
|
||||||
typedef struct _FLOATING_SAVE_AREA {
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -165,12 +165,12 @@ VOID ApcRoutine(PVOID ApcContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WINBOOL STDCALL WriteFileEx (HANDLE hFile,
|
WINBOOL STDCALL
|
||||||
LPCVOID lpBuffer,
|
WriteFileEx (HANDLE hFile,
|
||||||
DWORD nNumberOfBytesToWrite,
|
LPCVOID lpBuffer,
|
||||||
LPOVERLAPPED lpOverLapped,
|
DWORD nNumberOfBytesToWrite,
|
||||||
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
|
LPOVERLAPPED lpOverLapped,
|
||||||
)
|
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
|
||||||
{
|
{
|
||||||
|
|
||||||
LARGE_INTEGER Offset;
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -344,12 +344,9 @@ DWORD STDCALL ResumeThread(HANDLE hThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WINBOOL
|
WINBOOL STDCALL
|
||||||
STDCALL
|
TerminateThread (HANDLE hThread,
|
||||||
TerminateThread (
|
DWORD dwExitCode)
|
||||||
HANDLE hThread,
|
|
||||||
DWORD dwExitCode
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
NTSTATUS errCode;
|
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
|
; ReactOS Operating System
|
||||||
;
|
;
|
||||||
|
@ -29,7 +29,7 @@ DbgUiContinue@8
|
||||||
DbgUiWaitStateChange@8
|
DbgUiWaitStateChange@8
|
||||||
DbgUserBreakPoint@0
|
DbgUserBreakPoint@0
|
||||||
;KiRaiseUserExceptionDispatcher
|
;KiRaiseUserExceptionDispatcher
|
||||||
;KiUserApcDispatcher
|
KiUserApcDispatcher
|
||||||
;KiUserCallbackDispatcher
|
;KiUserCallbackDispatcher
|
||||||
;KiUserExceptionDispatcher
|
;KiUserExceptionDispatcher
|
||||||
LdrAccessResource@16
|
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
|
; ReactOS Operating System
|
||||||
;
|
;
|
||||||
|
@ -29,7 +29,7 @@ DbgUiContinue=DbgUiContinue@8
|
||||||
DbgUiWaitStateChange=DbgUiWaitStateChange@8
|
DbgUiWaitStateChange=DbgUiWaitStateChange@8
|
||||||
DbgUserBreakPoint=DbgUserBreakPoint@0
|
DbgUserBreakPoint=DbgUserBreakPoint@0
|
||||||
;KiRaiseUserExceptionDispatcher
|
;KiRaiseUserExceptionDispatcher
|
||||||
;KiUserApcDispatcher
|
KiUserApcDispatcher=KiUserApcDispatcher@20
|
||||||
;KiUserCallbackDispatcher
|
;KiUserCallbackDispatcher
|
||||||
;KiUserExceptionDispatcher
|
;KiUserExceptionDispatcher
|
||||||
LdrAccessResource=LdrAccessResource@16
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -20,9 +20,14 @@ VOID STDCALL KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine,
|
||||||
ULONG Reserved,
|
ULONG Reserved,
|
||||||
PCONTEXT Context)
|
PCONTEXT Context)
|
||||||
{
|
{
|
||||||
|
DbgPrint("KiUserApcDispatcher(ApcRoutine %x, ApcContext %x, Context %x)\n",
|
||||||
|
ApcRoutine, ApcContext, Context);
|
||||||
ApcRoutine(ApcContext,
|
ApcRoutine(ApcContext,
|
||||||
Iosb,
|
Iosb,
|
||||||
Reserved);;
|
Reserved);
|
||||||
|
DbgPrint("Done ApcRoutine, Context %x, Context->Eip %x\n",
|
||||||
|
Context, Context->Eip);
|
||||||
NtContinue(Context, 1);
|
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
|
# ReactOS Operating System
|
||||||
#
|
#
|
||||||
TARGET=midl
|
TARGET=midl
|
||||||
|
|
||||||
BASE_CFLAGS = -I../../include
|
CFLAGS =
|
||||||
|
|
||||||
CFLAGS = $(CFLAGS)
|
|
||||||
|
|
||||||
all: midl$(EXE_POSTFIX)
|
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 $
|
/*
|
||||||
*
|
* ReactOS kernel
|
||||||
* PROJECT: ReactOS kernel
|
* Copyright (C) 2000 David Welch <welch@cwcom.net>
|
||||||
* FILE: ntoskrnl/hal/x86/udelay.c
|
* Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
|
||||||
* PURPOSE: Busy waiting
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||||
* PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 06/11/99 Created
|
|
||||||
*
|
*
|
||||||
* This software is free software; you can redistribute it and/or
|
* This software is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
@ -23,6 +20,15 @@
|
||||||
* MA 02139, USA.
|
* 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 ***************************************************************/
|
/* INCLUDES ***************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ typedef struct _KTRAP_FRAME
|
||||||
PVOID DebugEbp;
|
PVOID DebugEbp;
|
||||||
PVOID DebugEip;
|
PVOID DebugEip;
|
||||||
PVOID DebugArgMark;
|
PVOID DebugArgMark;
|
||||||
|
PVOID DebugPointer;
|
||||||
PVOID TempCs;
|
PVOID TempCs;
|
||||||
PVOID TempEip;
|
PVOID TempEip;
|
||||||
PVOID Dr0;
|
PVOID Dr0;
|
||||||
|
|
|
@ -36,9 +36,9 @@ LdrpMapSystemDll (
|
||||||
PVOID * LdrStartupAddress
|
PVOID * LdrStartupAddress
|
||||||
);
|
);
|
||||||
PVOID
|
PVOID
|
||||||
LdrpGetSystemDllEntryPoint (
|
LdrpGetSystemDllEntryPoint (VOID);
|
||||||
VOID
|
PVOID
|
||||||
);
|
LdrpGetSystemDllApcDispatcher(VOID);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
LdrpMapImage (
|
LdrpMapImage (
|
||||||
HANDLE ProcessHandle,
|
HANDLE ProcessHandle,
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
/*
|
/*
|
||||||
* Defines for accessing KPCR and KTHREAD structure members
|
* Defines for accessing KPCR and KTHREAD structure members
|
||||||
*/
|
*/
|
||||||
|
#define KTHREAD_KERNEL_STACK 0x28
|
||||||
#define KTHREAD_PREVIOUS_MODE 0x137
|
#define KTHREAD_PREVIOUS_MODE 0x137
|
||||||
#define KTHREAD_TRAP_FRAME 0x128
|
#define KTHREAD_TRAP_FRAME 0x128
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,38 @@ VOID IopCompleteRequest1(struct _KAPC* Apc,
|
||||||
PVOID* SystemArgument2)
|
PVOID* SystemArgument2)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
|
CCHAR PriorityBoost;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
DPRINT("IopCompleteRequest1()\n");
|
DPRINT("IopCompleteRequest1()\n");
|
||||||
|
|
||||||
Irp = (PIRP)(*SystemArgument1);
|
Irp = (PIRP)(*SystemArgument1);
|
||||||
|
PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
(*SystemArgument1) = (PVOID)Irp->UserIosb;
|
(*SystemArgument1) = (PVOID)Irp->UserIosb;
|
||||||
(*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
|
(*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,
|
VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
|
||||||
|
@ -196,7 +221,7 @@ VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
|
||||||
UserApcRoutine = (PKNORMAL_ROUTINE)
|
UserApcRoutine = (PKNORMAL_ROUTINE)
|
||||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine;
|
Irp->Overlay.AsynchronousParameters.UserApcRoutine;
|
||||||
UserApcContext = (PVOID)
|
UserApcContext = (PVOID)
|
||||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine;
|
Irp->Overlay.AsynchronousParameters.UserApcContext;
|
||||||
KeInitializeApc(&Irp->Tail.Apc,
|
KeInitializeApc(&Irp->Tail.Apc,
|
||||||
Thread,
|
Thread,
|
||||||
0,
|
0,
|
||||||
|
@ -207,7 +232,7 @@ VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
|
||||||
UserApcContext);
|
UserApcContext);
|
||||||
KeInsertQueueApc(&Irp->Tail.Apc,
|
KeInsertQueueApc(&Irp->Tail.Apc,
|
||||||
Irp,
|
Irp,
|
||||||
NULL,
|
(PVOID)(LONG)PriorityBoost,
|
||||||
KernelMode);
|
KernelMode);
|
||||||
return;
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -40,8 +40,7 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
PDEVICE_OBJECT
|
PDEVICE_OBJECT STDCALL
|
||||||
STDCALL
|
|
||||||
IoGetDeviceToVerify (PETHREAD Thread)
|
IoGetDeviceToVerify (PETHREAD Thread)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Returns a pointer to the device, representing a removable-media
|
* FUNCTION: Returns a pointer to the device, representing a removable-media
|
||||||
|
@ -52,8 +51,7 @@ IoGetDeviceToVerify (PETHREAD Thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID STDCALL
|
||||||
STDCALL
|
|
||||||
IoFreeIrp (PIRP Irp)
|
IoFreeIrp (PIRP Irp)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Releases a caller allocated irp
|
* FUNCTION: Releases a caller allocated irp
|
||||||
|
@ -65,8 +63,7 @@ IoFreeIrp (PIRP Irp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIRP
|
PIRP STDCALL
|
||||||
STDCALL
|
|
||||||
IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
|
IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Allocates and initializes an irp to associated with a master irp
|
* FUNCTION: Allocates and initializes an irp to associated with a master irp
|
||||||
|
@ -83,8 +80,7 @@ IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID STDCALL
|
||||||
STDCALL
|
|
||||||
IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
|
IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Initalizes an irp allocated by the caller
|
* FUNCTION: Initalizes an irp allocated by the caller
|
||||||
|
@ -104,8 +100,7 @@ IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS FASTCALL
|
||||||
FASTCALL
|
|
||||||
IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Sends an IRP to the next lower driver
|
* FUNCTION: Sends an IRP to the next lower driver
|
||||||
|
@ -248,10 +243,9 @@ IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
|
||||||
IopCompleteRequest,
|
IopCompleteRequest,
|
||||||
NULL,
|
NULL,
|
||||||
(PKNORMAL_ROUTINE)
|
(PKNORMAL_ROUTINE)
|
||||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine,
|
NULL,
|
||||||
UserMode,
|
KernelMode,
|
||||||
(PVOID)
|
NULL);
|
||||||
Irp->Overlay.AsynchronousParameters.UserApcContext);
|
|
||||||
KeInsertQueueApc(&Irp->Tail.Apc,
|
KeInsertQueueApc(&Irp->Tail.Apc,
|
||||||
(PVOID)Irp,
|
(PVOID)Irp,
|
||||||
(PVOID)(ULONG)PriorityBoost,
|
(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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -88,16 +88,21 @@ NTSTATUS STDCALL NtReadFile(HANDLE FileHandle,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||||
{
|
{
|
||||||
KeInitializeEvent(&Event,
|
KeInitializeEvent(&Event,
|
||||||
NotificationEvent,
|
NotificationEvent,
|
||||||
FALSE);
|
FALSE);
|
||||||
ptrEvent = &Event;
|
ptrEvent = &Event;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptrEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||||
FileObject->DeviceObject,
|
FileObject->DeviceObject,
|
||||||
|
@ -126,10 +131,21 @@ NTSTATUS STDCALL NtReadFile(HANDLE FileHandle,
|
||||||
if ((Status == STATUS_PENDING) &&
|
if ((Status == STATUS_PENDING) &&
|
||||||
(FileObject->Flags & FO_SYNCHRONOUS_IO))
|
(FileObject->Flags & FO_SYNCHRONOUS_IO))
|
||||||
{
|
{
|
||||||
|
BOOLEAN Alertable;
|
||||||
|
|
||||||
|
if (FileObject->Flags & FO_ALERTABLE_IO)
|
||||||
|
{
|
||||||
|
Alertable = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Alertable = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
KeWaitForSingleObject(&Event,
|
KeWaitForSingleObject(&Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
Alertable,
|
||||||
NULL);
|
NULL);
|
||||||
Status = IoStatusBlock->Status;
|
Status = IoStatusBlock->Status;
|
||||||
}
|
}
|
||||||
|
@ -166,6 +182,7 @@ NTSTATUS STDCALL NtWriteFile(HANDLE FileHandle,
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION StackPtr;
|
PIO_STACK_LOCATION StackPtr;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
|
PKEVENT ptrEvent;
|
||||||
|
|
||||||
DPRINT("NtWriteFile(FileHandle %x, Buffer %x, Length %d)\n",
|
DPRINT("NtWriteFile(FileHandle %x, Buffer %x, Length %d)\n",
|
||||||
FileHandle, Buffer, Length);
|
FileHandle, Buffer, Length);
|
||||||
|
@ -185,7 +202,33 @@ NTSTATUS STDCALL NtWriteFile(HANDLE FileHandle,
|
||||||
{
|
{
|
||||||
ByteOffset = &FileObject->CurrentByteOffset;
|
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,
|
KeInitializeEvent(&Event,
|
||||||
NotificationEvent,
|
NotificationEvent,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
@ -194,7 +237,7 @@ NTSTATUS STDCALL NtWriteFile(HANDLE FileHandle,
|
||||||
Buffer,
|
Buffer,
|
||||||
Length,
|
Length,
|
||||||
ByteOffset,
|
ByteOffset,
|
||||||
&Event,
|
ptrEvent,
|
||||||
IoStatusBlock);
|
IoStatusBlock);
|
||||||
|
|
||||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
|
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
|
||||||
|
|
|
@ -17,10 +17,15 @@
|
||||||
#include <internal/i386/segment.h>
|
#include <internal/i386/segment.h>
|
||||||
#include <internal/ps.h>
|
#include <internal/ps.h>
|
||||||
#include <internal/ke.h>
|
#include <internal/ke.h>
|
||||||
|
#include <internal/ldr.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* NOTES *********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
KSPIN_LOCK PiApcLock;
|
KSPIN_LOCK PiApcLock;
|
||||||
|
@ -45,9 +50,16 @@ VOID KeCallKernelRoutineApc(PKAPC Apc)
|
||||||
DPRINT("Finished KeCallKernelRoutineApc()\n");
|
DPRINT("Finished KeCallKernelRoutineApc()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID KiRundownThread(VOID)
|
||||||
|
/*
|
||||||
|
* FUNCTION:
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN KiTestAlert(VOID)
|
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
|
* 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
|
* UserContext = The user context saved on entry to kernel mode
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PKAPC Apc;
|
PKAPC Apc;
|
||||||
PULONG Esp;
|
PULONG Esp;
|
||||||
|
PCONTEXT Context;
|
||||||
KIRQL oldlvl;
|
KIRQL oldlvl;
|
||||||
CONTEXT SavedContext;
|
|
||||||
ULONG Top;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
PETHREAD EThread;
|
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
|
|
||||||
DPRINT("KiDeliverUserApc(TrapFrame %x)\n", TrapFrame);
|
DPRINT("KiDeliverUserApc(TrapFrame %x/%x)\n", TrapFrame,
|
||||||
|
KeGetCurrentThread()->TrapFrame);
|
||||||
Thread = KeGetCurrentThread();
|
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);
|
KeReleaseSpinLock(&PiApcLock, oldlvl);
|
||||||
current_entry = Thread->ApcState.ApcListHead[1].Flink;
|
DbgPrint("KiDeliverUserApc called but no APC was pending\n");
|
||||||
|
return(FALSE);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
|
||||||
EThread = CONTAINING_RECORD(Thread, ETHREAD, Tcb);
|
EThread = CONTAINING_RECORD(Thread, ETHREAD, Tcb);
|
||||||
if (EThread->DeadThread)
|
if (EThread->DeadThread)
|
||||||
|
@ -147,6 +196,14 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
|
||||||
VOID STDCALL KiDeliverApc(ULONG Unknown1,
|
VOID STDCALL KiDeliverApc(ULONG Unknown1,
|
||||||
ULONG Unknown2,
|
ULONG Unknown2,
|
||||||
ULONG Unknown3)
|
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();
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
PLIST_ENTRY current;
|
PLIST_ENTRY current;
|
||||||
|
@ -217,8 +274,6 @@ VOID STDCALL KeInsertQueueApc (PKAPC Apc,
|
||||||
{
|
{
|
||||||
InsertTailList(&TargetThread->ApcState.ApcListHead[1],
|
InsertTailList(&TargetThread->ApcState.ApcListHead[1],
|
||||||
&Apc->ApcListEntry);
|
&Apc->ApcListEntry);
|
||||||
TargetThread->ApcState.KernelApcPending++;
|
|
||||||
TargetThread->ApcState.UserApcPending++;
|
|
||||||
}
|
}
|
||||||
Apc->Inserted = TRUE;
|
Apc->Inserted = TRUE;
|
||||||
|
|
||||||
|
@ -235,6 +290,7 @@ VOID STDCALL KeInsertQueueApc (PKAPC Apc,
|
||||||
|
|
||||||
DPRINT("Resuming thread for user APC\n");
|
DPRINT("Resuming thread for user APC\n");
|
||||||
|
|
||||||
|
TargetThread->ApcState.UserApcPending++;
|
||||||
Status = STATUS_USER_APC;
|
Status = STATUS_USER_APC;
|
||||||
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
|
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
|
||||||
STATUS_USER_APC);
|
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,
|
NTSTATUS STDCALL NtQueueApcThread(HANDLE ThreadHandle,
|
||||||
PKNORMAL_ROUTINE ApcRoutine,
|
PKNORMAL_ROUTINE ApcRoutine,
|
||||||
|
@ -321,8 +390,8 @@ NTSTATUS STDCALL NtQueueApcThread(HANDLE ThreadHandle,
|
||||||
KeInitializeApc(Apc,
|
KeInitializeApc(Apc,
|
||||||
&Thread->Tcb,
|
&Thread->Tcb,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NtQueueApcKernelRoutine,
|
||||||
NULL,
|
NtQueueApcRundownRoutine,
|
||||||
ApcRoutine,
|
ApcRoutine,
|
||||||
UserMode,
|
UserMode,
|
||||||
NormalContext);
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -170,7 +170,7 @@ new_serviceInRange:
|
||||||
movl %ebp,%esp
|
movl %ebp,%esp
|
||||||
|
|
||||||
/* Call the post system call hook and deliver any pending APCs */
|
/* Call the post system call hook and deliver any pending APCs */
|
||||||
pushl %esp
|
pushl %ebp
|
||||||
pushl %eax
|
pushl %eax
|
||||||
call _KiAfterSystemCallHook
|
call _KiAfterSystemCallHook
|
||||||
addl $8,%esp
|
addl $8,%esp
|
||||||
|
@ -251,9 +251,7 @@ new_done:
|
||||||
popl %ebx
|
popl %ebx
|
||||||
movl %ebx, %fs:KPCR_EXCEPTION_LIST
|
movl %ebx, %fs:KPCR_EXCEPTION_LIST
|
||||||
|
|
||||||
popl %ebx
|
popl %fs
|
||||||
movl %ebx, %fs
|
|
||||||
/* popl %fs */
|
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
popl %ebx
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -44,7 +44,8 @@ VOID KiSystemCallHook(ULONG Nr, ...)
|
||||||
|
|
||||||
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
|
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
|
||||||
{
|
{
|
||||||
if (KeGetCurrentThread()->ApcState.UserApcPending == 0)
|
if (KeGetCurrentThread()->ApcState.UserApcPending == 0 ||
|
||||||
|
TrapFrame->Cs == KERNEL_CS)
|
||||||
{
|
{
|
||||||
return(NtStatus);
|
return(NtStatus);
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,6 +397,7 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
|
||||||
if (Alertable && !IsListEmpty(&CurrentThread->ApcState.ApcListHead[1]))
|
if (Alertable && !IsListEmpty(&CurrentThread->ApcState.ApcListHead[1]))
|
||||||
{
|
{
|
||||||
DPRINT("Thread is alertable and user APCs are pending\n");
|
DPRINT("Thread is alertable and user APCs are pending\n");
|
||||||
|
KiTestAlert();
|
||||||
return(STATUS_USER_APC);
|
return(STATUS_USER_APC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +446,10 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
|
||||||
{
|
{
|
||||||
KeCancelTimer(&KeGetCurrentThread()->Timer);
|
KeCancelTimer(&KeGetCurrentThread()->Timer);
|
||||||
}
|
}
|
||||||
|
if (Status == STATUS_USER_APC)
|
||||||
|
{
|
||||||
|
KiTestAlert();
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("Returning from KeWaitForSingleObject()\n");
|
DPRINT("Returning from KeWaitForSingleObject()\n");
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -246,13 +246,12 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle,
|
||||||
/*
|
/*
|
||||||
* FIXME: retrieve the offset of the APC dispatcher from NTDLL
|
* FIXME: retrieve the offset of the APC dispatcher from NTDLL
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
RtlInitAnsiString (&ProcedureName,
|
RtlInitAnsiString (&ProcedureName,
|
||||||
"KiUserApcDispatcher");
|
"KiUserApcDispatcher");
|
||||||
Status = LdrGetProcedureAddress ((PVOID)ImageBase,
|
Status = LdrGetProcedureAddress ((PVOID)ImageBase,
|
||||||
&ProcedureName,
|
&ProcedureName,
|
||||||
0,
|
0,
|
||||||
(PULONG)&SystemDllApcDispatcher);
|
&SystemDllApcDispatcher);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status);
|
DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status);
|
||||||
|
@ -261,8 +260,6 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle,
|
||||||
ZwClose(NTDllSectionHandle);
|
ZwClose(NTDllSectionHandle);
|
||||||
return (Status);
|
return (Status);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
SystemDllApcDispatcher = NULL;
|
|
||||||
|
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
ObDereferenceObject(Process);
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -53,56 +53,6 @@ static PETHREAD CurrentThread = NULL;
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* 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)
|
PKTHREAD STDCALL KeGetCurrentThread(VOID)
|
||||||
{
|
{
|
||||||
return(&(CurrentThread->Tcb));
|
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,
|
ULONG PsFreezeThread(PETHREAD Thread,
|
||||||
PNTSTATUS Status,
|
PNTSTATUS Status,
|
||||||
UCHAR Alertable,
|
UCHAR Alertable,
|
||||||
|
@ -346,13 +277,8 @@ ULONG PsFreezeThread(PETHREAD Thread,
|
||||||
|
|
||||||
if (PsGetCurrentThread() != Thread)
|
if (PsGetCurrentThread() != Thread)
|
||||||
{
|
{
|
||||||
DPRINT("Suspending other\n");
|
DbgPrint("Suspending other\n");
|
||||||
if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
|
KeBugCheck(0);
|
||||||
{
|
|
||||||
RemoveEntryList(&Thread->Tcb.QueueListEntry);
|
|
||||||
}
|
|
||||||
Thread->Tcb.State = THREAD_STATE_FROZEN;
|
|
||||||
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -495,14 +421,6 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL NtGetContextThread (IN HANDLE ThreadHandle,
|
|
||||||
OUT PCONTEXT Context)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle,
|
NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
@ -511,6 +429,214 @@ NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle,
|
||||||
UNIMPLEMENTED;
|
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,
|
NTSTATUS STDCALL NtResumeThread (IN HANDLE ThreadHandle,
|
||||||
IN PULONG SuspendCount)
|
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,
|
NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
|
||||||
IN PULONG PreviousSuspendCount)
|
IN PULONG PreviousSuspendCount)
|
||||||
/*
|
/*
|
||||||
|
@ -561,12 +680,15 @@ NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
|
||||||
NTSTATUS STDCALL NtContinue(IN PCONTEXT Context,
|
NTSTATUS STDCALL NtContinue(IN PCONTEXT Context,
|
||||||
IN BOOLEAN TestAlert)
|
IN BOOLEAN TestAlert)
|
||||||
{
|
{
|
||||||
PULONG StackTop;
|
PKTRAP_FRAME TrapFrame;
|
||||||
|
|
||||||
StackTop = KeGetStackTopThread(PsGetCurrentThread());
|
|
||||||
|
|
||||||
memcpy(StackTop, Context, sizeof(CONTEXT));
|
|
||||||
|
|
||||||
|
TrapFrame = KeGetCurrentThread()->TrapFrame;
|
||||||
|
if (TrapFrame == NULL)
|
||||||
|
{
|
||||||
|
DbgPrint("NtContinue called but TrapFrame was NULL\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
KeContextToTrapFrame(Context, TrapFrame);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue