mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Kernel:
- apc.c: Fixed some bugs and used Dispatcher Lock. Simplified some functions and renamed/inlined others. - wait.c: Fixed some assumptions about Dispatcher Lock and Waiting/Alertability - process.c: Fully implemented KeStackAttachProcess and KeStackDetachProcess. Made all functions use PKPROCESS and not PEPROCESS. Memory Manager: Fixed calls to KeAttachProcess/DetachProcess to typecast PKPROCESS Process Manager: Removed call to empty function in apc.c svn path=/trunk/; revision=11622
This commit is contained in:
parent
0cc7d4d22d
commit
a9c33470e5
11 changed files with 327 additions and 300 deletions
|
@ -20,13 +20,14 @@ KeSaveFloatingPointState(
|
|||
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
|
||||
#endif
|
||||
|
||||
VOID STDCALL KeAttachProcess (struct _EPROCESS* Process);
|
||||
VOID STDCALL KeAttachProcess(struct _KPROCESS *Process);
|
||||
|
||||
VOID FASTCALL KiAcquireSpinLock(PKSPIN_LOCK SpinLock);
|
||||
|
||||
VOID FASTCALL KiReleaseSpinLock(PKSPIN_LOCK SpinLock);
|
||||
|
||||
VOID KeDrainApcQueue(VOID);
|
||||
|
||||
struct _KPROCESS* KeGetCurrentProcess(VOID);
|
||||
|
||||
/*
|
||||
|
|
|
@ -122,6 +122,24 @@ typedef struct _KAPC
|
|||
|
||||
#include <poppack.h>
|
||||
|
||||
#ifndef __USE_W32API
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _KAPC_STATE
|
||||
{
|
||||
LIST_ENTRY ApcListHead[2];
|
||||
struct _KPROCESS* Process;
|
||||
UCHAR KernelApcInProgress;
|
||||
UCHAR KernelApcPending;
|
||||
UCHAR UserApcPending;
|
||||
UCHAR Reserved;
|
||||
} KAPC_STATE, *PKAPC_STATE, *__restrict PRKAPC_STATE;
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#endif /* __USE_W32API */
|
||||
|
||||
typedef struct _KBUGCHECK_CALLBACK_RECORD
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
|
|
|
@ -96,6 +96,10 @@ VOID KiInitializeUserApc(IN PVOID Reserved,
|
|||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2);
|
||||
|
||||
VOID STDCALL KiAttachProcess(struct _KTHREAD *Thread, struct _KPROCESS *Process, KIRQL ApcLock, struct _KAPC_STATE *SavedApcState);
|
||||
|
||||
VOID STDCALL KiSwapProcess(struct _KPROCESS *NewProcess, struct _KPROCESS *OldProcess);
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
|
||||
|
@ -122,10 +126,10 @@ VOID KeInit2(VOID);
|
|||
|
||||
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
|
||||
|
||||
VOID FASTCALL
|
||||
KiSwapApcEnvironment(
|
||||
struct _KTHREAD* Thread,
|
||||
struct _KPROCESS* NewProcess);
|
||||
VOID
|
||||
STDCALL
|
||||
KiMoveApcState (PKAPC_STATE OldState,
|
||||
PKAPC_STATE NewState);
|
||||
|
||||
VOID
|
||||
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: ps.h,v 1.73 2004/11/10 02:50:59 ion Exp $
|
||||
/* $Id: ps.h,v 1.74 2004/11/11 22:23:52 ion Exp $
|
||||
*
|
||||
* FILE: ntoskrnl/ke/kthread.c
|
||||
* PURPOSE: Process manager definitions
|
||||
|
@ -53,24 +53,6 @@ extern HANDLE SystemProcessHandle;
|
|||
extern LCID PsDefaultThreadLocaleId;
|
||||
extern LCID PsDefaultSystemLocaleId;
|
||||
|
||||
#ifndef __USE_W32API
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _KAPC_STATE
|
||||
{
|
||||
LIST_ENTRY ApcListHead[2];
|
||||
struct _KPROCESS* Process;
|
||||
UCHAR KernelApcInProgress;
|
||||
UCHAR KernelApcPending;
|
||||
UCHAR UserApcPending;
|
||||
UCHAR Reserved;
|
||||
} KAPC_STATE, *PKAPC_STATE, *__restrict PRKAPC_STATE;
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#endif /* __USE_W32API */
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _KTHREAD
|
||||
|
|
|
@ -123,12 +123,12 @@ KeInsertQueueApc (PKAPC Apc,
|
|||
PLIST_ENTRY ApcListEntry;
|
||||
PKAPC QueuedApc;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
|
||||
"SystemArgument2 %x)\n",Apc,SystemArgument1,
|
||||
SystemArgument2);
|
||||
|
||||
/* FIXME: Implement Dispatcher Lock */
|
||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Get the Thread specified in the APC */
|
||||
Thread = Apc->Thread;
|
||||
|
@ -136,7 +136,7 @@ KeInsertQueueApc (PKAPC Apc,
|
|||
/* Make sure the thread allows APC Queues */
|
||||
if (Thread->ApcQueueable == FALSE) {
|
||||
DPRINT("Thread doesn't allow APC Queues\n");
|
||||
KeLowerIrql(OldIrql);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ KeInsertQueueApc (PKAPC Apc,
|
|||
|
||||
/* Don't do anything if the APC is already inserted */
|
||||
if (Apc->Inserted) {
|
||||
KeLowerIrql(OldIrql);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ KeInsertQueueApc (PKAPC Apc,
|
|||
}
|
||||
|
||||
/* Return Sucess if we are here */
|
||||
KeLowerIrql(OldIrql);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -226,10 +226,10 @@ KeRemoveQueueApc (PKAPC Apc)
|
|||
KIRQL OldIrql;
|
||||
PKTHREAD Thread = Apc->Thread;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
|
||||
|
||||
/* FIXME: Implement Dispatcher Lock */
|
||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
||||
|
||||
/* Remove it from the Queue if it's inserted */
|
||||
|
@ -247,13 +247,13 @@ KeRemoveQueueApc (PKAPC Apc)
|
|||
}
|
||||
} else {
|
||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||
KeLowerIrql(OldIrql);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Restore IRQL and Return */
|
||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||
KeLowerIrql(OldIrql);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
@ -269,9 +269,10 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
|||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
BOOLEAN OldState;
|
||||
|
||||
/* FIXME: Implement Dispatcher Lock */
|
||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
OldState = Thread->Alerted[(int)AlertMode];
|
||||
|
||||
|
@ -283,9 +284,8 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
|||
Thread->ApcState.UserApcPending = TRUE;
|
||||
}
|
||||
|
||||
/* FIXME: Implement Dispatcher Lock */
|
||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||
KeLowerIrql(OldIrql);
|
||||
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return OldState;
|
||||
}
|
||||
|
||||
|
@ -444,12 +444,25 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
|||
}
|
||||
}
|
||||
|
||||
VOID KiInitializeUserApc(IN PVOID Reserved,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKNORMAL_ROUTINE NormalRoutine,
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
VOID
|
||||
STDCALL
|
||||
KiFreeApcRoutine(PKAPC Apc,
|
||||
PKNORMAL_ROUTINE* NormalRoutine,
|
||||
PVOID* NormalContext,
|
||||
PVOID* SystemArgument1,
|
||||
PVOID* SystemArgument2)
|
||||
{
|
||||
/* Free the APC and do nothing else */
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
|
||||
VOID
|
||||
KiInitializeUserApc(IN PVOID Reserved,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKNORMAL_ROUTINE NormalRoutine,
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
/*
|
||||
* FUNCTION: Prepares the Context for a user mode APC through ntdll.dll
|
||||
*/
|
||||
|
@ -508,77 +521,87 @@ KeAreApcsDisabled(
|
|||
VOID
|
||||
)
|
||||
{
|
||||
return KeGetCurrentThread()->KernelApcDisable ? FALSE : TRUE;
|
||||
return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
NtQueueApcRundownRoutine(PKAPC Apc)
|
||||
{
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
NtQueueApcKernelRoutine(PKAPC Apc,
|
||||
PKNORMAL_ROUTINE* NormalRoutine,
|
||||
PVOID* NormalContext,
|
||||
PVOID* SystemArgument1,
|
||||
PVOID* SystemArgument2)
|
||||
{
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueueApcThread(HANDLE ThreadHandle,
|
||||
PKNORMAL_ROUTINE ApcRoutine,
|
||||
PVOID NormalContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
/*
|
||||
* FUNCTION:
|
||||
* This function is used to queue an APC from user-mode for the specified thread.
|
||||
* The thread must enter an alertable wait before the APC will be delivered.
|
||||
*
|
||||
* ARGUMENTS:
|
||||
* Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
|
||||
* ApcRoutine - Pointer to the APC Routine to call when the APC executes.
|
||||
* NormalContext - User-defined value to pass to the APC Routine
|
||||
* SystemArgument1 - User-defined value to pass to the APC Routine
|
||||
* SystemArgument2 - User-defined value to pass to the APC Routine
|
||||
*
|
||||
* RETURNS: NTSTATUS SUCCESS or Failure Code from included calls.
|
||||
*/
|
||||
{
|
||||
PKAPC Apc;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
PVOID ThreadVar;
|
||||
|
||||
ThreadVar = &Thread;
|
||||
PKAPC Apc;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Get ETHREAD from Handle */
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SET_CONTEXT,
|
||||
PsThreadType,
|
||||
KeGetPreviousMode(),
|
||||
(PVOID)&Thread,
|
||||
NULL);
|
||||
|
||||
/* Fail if the Handle is invalid for some reason */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* If this is a Kernel or System Thread, then fail */
|
||||
if (Thread->Tcb.Teb == NULL) {
|
||||
ObDereferenceObject(Thread);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_ALL_ACCESS, /* FIXME */
|
||||
PsThreadType,
|
||||
UserMode,
|
||||
&ThreadVar,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
/* Allocate an APC */
|
||||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
|
||||
if (Apc == NULL) {
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
|
||||
if (Apc == NULL)
|
||||
{
|
||||
/* Initialize and Queue */
|
||||
KeInitializeApc(Apc,
|
||||
&Thread->Tcb,
|
||||
OriginalApcEnvironment,
|
||||
KiFreeApcRoutine,
|
||||
NULL,
|
||||
ApcRoutine,
|
||||
UserMode,
|
||||
NormalContext);
|
||||
if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
} else {
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Dereference Thread and Return */
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
KeInitializeApc(Apc,
|
||||
&Thread->Tcb,
|
||||
OriginalApcEnvironment,
|
||||
NtQueueApcKernelRoutine,
|
||||
NtQueueApcRundownRoutine,
|
||||
ApcRoutine,
|
||||
UserMode,
|
||||
NormalContext);
|
||||
KeInsertQueueApc(Apc,
|
||||
SystemArgument1,
|
||||
SystemArgument2,
|
||||
IO_NO_INCREMENT);
|
||||
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_SUCCESS);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL NtTestAlert(VOID)
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTestAlert(VOID)
|
||||
{
|
||||
/* Check and Alert Thread if needed */
|
||||
if (KeTestAlertThread(KeGetPreviousMode())) {
|
||||
return STATUS_ALERTED;
|
||||
} else {
|
||||
|
@ -586,103 +609,31 @@ NTSTATUS STDCALL NtTestAlert(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
PiInitApcManagement(VOID)
|
||||
static inline VOID RepairList(PLIST_ENTRY Original,
|
||||
PLIST_ENTRY Copy,
|
||||
KPROCESSOR_MODE Mode)
|
||||
{
|
||||
/* Copy Source to Desination */
|
||||
if (IsListEmpty(&Original[(int)Mode])) {
|
||||
InitializeListHead(&Copy[(int)Mode]);
|
||||
} else {
|
||||
Copy[(int)Mode].Flink = Original[(int)Mode].Flink;
|
||||
Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
|
||||
Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
|
||||
Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, int Mode)
|
||||
VOID
|
||||
STDCALL
|
||||
KiMoveApcState (PKAPC_STATE OldState,
|
||||
PKAPC_STATE NewState)
|
||||
{
|
||||
if (IsListEmpty(&Original[Mode]))
|
||||
{
|
||||
InitializeListHead(&Copy[Mode]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy[Mode].Flink->Blink = &Copy[Mode];
|
||||
Copy[Mode].Blink->Flink = &Copy[Mode];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID FASTCALL
|
||||
KiSwapApcEnvironment(
|
||||
PKTHREAD Thread,
|
||||
PKPROCESS NewProcess)
|
||||
{
|
||||
if (Thread->ApcStateIndex == AttachedApcEnvironment)
|
||||
{
|
||||
/* NewProcess must be the same as in the original-environment */
|
||||
ASSERT(NewProcess == Thread->ApcStatePointer[OriginalApcEnvironment]->Process);
|
||||
|
||||
/*
|
||||
FIXME: Deliver any pending apc's queued to the attached environment before
|
||||
switching back to the original environment.
|
||||
This is not crucial thou, since i don't think we'll ever target apc's
|
||||
to attached environments (or?)...
|
||||
Remove the following asserts if implementing this.
|
||||
-Gunnar
|
||||
*/
|
||||
|
||||
/* we don't support targeting apc's at attached-environments (yet)... */
|
||||
ASSERT(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]));
|
||||
ASSERT(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]));
|
||||
ASSERT(Thread->ApcState.KernelApcInProgress == FALSE);
|
||||
ASSERT(Thread->ApcState.KernelApcPending == FALSE);
|
||||
ASSERT(Thread->ApcState.UserApcPending == FALSE);
|
||||
/* Restore backup of Original Environment */
|
||||
*NewState = *OldState;
|
||||
|
||||
/* restore backup of original environment */
|
||||
Thread->ApcState = Thread->SavedApcState;
|
||||
/* repair lists */
|
||||
RepairList(Thread->SavedApcState.ApcListHead, Thread->ApcState.ApcListHead,
|
||||
KernelMode);
|
||||
RepairList(Thread->SavedApcState.ApcListHead, Thread->ApcState.ApcListHead,
|
||||
UserMode);
|
||||
|
||||
/* update environment pointers */
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||
|
||||
/* update current-environment index */
|
||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||
}
|
||||
else if (Thread->ApcStateIndex == OriginalApcEnvironment)
|
||||
{
|
||||
/* backup original environment */
|
||||
Thread->SavedApcState = Thread->ApcState;
|
||||
/* repair lists */
|
||||
RepairList(Thread->ApcState.ApcListHead, Thread->SavedApcState.ApcListHead,
|
||||
KernelMode);
|
||||
RepairList(Thread->ApcState.ApcListHead, Thread->SavedApcState.ApcListHead,
|
||||
UserMode);
|
||||
|
||||
/*
|
||||
FIXME: Is it possible to target an apc to an attached environment even if the
|
||||
thread is not currently attached???? If so, then this is bougus since it
|
||||
reinitializes the attached apc environment then located in SavedApcState.
|
||||
-Gunnar
|
||||
*/
|
||||
|
||||
/* setup a fresh new attached environment */
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
|
||||
Thread->ApcState.Process = NewProcess;
|
||||
Thread->ApcState.KernelApcInProgress = FALSE;
|
||||
Thread->ApcState.KernelApcPending = FALSE;
|
||||
Thread->ApcState.UserApcPending = FALSE;
|
||||
|
||||
/* update environment pointers */
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->SavedApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
|
||||
|
||||
/* update current-environment index */
|
||||
Thread->ApcStateIndex = AttachedApcEnvironment;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Is this the correct bug code? */
|
||||
KEBUGCHECK(APC_INDEX_MISMATCH);
|
||||
}
|
||||
/* Repair Lists */
|
||||
RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
|
||||
RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: process.c,v 1.30 2004/10/17 03:43:26 ion Exp $
|
||||
/* $Id: process.c,v 1.31 2004/11/11 22:23:52 ion Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/process.c
|
||||
|
@ -38,79 +38,95 @@
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeAttachProcess (PEPROCESS Process)
|
||||
VOID
|
||||
STDCALL
|
||||
KeAttachProcess(PKPROCESS Process)
|
||||
{
|
||||
KIRQL oldlvl;
|
||||
PETHREAD CurrentThread;
|
||||
ULONG PageDir;
|
||||
|
||||
DPRINT("KeAttachProcess(Process %x)\n",Process);
|
||||
|
||||
CurrentThread = PsGetCurrentThread();
|
||||
|
||||
if (&CurrentThread->ThreadsProcess->Pcb != CurrentThread->Tcb.ApcState.Process)
|
||||
{
|
||||
DPRINT1("Invalid attach (thread is already attached)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
||||
}
|
||||
if (&Process->Pcb == CurrentThread->Tcb.ApcState.Process)
|
||||
{
|
||||
DPRINT1("Invalid attach (process is the same)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
||||
}
|
||||
|
||||
|
||||
/* The stack and the thread structure of the current process may be
|
||||
located in a page which is not present in the page directory of
|
||||
the process we're attaching to. That would lead to a page fault
|
||||
when this function returns. However, since the processor can't
|
||||
call the page fault handler 'cause it can't push EIP on the stack,
|
||||
this will show up as a stack fault which will crash the entire system.
|
||||
To prevent this, make sure the page directory of the process we're
|
||||
attaching to is up-to-date. */
|
||||
|
||||
MmUpdatePageDir(Process, (PVOID)CurrentThread->Tcb.StackLimit, MM_STACK_SIZE);
|
||||
MmUpdatePageDir(Process, (PVOID)CurrentThread, sizeof(ETHREAD));
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
||||
|
||||
KiSwapApcEnvironment(&CurrentThread->Tcb, &Process->Pcb);
|
||||
|
||||
CurrentThread->Tcb.ApcState.Process = &Process->Pcb;
|
||||
PageDir = Process->Pcb.DirectoryTableBase.u.LowPart;
|
||||
DPRINT("Switching process context to %x\n",PageDir);
|
||||
Ke386SetPageTableDirectory(PageDir);
|
||||
KeLowerIrql(oldlvl);
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
DPRINT("KeAttachProcess: %x\n", Process);
|
||||
|
||||
/* Lock Dispatcher */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Crash system if DPC is being executed! */
|
||||
if (KeIsExecutingDpc()) {
|
||||
DPRINT1("Invalid attach (Thread is executing a DPC!)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
||||
}
|
||||
|
||||
/* Check if the Target Process is already attached */
|
||||
if (Thread->ApcState.Process == Process || Thread->ApcStateIndex != OriginalApcEnvironment) {
|
||||
DPRINT("Process already Attached. Exitting\n");
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
} else {
|
||||
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeDetachProcess (VOID)
|
||||
VOID
|
||||
STDCALL
|
||||
KiAttachProcess(PKTHREAD Thread, PKPROCESS Process, KIRQL ApcLock, PRKAPC_STATE SavedApcState)
|
||||
{
|
||||
KIRQL oldlvl;
|
||||
PETHREAD CurrentThread;
|
||||
ULONG PageDir;
|
||||
|
||||
DPRINT("KiAttachProcess(Thread: %x, Process: %x, SavedApcState: %x\n", Thread, Process, SavedApcState);
|
||||
|
||||
DPRINT("KeDetachProcess()\n");
|
||||
|
||||
CurrentThread = PsGetCurrentThread();
|
||||
/* The stack and the thread structure of the current process may be
|
||||
located in a page which is not present in the page directory of
|
||||
the process we're attaching to. That would lead to a page fault
|
||||
when this function returns. However, since the processor can't
|
||||
call the page fault handler 'cause it can't push EIP on the stack,
|
||||
this will show up as a stack fault which will crash the entire system.
|
||||
To prevent this, make sure the page directory of the process we're
|
||||
attaching to is up-to-date. */
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
||||
|
||||
/* Increase Stack Count */
|
||||
Process->StackCount++;
|
||||
|
||||
/* Swap the APC Environment */
|
||||
KiMoveApcState(&Thread->ApcState, SavedApcState);
|
||||
|
||||
/* Reinitialize Apc State */
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
|
||||
Thread->ApcState.Process = Process;
|
||||
Thread->ApcState.KernelApcInProgress = FALSE;
|
||||
Thread->ApcState.KernelApcPending = FALSE;
|
||||
Thread->ApcState.UserApcPending = FALSE;
|
||||
|
||||
/* Update Environment Pointers if needed*/
|
||||
if (SavedApcState == &Thread->SavedApcState) {
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->SavedApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStateIndex = AttachedApcEnvironment;
|
||||
}
|
||||
|
||||
/* Swap the Processes */
|
||||
KiSwapProcess(Process, SavedApcState->Process);
|
||||
|
||||
/* Return to old IRQL*/
|
||||
KeReleaseDispatcherDatabaseLock(ApcLock);
|
||||
|
||||
DPRINT("KiAttachProcess Completed Sucesfully\n");
|
||||
}
|
||||
|
||||
if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
|
||||
{
|
||||
DPRINT1("Invalid detach (thread was not attached)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
||||
}
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
||||
VOID
|
||||
STDCALL
|
||||
KiSwapProcess(PKPROCESS NewProcess, PKPROCESS OldProcess)
|
||||
{
|
||||
//PKPCR Pcr = KeGetCurrentKpcr();
|
||||
|
||||
KiSwapApcEnvironment(&CurrentThread->Tcb, CurrentThread->Tcb.SavedApcState.Process);
|
||||
PageDir = CurrentThread->Tcb.ApcState.Process->DirectoryTableBase.u.LowPart;
|
||||
Ke386SetPageTableDirectory(PageDir);
|
||||
|
||||
KeLowerIrql(oldlvl);
|
||||
/* Do they have an LDT? */
|
||||
if ((NewProcess->LdtDescriptor) || (OldProcess->LdtDescriptor)) {
|
||||
/* FIXME : SWitch GDT/IDT */
|
||||
}
|
||||
DPRINT("Switching CR3 to: %x\n", NewProcess->DirectoryTableBase.u.LowPart);
|
||||
Ke386SetPageTableDirectory(NewProcess->DirectoryTableBase.u.LowPart);
|
||||
|
||||
/* FIXME: Set IopmOffset in TSS */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -136,10 +152,9 @@ KeStackAttachProcess (
|
|||
)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
Thread = KeGetCurrentThread();
|
||||
|
||||
/* Crash system if DPC is being executed! */
|
||||
if (KeIsExecutingDpc()) {
|
||||
|
@ -151,16 +166,53 @@ KeStackAttachProcess (
|
|||
if (Thread->ApcState.Process == Process) {
|
||||
ApcState->Process = (PKPROCESS)1; /* Meaning already attached to the same Process */
|
||||
} else {
|
||||
/* Check if the Current Thread is already attached */
|
||||
if (Thread->ApcStateIndex != 0) {
|
||||
KeAttachProcess((PEPROCESS)Process); /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
|
||||
/* Check if the Current Thread is already attached and call the Internal Function*/
|
||||
if (Thread->ApcStateIndex != OriginalApcEnvironment) {
|
||||
KiAttachProcess(Thread, Process, OldIrql, ApcState);
|
||||
} else {
|
||||
KeAttachProcess((PEPROCESS)Process);
|
||||
ApcState->Process = NULL; /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
|
||||
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
|
||||
ApcState->Process = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeDetachProcess (VOID)
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("KeDetachProcess()\n");
|
||||
|
||||
/* Get Current Thread and Lock */
|
||||
Thread = KeGetCurrentThread();
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Return to old IRQL*/
|
||||
/* Check if it's attached */
|
||||
DPRINT("Current ApcStateIndex: %x\n", Thread->ApcStateIndex);
|
||||
|
||||
if (Thread->ApcStateIndex == OriginalApcEnvironment) {
|
||||
DPRINT1("Invalid detach (thread was not attached)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
||||
}
|
||||
|
||||
/* Decrease Stack Count */
|
||||
Thread->ApcState.Process->StackCount--;
|
||||
|
||||
/* Restore the APC State */
|
||||
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
|
||||
Thread->SavedApcState.Process = NULL;
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||
|
||||
/* Swap Processes */
|
||||
KiSwapProcess(Thread->ApcState.Process, Thread->ApcState.Process);
|
||||
|
||||
/* Unlock Dispatcher */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
}
|
||||
|
||||
|
@ -175,7 +227,6 @@ KeUnstackDetachProcess (
|
|||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread;
|
||||
ULONG PageDir;
|
||||
|
||||
/* If the special "We tried to attach to the process already being attached to" flag is there, don't do anything */
|
||||
if (ApcState->Process == (PKPROCESS)1) return;
|
||||
|
@ -184,7 +235,7 @@ KeUnstackDetachProcess (
|
|||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Sorry Buddy, can't help you if you've got APCs or just aren't attached */
|
||||
if ((Thread->ApcStateIndex == 0) || (Thread->ApcState.KernelApcInProgress)) {
|
||||
if ((Thread->ApcStateIndex == OriginalApcEnvironment) || (Thread->ApcState.KernelApcInProgress)) {
|
||||
DPRINT1("Invalid detach (Thread not Attached, or Kernel APC in Progress!)\n");
|
||||
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
||||
}
|
||||
|
@ -196,15 +247,16 @@ KeUnstackDetachProcess (
|
|||
/* The ApcState parameter is useless, so use the saved data and reset it */
|
||||
RtlMoveMemory(&Thread->SavedApcState, &Thread->ApcState, sizeof(KAPC_STATE));
|
||||
Thread->SavedApcState.Process = NULL;
|
||||
Thread->ApcStateIndex = 0;
|
||||
Thread->ApcStatePointer[0] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
|
||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||
}
|
||||
|
||||
/* Do the Actual Swap */
|
||||
KiSwapApcEnvironment(Thread, Thread->SavedApcState.Process);
|
||||
PageDir = Thread->ApcState.Process->DirectoryTableBase.u.LowPart;
|
||||
Ke386SetPageTableDirectory(PageDir);
|
||||
/* Restore the APC State */
|
||||
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
|
||||
|
||||
/* Swap Processes */
|
||||
KiSwapProcess(Thread->ApcState.Process, Thread->ApcState.Process);
|
||||
|
||||
/* Return to old IRQL*/
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
|
|
@ -197,9 +197,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
|
|||
{
|
||||
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
|
||||
BOOLEAN WasWaiting = FALSE;
|
||||
KIRQL OldIrql;
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
|
||||
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
|
||||
if (WaitBlock != NULL)
|
||||
|
@ -223,8 +220,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
|
|||
{
|
||||
PsUnblockThread(Thread, &WaitStatus);
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
|
@ -542,15 +537,40 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are going to wait alertably and a user apc is pending
|
||||
* then return
|
||||
/* Alertability 101
|
||||
* ----------------
|
||||
* A Wait can either be Alertable, or Non-Alertable.
|
||||
* An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting
|
||||
* If an APC is Pending however, we must refuse an Alertable Wait. Such a wait would
|
||||
* be pointless since an APC is just about to be delivered.
|
||||
*
|
||||
* There are many ways to check if it's safe to be alertable, and these are the ones
|
||||
* that I could think of:
|
||||
* - The Thread is already Alerted. So someone beat us to the punch and we bail out.
|
||||
* - The Thread is Waiting in User-Mode, the APC Queue is not-empty.
|
||||
* It's defintely clear that we have incoming APCs, so we need to bail out and let the system
|
||||
* know that there are Pending User APCs (so they can be Delivered and maybe we can try again)
|
||||
*
|
||||
* Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there
|
||||
* are Pending User APCs, we should bail out, since APCs will be delivered any second.
|
||||
*/
|
||||
if (Alertable && KeTestAlertThread(KeGetPreviousMode()))
|
||||
{
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return (STATUS_USER_APC);
|
||||
}
|
||||
if (Alertable) {
|
||||
if (CurrentThread->Alerted[(int)WaitMode]) {
|
||||
CurrentThread->Alerted[(int)WaitMode] = FALSE;
|
||||
DPRINT("Alertability failed\n");
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return (STATUS_ALERTED);
|
||||
} else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) {
|
||||
DPRINT1("Alertability failed\n");
|
||||
CurrentThread->ApcState.UserApcPending = TRUE;
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return (STATUS_USER_APC);
|
||||
}
|
||||
} else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) {
|
||||
DPRINT1("Alertability failed\n");
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return (STATUS_USER_APC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the wait is (already) satisfied
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: page.c,v 1.75 2004/10/05 18:53:28 hbirr Exp $
|
||||
/* $Id: page.c,v 1.76 2004/11/11 22:23:52 ion Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/i386/page.c
|
||||
|
@ -375,7 +375,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
|
|||
|
||||
if (Process != NULL && Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Process);
|
||||
KeAttachProcess(&Process->Pcb);
|
||||
}
|
||||
|
||||
if (Ke386Pae)
|
||||
|
@ -408,7 +408,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
|
|||
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
|
||||
if (Process != NULL && Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Process);
|
||||
KeAttachProcess(&Process->Pcb);
|
||||
}
|
||||
if (Ke386Pae)
|
||||
{
|
||||
|
|
|
@ -453,7 +453,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
|||
if (AddressSpace->Process != NULL &&
|
||||
AddressSpace->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(AddressSpace->Process);
|
||||
KeAttachProcess((PKPROCESS)AddressSpace->Process);
|
||||
}
|
||||
EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length);
|
||||
for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: virtual.c,v 1.83 2004/10/29 16:48:10 chorns Exp $
|
||||
/* $Id: virtual.c,v 1.84 2004/11/11 22:23:52 ion Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/virtual.c
|
||||
|
@ -425,7 +425,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
|||
UserMode,
|
||||
IoWriteAccess);
|
||||
|
||||
KeAttachProcess(Process);
|
||||
KeAttachProcess((PKPROCESS)Process);
|
||||
|
||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
|
||||
|
@ -553,7 +553,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
|||
ObDereferenceObject(Process);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
KeAttachProcess(Process);
|
||||
KeAttachProcess((PKPROCESS)Process);
|
||||
|
||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: psmgr.c,v 1.23 2004/09/28 15:02:29 weiden Exp $
|
||||
/* $Id: psmgr.c,v 1.24 2004/11/11 22:23:52 ion Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -32,7 +32,6 @@ PiInitProcessManager(VOID)
|
|||
PsInitProcessManagment();
|
||||
PsInitThreadManagment();
|
||||
PsInitIdleThread();
|
||||
PiInitApcManagement();
|
||||
PsInitialiseSuspendImplementation();
|
||||
PsInitialiseW32Call();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue