3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: process.c,v 1.30 2004/10/17 03:43:26 ion Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/process.c
23 * PURPOSE: Microkernel process management
24 * PROGRAMMER: David Welch (welch@cwcom.net)
30 /* INCLUDES *****************************************************************/
34 #include <internal/debug.h>
36 /* FUNCTIONS *****************************************************************/
42 KeAttachProcess (PEPROCESS Process
)
45 PETHREAD CurrentThread
;
48 DPRINT("KeAttachProcess(Process %x)\n",Process
);
50 CurrentThread
= PsGetCurrentThread();
52 if (&CurrentThread
->ThreadsProcess
->Pcb
!= CurrentThread
->Tcb
.ApcState
.Process
)
54 DPRINT1("Invalid attach (thread is already attached)\n");
55 KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT
);
57 if (&Process
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
59 DPRINT1("Invalid attach (process is the same)\n");
60 KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT
);
64 /* The stack and the thread structure of the current process may be
65 located in a page which is not present in the page directory of
66 the process we're attaching to. That would lead to a page fault
67 when this function returns. However, since the processor can't
68 call the page fault handler 'cause it can't push EIP on the stack,
69 this will show up as a stack fault which will crash the entire system.
70 To prevent this, make sure the page directory of the process we're
71 attaching to is up-to-date. */
73 MmUpdatePageDir(Process
, (PVOID
)CurrentThread
->Tcb
.StackLimit
, MM_STACK_SIZE
);
74 MmUpdatePageDir(Process
, (PVOID
)CurrentThread
, sizeof(ETHREAD
));
76 KeRaiseIrql(DISPATCH_LEVEL
, &oldlvl
);
78 KiSwapApcEnvironment(&CurrentThread
->Tcb
, &Process
->Pcb
);
80 CurrentThread
->Tcb
.ApcState
.Process
= &Process
->Pcb
;
81 PageDir
= Process
->Pcb
.DirectoryTableBase
.u
.LowPart
;
82 DPRINT("Switching process context to %x\n",PageDir
);
83 Ke386SetPageTableDirectory(PageDir
);
91 KeDetachProcess (VOID
)
94 PETHREAD CurrentThread
;
97 DPRINT("KeDetachProcess()\n");
99 CurrentThread
= PsGetCurrentThread();
101 if (&CurrentThread
->ThreadsProcess
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
103 DPRINT1("Invalid detach (thread was not attached)\n");
104 KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT
);
107 KeRaiseIrql(DISPATCH_LEVEL
, &oldlvl
);
109 KiSwapApcEnvironment(&CurrentThread
->Tcb
, CurrentThread
->Tcb
.SavedApcState
.Process
);
110 PageDir
= CurrentThread
->Tcb
.ApcState
.Process
->DirectoryTableBase
.u
.LowPart
;
111 Ke386SetPageTableDirectory(PageDir
);
125 return KeGetCurrentThread()->ApcStateIndex
;
133 KeStackAttachProcess (
134 IN PKPROCESS Process
,
135 OUT PRKAPC_STATE ApcState
141 OldIrql
= KeAcquireDispatcherDatabaseLock();
142 Thread
= KeGetCurrentThread();
144 /* Crash system if DPC is being executed! */
145 if (KeIsExecutingDpc()) {
146 DPRINT1("Invalid attach (Thread is executing a DPC!)\n");
147 KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT
);
150 /* Check if the Target Process is already attached */
151 if (Thread
->ApcState
.Process
== Process
) {
152 ApcState
->Process
= (PKPROCESS
)1; /* Meaning already attached to the same Process */
154 /* Check if the Current Thread is already attached */
155 if (Thread
->ApcStateIndex
!= 0) {
156 KeAttachProcess((PEPROCESS
)Process
); /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
158 KeAttachProcess((PEPROCESS
)Process
);
159 ApcState
->Process
= NULL
; /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
163 /* Return to old IRQL*/
164 KeReleaseDispatcherDatabaseLock(OldIrql
);
172 KeUnstackDetachProcess (
173 IN PRKAPC_STATE ApcState
180 /* If the special "We tried to attach to the process already being attached to" flag is there, don't do anything */
181 if (ApcState
->Process
== (PKPROCESS
)1) return;
183 Thread
= KeGetCurrentThread();
184 OldIrql
= KeAcquireDispatcherDatabaseLock();
186 /* Sorry Buddy, can't help you if you've got APCs or just aren't attached */
187 if ((Thread
->ApcStateIndex
== 0) || (Thread
->ApcState
.KernelApcInProgress
)) {
188 DPRINT1("Invalid detach (Thread not Attached, or Kernel APC in Progress!)\n");
189 KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT
);
192 /* Restore the Old APC State if a Process was present */
193 if (ApcState
->Process
) {
194 RtlMoveMemory(ApcState
, &Thread
->ApcState
, sizeof(KAPC_STATE
));
196 /* The ApcState parameter is useless, so use the saved data and reset it */
197 RtlMoveMemory(&Thread
->SavedApcState
, &Thread
->ApcState
, sizeof(KAPC_STATE
));
198 Thread
->SavedApcState
.Process
= NULL
;
199 Thread
->ApcStateIndex
= 0;
200 Thread
->ApcStatePointer
[0] = &Thread
->ApcState
;
201 Thread
->ApcStatePointer
[1] = &Thread
->SavedApcState
;
204 /* Do the Actual Swap */
205 KiSwapApcEnvironment(Thread
, Thread
->SavedApcState
.Process
);
206 PageDir
= Thread
->ApcState
.Process
->DirectoryTableBase
.u
.LowPart
;
207 Ke386SetPageTableDirectory(PageDir
);
209 /* Return to old IRQL*/
210 KeReleaseDispatcherDatabaseLock(OldIrql
);