Commit in reactos on MAIN
include/ddk/kefuncs.h+2-11.47 -> 1.48
           /ketypes.h+181.50 -> 1.51
ntoskrnl/include/internal/ke.h+8-41.63 -> 1.64
                         /ps.h+1-191.73 -> 1.74
ntoskrnl/ke/apc.c+122-1711.67 -> 1.68
           /process.c+136-841.30 -> 1.31
           /wait.c+33-131.60 -> 1.61
ntoskrnl/mm/marea.c+1-11.70 -> 1.71
           /virtual.c+3-31.83 -> 1.84
ntoskrnl/mm/i386/page.c+3-31.75 -> 1.76
ntoskrnl/ps/psmgr.c+1-21.23 -> 1.24
+328-301
11 modified files
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

reactos/include/ddk
kefuncs.h 1.47 -> 1.48
diff -u -r1.47 -r1.48
--- kefuncs.h	10 Nov 2004 02:50:59 -0000	1.47
+++ kefuncs.h	11 Nov 2004 22:23:51 -0000	1.48
@@ -20,13 +20,14 @@
 #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);
 
 /*

reactos/include/ddk
ketypes.h 1.50 -> 1.51
diff -u -r1.50 -r1.51
--- ketypes.h	10 Nov 2004 02:50:59 -0000	1.50
+++ ketypes.h	11 Nov 2004 22:23:51 -0000	1.51
@@ -122,6 +122,24 @@
 
 #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;

reactos/ntoskrnl/include/internal
ke.h 1.63 -> 1.64
diff -u -r1.63 -r1.64
--- ke.h	10 Nov 2004 02:50:59 -0000	1.63
+++ ke.h	11 Nov 2004 22:23:52 -0000	1.64
@@ -96,6 +96,10 @@
 			 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 @@
 
 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);

reactos/ntoskrnl/include/internal
ps.h 1.73 -> 1.74
diff -u -r1.73 -r1.74
--- ps.h	10 Nov 2004 02:50:59 -0000	1.73
+++ ps.h	11 Nov 2004 22:23:52 -0000	1.74
@@ -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 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

reactos/ntoskrnl/ke
apc.c 1.67 -> 1.68
diff -u -r1.67 -r1.68
--- apc.c	10 Nov 2004 02:50:59 -0000	1.67
+++ apc.c	11 Nov 2004 22:23:52 -0000	1.68
@@ -123,12 +123,12 @@
 	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 @@
 	/* 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 @@
 
 	/* Don't do anything if the APC is already inserted */
 	if (Apc->Inserted) {
-		KeLowerIrql(OldIrql);	
+		KeReleaseDispatcherDatabaseLock(OldIrql);
 		return FALSE;
 	}
 	
@@ -208,7 +208,7 @@
 	}
 
 	/* Return Sucess if we are here */
-	KeLowerIrql(OldIrql);
+	KeReleaseDispatcherDatabaseLock(OldIrql);
 	return TRUE;
 }
 
@@ -226,10 +226,10 @@
 	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 @@
 		}
 	} 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 @@
 	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 @@
 		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 @@
 	}
 }
 
-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 @@
 	VOID
 	)
 {
- 	return KeGetCurrentThread()->KernelApcDisable ? FALSE : TRUE;
-}
-
-VOID STDCALL
-NtQueueApcRundownRoutine(PKAPC Apc)
-{
-   ExFreePool(Apc);
-}
-
-VOID STDCALL
-NtQueueApcKernelRoutine(PKAPC Apc,
-			PKNORMAL_ROUTINE* NormalRoutine,
-			PVOID* NormalContext,
-			PVOID* SystemArgument1,
-			PVOID* SystemArgument2)
-{
-   ExFreePool(Apc);
+ 	return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
 }
 
-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;
-   
-   Status = ObReferenceObjectByHandle(ThreadHandle,
-				      THREAD_ALL_ACCESS, /* FIXME */
-				      PsThreadType,
-				      UserMode,
-				      &ThreadVar,
-				      NULL);
-   if (!NT_SUCCESS(Status))
-     {
-	return(Status);
-     }
+	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;
+	}
    
-   Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
-   if (Apc == NULL)
-     {
-	ObDereferenceObject(Thread);
-	return(STATUS_NO_MEMORY);
-     }
+	/* Allocate an APC */
+	Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
+	if (Apc == NULL) {
+		ObDereferenceObject(Thread);
+		return(STATUS_NO_MEMORY);
+	}
    
-   KeInitializeApc(Apc,
-		   &Thread->Tcb,
-                   OriginalApcEnvironment,
-		   NtQueueApcKernelRoutine,
-		   NtQueueApcRundownRoutine,
-		   ApcRoutine,
-		   UserMode,
-		   NormalContext);
-   KeInsertQueueApc(Apc,
-		    SystemArgument1,
-		    SystemArgument2,
-		    IO_NO_INCREMENT);
+	/* 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;
+	}
    
-   ObDereferenceObject(Thread);
-   return(STATUS_SUCCESS);
+	/* Dereference Thread and Return */
+	ObDereferenceObject(Thread);
+	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 @@
 	}
 }
 
-VOID INIT_FUNCTION
-PiInitApcManagement(VOID)
-{
-}
-
-static VOID FASTCALL
-RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, int Mode)
-{
-  if (IsListEmpty(&Original[Mode]))
-    {
-      InitializeListHead(&Copy[Mode]);
-    }
-  else
-    {
-      Copy[Mode].Flink->Blink = &Copy[Mode];
-      Copy[Mode].Blink->Flink = &Copy[Mode];
-    }
+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];
+	}
 }
 
-
-VOID FASTCALL
-KiSwapApcEnvironment(
-  PKTHREAD Thread,
-  PKPROCESS NewProcess)
+VOID
+STDCALL
+KiMoveApcState (PKAPC_STATE OldState,
+		PKAPC_STATE NewState)
 {
-  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);
 }
 

reactos/ntoskrnl/ke
process.c 1.30 -> 1.31
diff -u -r1.30 -r1.31
--- process.c	17 Oct 2004 03:43:26 -0000	1.30
+++ process.c	11 Nov 2004 22:23:52 -0000	1.31
@@ -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("KeDetachProcess()\n");
-   
-   CurrentThread = PsGetCurrentThread();
-
-   if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
-     {
-	DPRINT1("Invalid detach (thread was not attached)\n");
-	KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
-     }
+  
+	DPRINT("KiAttachProcess(Thread: %x, Process: %x, SavedApcState: %x\n", Thread, Process, SavedApcState);
    
-   KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
+	/* 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");
+}
 
-   KiSwapApcEnvironment(&CurrentThread->Tcb, CurrentThread->Tcb.SavedApcState.Process);
-   PageDir = CurrentThread->Tcb.ApcState.Process->DirectoryTableBase.u.LowPart;
-   Ke386SetPageTableDirectory(PageDir);
+VOID
+STDCALL
+KiSwapProcess(PKPROCESS NewProcess, PKPROCESS OldProcess) 
+{
+	//PKPCR Pcr = KeGetCurrentKpcr();
 
-   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 @@
     )
 {
 	KIRQL OldIrql;
-	PKTHREAD Thread;
+	PKTHREAD Thread = KeGetCurrentThread();
 	
 	OldIrql = KeAcquireDispatcherDatabaseLock();
-	Thread = KeGetCurrentThread();
 	
 	/* Crash system if DPC is being executed! */
 	if (KeIsExecutingDpc()) {
@@ -151,16 +166,53 @@
 	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 @@
 {
 	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 @@
 	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 @@
 		/* 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);

reactos/ntoskrnl/ke
wait.c 1.60 -> 1.61
diff -u -r1.60 -r1.61
--- wait.c	10 Nov 2004 02:50:59 -0000	1.60
+++ wait.c	11 Nov 2004 22:23:52 -0000	1.61
@@ -197,9 +197,6 @@
 {
    PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
    BOOLEAN WasWaiting = FALSE;
-   KIRQL OldIrql;
-
-   OldIrql = KeAcquireDispatcherDatabaseLock ();
 
    WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
    if (WaitBlock != NULL)
@@ -223,8 +220,6 @@
      {
 	PsUnblockThread(Thread, &WaitStatus);
      }
-
-   KeReleaseDispatcherDatabaseLock (OldIrql);
 }
 
 static BOOLEAN
@@ -542,15 +537,40 @@
          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

reactos/ntoskrnl/mm
marea.c 1.70 -> 1.71
diff -u -r1.70 -r1.71
--- marea.c	22 Oct 2004 20:38:22 -0000	1.70
+++ marea.c	11 Nov 2004 22:23:52 -0000	1.71
@@ -453,7 +453,7 @@
    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)

reactos/ntoskrnl/mm
virtual.c 1.83 -> 1.84
diff -u -r1.83 -r1.84
--- virtual.c	29 Oct 2004 16:48:10 -0000	1.83
+++ virtual.c	11 Nov 2004 22:23:52 -0000	1.84
@@ -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 @@
                           UserMode,
                           IoWriteAccess);
 
-      KeAttachProcess(Process);
+      KeAttachProcess((PKPROCESS)Process);
 
       SystemAddress = MmGetSystemAddressForMdl(Mdl);
       memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
@@ -553,7 +553,7 @@
          ObDereferenceObject(Process);
          return(STATUS_NO_MEMORY);
       }
-      KeAttachProcess(Process);
+      KeAttachProcess((PKPROCESS)Process);
 
       SystemAddress = MmGetSystemAddressForMdl(Mdl);
       memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);

reactos/ntoskrnl/mm/i386
page.c 1.75 -> 1.76
diff -u -r1.75 -r1.76
--- page.c	5 Oct 2004 18:53:28 -0000	1.75
+++ page.c	11 Nov 2004 22:23:52 -0000	1.76
@@ -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 @@
 
    if (Process != NULL && Process != CurrentProcess)
    {
-      KeAttachProcess(Process);
+      KeAttachProcess(&Process->Pcb);
    }
 
    if (Ke386Pae)
@@ -408,7 +408,7 @@
    DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
    if (Process != NULL && Process != CurrentProcess)
    {
-      KeAttachProcess(Process);
+      KeAttachProcess(&Process->Pcb);
    }
    if (Ke386Pae)
    {

reactos/ntoskrnl/ps
psmgr.c 1.23 -> 1.24
diff -u -r1.23 -r1.24
--- psmgr.c	28 Sep 2004 15:02:29 -0000	1.23
+++ psmgr.c	11 Nov 2004 22:23:52 -0000	1.24
@@ -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 @@
    PsInitProcessManagment();
    PsInitThreadManagment();
    PsInitIdleThread();
-   PiInitApcManagement();
    PsInitialiseSuspendImplementation();
    PsInitialiseW32Call();
 }
CVSspam 0.2.8