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
printf("Returned from wait\n");
ZwClose(FileHandle);
printf("Program finished\n");
- for(;;);
return 0;
}
#
PATH_TO_TOP = ../..
+CFLAGS = -g
+
OBJECTS= ../common/crt0.o apc.o
PROGS= apc.exe
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,
DWORD LowPart;
LONG HighPart;
} u;
+#ifdef ANONYMOUSUNIONS
struct
{
DWORD LowPart;
LONG HighPart;
};
+#endif /* ANONYMOUSUNIONS */
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
DWORD LowPart;
DWORD HighPart;
} u;
+#ifdef ANONYMOUSUNIONS
struct
{
DWORD LowPart;
DWORD HighPart;
};
+#endif /* ANONYMOUSUNIONS */
ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;
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 {
-/* $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
}
-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;
-/* $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
}
-WINBOOL
-STDCALL
-TerminateThread (
- HANDLE hThread,
- DWORD dwExitCode
- )
+WINBOOL STDCALL
+TerminateThread (HANDLE hThread,
+ DWORD dwExitCode)
{
NTSTATUS errCode;
-; $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
;
DbgUiWaitStateChange@8
DbgUserBreakPoint@0
;KiRaiseUserExceptionDispatcher
-;KiUserApcDispatcher
+KiUserApcDispatcher
;KiUserCallbackDispatcher
;KiUserExceptionDispatcher
LdrAccessResource@16
-; $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
;
DbgUiWaitStateChange=DbgUiWaitStateChange@8
DbgUserBreakPoint=DbgUserBreakPoint@0
;KiRaiseUserExceptionDispatcher
-;KiUserApcDispatcher
+KiUserApcDispatcher=KiUserApcDispatcher@20
;KiUserCallbackDispatcher
;KiUserExceptionDispatcher
LdrAccessResource=LdrAccessResource@16
-/* $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
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");
}
+++ /dev/null
-RPC_STATUS RpcBindingFromStringBindingW(PWCHAR Binding,
- handle_t* BindingHandle)
-{
-
-}
-
-RPC_STATUS RpcBindingFromStringBindingA(PUCHAR Binding,
- handle_t BindingHandle)
-{
-}
+++ /dev/null
-/*
- *
- */
-
-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);
-}
-# $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)
+++ /dev/null
-/*
- *
- */
-
-/* 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)
-{
-
-}
-
-
+++ /dev/null
-/*
- *
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <windows.h>
-
-/* FUNCTIONS *****************************************************************/
-
-RPC_STATUS RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
-{
-}
-
-RPC_STATUS RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
-{
-}
-
-RPC_STATUS RpcRevertToSelf()
-{
-}
+++ /dev/null
-/*
- * 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)
-{
-}
-/* $Id: udelay.c,v 1.3 2000/10/07 13:41:50 dwelch Exp $
- *
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/hal/x86/udelay.c
- * PURPOSE: Busy waiting
- * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
- * UPDATE HISTORY:
- * 06/11/99 Created
+/*
+ * ReactOS kernel
+ * Copyright (C) 2000 David Welch <welch@cwcom.net>
+ * Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
+ * Copyright (C) 1991, 1992 Linus Torvalds
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* MA 02139, USA.
*
*/
+/* $Id: udelay.c,v 1.4 2000/10/11 20:50:33 dwelch Exp $
+ *
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/udelay.c
+ * PURPOSE: Busy waiting
+ * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
+ * UPDATE HISTORY:
+ * 06/11/99 Created
+ */
/* INCLUDES ***************************************************************/
PVOID DebugEbp;
PVOID DebugEip;
PVOID DebugArgMark;
+ PVOID DebugPointer;
PVOID TempCs;
PVOID TempEip;
PVOID Dr0;
PVOID * LdrStartupAddress
);
PVOID
-LdrpGetSystemDllEntryPoint (
- VOID
- );
+LdrpGetSystemDllEntryPoint (VOID);
+PVOID
+LdrpGetSystemDllApcDispatcher(VOID);
NTSTATUS
LdrpMapImage (
HANDLE ProcessHandle,
/*
* Defines for accessing KPCR and KTHREAD structure members
*/
+#define KTHREAD_KERNEL_STACK 0x28
#define KTHREAD_PREVIOUS_MODE 0x137
#define KTHREAD_TRAP_FRAME 0x128
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,
UserApcRoutine = (PKNORMAL_ROUTINE)
Irp->Overlay.AsynchronousParameters.UserApcRoutine;
UserApcContext = (PVOID)
- Irp->Overlay.AsynchronousParameters.UserApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext;
KeInitializeApc(&Irp->Tail.Apc,
Thread,
0,
UserApcContext);
KeInsertQueueApc(&Irp->Tail.Apc,
Irp,
- NULL,
+ (PVOID)(LONG)PriorityBoost,
KernelMode);
return;
}
-/* $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
/* FUNCTIONS ****************************************************************/
-PDEVICE_OBJECT
-STDCALL
+PDEVICE_OBJECT STDCALL
IoGetDeviceToVerify (PETHREAD Thread)
/*
* FUNCTION: Returns a pointer to the device, representing a removable-media
}
-VOID
-STDCALL
+VOID STDCALL
IoFreeIrp (PIRP Irp)
/*
* FUNCTION: Releases a caller allocated irp
}
-PIRP
-STDCALL
+PIRP STDCALL
IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
/*
* FUNCTION: Allocates and initializes an irp to associated with a master irp
}
-VOID
-STDCALL
+VOID STDCALL
IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
/*
* FUNCTION: Initalizes an irp allocated by the caller
}
-NTSTATUS
-FASTCALL
+NTSTATUS FASTCALL
IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* FUNCTION: Sends an IRP to the next lower driver
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,
-/* $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
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,
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;
}
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
KEVENT Event;
+ PKEVENT ptrEvent;
DPRINT("NtWriteFile(FileHandle %x, Buffer %x, Length %d)\n",
FileHandle, Buffer, Length);
{
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);
Buffer,
Length,
ByteOffset,
- &Event,
+ ptrEvent,
IoStatusBlock);
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
#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;
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
*/
{
* 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)
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;
{
InsertTailList(&TargetThread->ApcState.ApcListHead[1],
&Apc->ApcListEntry);
- TargetThread->ApcState.KernelApcPending++;
- TargetThread->ApcState.UserApcPending++;
}
Apc->Inserted = TRUE;
DPRINT("Resuming thread for user APC\n");
+ TargetThread->ApcState.UserApcPending++;
Status = STATUS_USER_APC;
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_USER_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,
KeInitializeApc(Apc,
&Thread->Tcb,
0,
- NULL,
- NULL,
+ NtQueueApcKernelRoutine,
+ NtQueueApcRundownRoutine,
ApcRoutine,
UserMode,
NormalContext);
-/* $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
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
popl %ebx
movl %ebx, %fs:KPCR_EXCEPTION_LIST
- popl %ebx
- movl %ebx, %fs
-/* popl %fs */
+ popl %fs
popl %edi
popl %esi
popl %ebx
-/* $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
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
{
- if (KeGetCurrentThread()->ApcState.UserApcPending == 0)
+ if (KeGetCurrentThread()->ApcState.UserApcPending == 0 ||
+ TrapFrame->Cs == KERNEL_CS)
{
return(NtStatus);
}
if (Alertable && !IsListEmpty(&CurrentThread->ApcState.ApcListHead[1]))
{
DPRINT("Thread is alertable and user APCs are pending\n");
+ KiTestAlert();
return(STATUS_USER_APC);
}
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
+ if (Status == STATUS_USER_APC)
+ {
+ KiTestAlert();
+ }
DPRINT("Returning from KeWaitForSingleObject()\n");
return Status;
/*
* 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);
ZwClose(NTDllSectionHandle);
return (Status);
}
-*/
- SystemDllApcDispatcher = NULL;
KeDetachProcess();
ObDereferenceObject(Process);
-/* $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
/* 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));
}
}
-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,
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
{
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,
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)
}
-NTSTATUS STDCALL NtSetContextThread (IN HANDLE ThreadHandle,
- IN PCONTEXT Context)
-{
- UNIMPLEMENTED;
-}
-
-
NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
IN PULONG PreviousSuspendCount)
/*
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);
}