2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/procsup.c
5 * PURPOSE: CSR Process Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
10 /* INCLUDES *******************************************************************/
17 #define LOCK RtlEnterCriticalSection(&ProcessDataLock)
18 #define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
19 #define CsrHeap RtlGetProcessHeap()
21 #define CsrAcquireProcessLock() LOCK
22 #define CsrReleaseProcessLock() UNLOCK
24 /* GLOBALS ********************************************************************/
26 extern RTL_CRITICAL_SECTION ProcessDataLock
;
27 extern PCSRSS_PROCESS_DATA ProcessData
[256];
28 PCSRSS_PROCESS_DATA CsrRootProcess
;
29 LIST_ENTRY CsrThreadHashTable
[256];
30 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos
=
32 sizeof(SECURITY_QUALITY_OF_SERVICE
),
33 SecurityImpersonation
,
34 SECURITY_STATIC_TRACKING
,
38 /* FUNCTIONS ******************************************************************/
42 CsrSetToNormalPriority(VOID
)
44 KPRIORITY BasePriority
= (8 + 1) + 4;
46 /* Set the Priority */
47 NtSetInformationProcess(NtCurrentProcess(),
55 CsrSetToShutdownPriority(VOID
)
57 KPRIORITY SetBasePriority
= (8 + 1) + 6;
60 /* Get the shutdown privilege */
61 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
66 /* Set the Priority */
67 NtSetInformationProcess(NtCurrentProcess(),
76 CsrGetProcessLuid(HANDLE hProcess OPTIONAL
,
82 PTOKEN_STATISTICS TokenStats
;
84 /* Check if we have a handle to a CSR Process */
87 /* We don't, so try opening the Thread's Token */
88 Status
= NtOpenThreadToken(NtCurrentThread(),
93 /* Check for success */
94 if (!NT_SUCCESS(Status
))
96 /* If we got some other failure, then return and quit */
97 if (Status
!= STATUS_NO_TOKEN
) return Status
;
99 /* We don't have a Thread Token, use a Process Token */
100 hProcess
= NtCurrentProcess();
105 /* Check if we have a token by now */
108 /* No token yet, so open the Process Token */
109 Status
= NtOpenProcessToken(hProcess
,
112 if (!NT_SUCCESS(Status
))
114 /* Still no token, return the error */
119 /* Now get the size we'll need for the Token Information */
120 Status
= NtQueryInformationToken(hToken
,
126 /* Allocate memory for the Token Info */
127 if (!(TokenStats
= RtlAllocateHeap(CsrHeap
, 0, Length
)))
129 /* Fail and close the token */
131 return STATUS_NO_MEMORY
;
134 /* Now query the information */
135 Status
= NtQueryInformationToken(hToken
,
141 /* Close the handle */
144 /* Check for success */
145 if (NT_SUCCESS(Status
))
147 /* Return the LUID */
148 *Luid
= TokenStats
->AuthenticationId
;
151 /* Free the query information */
152 RtlFreeHeap(CsrHeap
, 0, TokenStats
);
154 /* Return the Status */
160 CsrImpersonateClient(IN PCSR_THREAD CsrThread
)
163 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
165 /* Use the current thread if none given */
166 if (!CsrThread
) CsrThread
= CurrentThread
;
168 /* Still no thread, something is wrong */
176 Status
= NtImpersonateThread(NtCurrentThread(),
177 CsrThread
->ThreadHandle
,
180 if (!NT_SUCCESS(Status
))
186 /* Increase the impersonation count for the current thread */
187 if (CurrentThread
) ++CurrentThread
->ImpersonationCount
;
195 CsrRevertToSelf(VOID
)
198 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
199 HANDLE ImpersonationToken
= NULL
;
201 /* Check if we have a Current Thread */
204 /* Make sure impersonation is on */
205 if (!CurrentThread
->ImpersonationCount
)
209 else if (--CurrentThread
->ImpersonationCount
> 0)
211 /* Success; impersonation count decreased but still not zero */
216 /* Impersonation has been totally removed, revert to ourselves */
217 Status
= NtSetInformationThread(NtCurrentThread(),
218 ThreadImpersonationToken
,
222 /* Return TRUE or FALSE */
223 return NT_SUCCESS(Status
);
228 FindProcessForShutdown(IN PLUID CallerLuid
)
231 PCSRSS_PROCESS_DATA CsrProcess
, ReturnCsrProcess
= NULL
;
235 LUID SystemLuid
= SYSTEM_LUID
;
236 BOOLEAN IsSystemLuid
= FALSE
, IsOurLuid
= FALSE
;
238 for (Hash
= 0; Hash
< (sizeof(ProcessData
) / sizeof(*ProcessData
)); Hash
++)
240 /* Get this process hash bucket */
241 CsrProcess
= ProcessData
[Hash
];
244 /* Skip this process if it's already been processed*/
245 if (CsrProcess
->Flags
& CsrProcessSkipShutdown
) goto Next
;
247 /* Get the LUID of this Process */
248 Status
= CsrGetProcessLuid(CsrProcess
->Process
, &ProcessLuid
);
250 /* Check if we didn't get access to the LUID */
251 if (Status
== STATUS_ACCESS_DENIED
)
253 /* FIXME:Check if we have any threads */
256 if (!NT_SUCCESS(Status
))
258 /* We didn't have access, so skip it */
259 CsrProcess
->Flags
|= CsrProcessSkipShutdown
;
263 /* Check if this is the System LUID */
264 if ((IsSystemLuid
= RtlEqualLuid(&ProcessLuid
, &SystemLuid
)))
266 /* Mark this process */
267 CsrProcess
->ShutdownFlags
|= CsrShutdownSystem
;
269 else if (!(IsOurLuid
= RtlEqualLuid(&ProcessLuid
, CallerLuid
)))
271 /* Our LUID doesn't match with the caller's */
272 CsrProcess
->ShutdownFlags
|= CsrShutdownOther
;
275 /* Check if we're past the previous level */
276 if (CsrProcess
->ShutdownLevel
> Level
)
278 /* Update the level */
279 Level
= CsrProcess
->ShutdownLevel
;
281 /* Set the final process */
282 ReturnCsrProcess
= CsrProcess
;
286 CsrProcess
= CsrProcess
->next
;
290 /* Check if we found a process */
291 if (ReturnCsrProcess
)
293 /* Skip this one next time */
294 ReturnCsrProcess
->Flags
|= CsrProcessSkipShutdown
;
297 return ReturnCsrProcess
;
300 /* This is really "CsrShutdownProcess", mostly */
303 CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc
,
306 PVOID
* RealContext
= (PVOID
*)Context
;
307 PLUID CallerLuid
= RealContext
[0];
308 PCSRSS_PROCESS_DATA CsrProcess
= NULL
;
309 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
314 /* Acquire process lock */
315 CsrAcquireProcessLock();
318 for (Hash
= 0; Hash
< (sizeof(ProcessData
) / sizeof(*ProcessData
)); Hash
++)
320 /* Get the Process */
321 CsrProcess
= ProcessData
[Hash
];
324 /* Remove the skip flag, set shutdown flags to 0*/
325 CsrProcess
->Flags
&= ~CsrProcessSkipShutdown
;
326 CsrProcess
->ShutdownFlags
= 0;
328 /* Move to the next */
329 CsrProcess
= CsrProcess
->next
;
333 /* Set shudown Priority */
334 CsrSetToShutdownPriority();
336 /* Loop all processes */
337 //DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart);
342 /* Find the next process to shutdown */
344 if (!(CsrProcess
= FindProcessForShutdown(CallerLuid
)))
347 CsrReleaseProcessLock();
348 Status
= STATUS_SUCCESS
;
353 /* Release the lock, make the callback, and acquire it back */
354 //DPRINT1("Found process: %lx\n", CsrProcess->ProcessId);
355 CsrReleaseProcessLock();
356 Result
= (ULONG
)EnumProc(CsrProcess
, (PVOID
)((ULONG_PTR
)Context
| FirstTry
));
357 CsrAcquireProcessLock();
359 /* Check the result */
360 //DPRINT1("Result: %d\n", Result);
361 if (Result
== CsrShutdownCsrProcess
)
363 /* The callback unlocked the process */
366 else if (Result
== CsrShutdownNonCsrProcess
)
368 /* A non-CSR process, the callback didn't touch it */
371 else if (Result
== CsrShutdownCancelled
)
373 /* Shutdown was cancelled, unlock and exit */
374 CsrReleaseProcessLock();
375 Status
= STATUS_CANCELLED
;
379 /* No matches during the first try, so loop again */
380 if (FirstTry
&& Result
== CsrShutdownNonCsrProcess
)
388 /* Return to normal priority */
389 CsrSetToNormalPriority();
395 CsrLockProcessByClientId(IN HANDLE Pid
,
396 OUT PCSRSS_PROCESS_DATA
*CsrProcess OPTIONAL
)
399 PCSRSS_PROCESS_DATA CurrentProcess
= NULL
;
400 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
402 /* Acquire the lock */
403 CsrAcquireProcessLock();
406 for (Hash
= 0; Hash
< (sizeof(ProcessData
) / sizeof(*ProcessData
)); Hash
++)
408 /* Get the Process */
409 CurrentProcess
= ProcessData
[Hash
];
410 while (CurrentProcess
)
412 /* Check for PID match */
413 if (CurrentProcess
->ProcessId
== Pid
)
415 /* Get out of here with success */
416 // DPRINT1("Found %p for PID %lx\n", CurrentProcess, Pid);
417 Status
= STATUS_SUCCESS
;
421 /* Move to the next */
422 CurrentProcess
= CurrentProcess
->next
;
426 /* Nothing found, release the lock */
428 if (!CurrentProcess
) CsrReleaseProcessLock();
430 /* Return the status and process */
431 if (CsrProcess
) *CsrProcess
= CurrentProcess
;
437 CsrUnlockProcess(IN PCSRSS_PROCESS_DATA CsrProcess
)
439 /* Dereference the process */
440 //CsrLockedDereferenceProcess(CsrProcess);
442 /* Release the lock and return */
443 CsrReleaseProcessLock();
444 return STATUS_SUCCESS
;