[CSRSRV]: Move the new process/thread management functions into new, dedicated files. Export some of the functions, so that win32csr can use them by linking to csrsrv. Last change needed for barebones user-mode shutdown support.

svn path=/trunk/; revision=46052
This commit is contained in:
Sir Richard 2010-03-10 06:49:53 +00:00
parent 1cd9cb22ef
commit 34fa6fb97b
7 changed files with 778 additions and 699 deletions

View file

@ -15,298 +15,19 @@
#define LOCK RtlEnterCriticalSection(&ProcessDataLock)
#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
#define CsrAcquireProcessLock() LOCK
#define CsrReleaseProcessLock() UNLOCK
/* GLOBALS *******************************************************************/
static ULONG NrProcess;
static PCSRSS_PROCESS_DATA ProcessData[256];
PCSRSS_PROCESS_DATA ProcessData[256];
RTL_CRITICAL_SECTION ProcessDataLock;
extern PCSRSS_PROCESS_DATA CsrRootProcess;
extern LIST_ENTRY CsrThreadHashTable[256];
/* FUNCTIONS *****************************************************************/
#define CsrHeap RtlGetProcessHeap()
#define CsrHashThread(t) \
(HandleToUlong(t)&(256 - 1))
LIST_ENTRY CsrThreadHashTable[256];
PCSRSS_PROCESS_DATA CsrRootProcess;
PCSR_THREAD
NTAPI
CsrAllocateThread(IN PCSRSS_PROCESS_DATA CsrProcess)
{
PCSR_THREAD CsrThread;
/* Allocate the structure */
CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
if (!CsrThread) return(NULL);
/* Reference the Thread and Process */
CsrThread->ReferenceCount++;
// CsrProcess->ReferenceCount++;
/* Set the Parent Process */
CsrThread->Process = CsrProcess;
/* Return Thread */
return CsrThread;
}
PCSR_THREAD
NTAPI
CsrLocateThreadByClientId(OUT PCSRSS_PROCESS_DATA *Process OPTIONAL,
IN PCLIENT_ID ClientId)
{
ULONG i;
PLIST_ENTRY ListHead, NextEntry;
PCSR_THREAD FoundThread;
/* Hash the Thread */
i = CsrHashThread(ClientId->UniqueThread);
/* Set the list pointers */
ListHead = &CsrThreadHashTable[i];
NextEntry = ListHead->Flink;
/* Star the loop */
while (NextEntry != ListHead)
{
/* Get the thread */
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
/* Compare the CID */
if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
{
/* Match found, return the process */
*Process = FoundThread->Process;
/* Return thread too */
// DPRINT1("Found: %p %p\n", FoundThread, FoundThread->Process);
return FoundThread;
}
/* Next */
NextEntry = NextEntry->Flink;
}
/* Nothing found */
return NULL;
}
PCSR_THREAD
NTAPI
CsrLocateThreadInProcess(IN PCSRSS_PROCESS_DATA CsrProcess OPTIONAL,
IN PCLIENT_ID Cid)
{
PLIST_ENTRY ListHead, NextEntry;
PCSR_THREAD FoundThread = NULL;
/* Use the Root Process if none was specified */
if (!CsrProcess) CsrProcess = CsrRootProcess;
/* Save the List pointers */
// DPRINT1("Searching in: %p %d\n", CsrProcess, CsrProcess->ThreadCount);
ListHead = &CsrProcess->ThreadList;
NextEntry = ListHead->Flink;
/* Start the Loop */
while (NextEntry != ListHead)
{
/* Get Thread Entry */
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
/* Check for TID Match */
if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
/* Next entry */
NextEntry = NextEntry->Flink;
}
/* Return what we found */
// DPRINT1("Found: %p\n", FoundThread);
return FoundThread;
}
VOID
NTAPI
CsrInsertThread(IN PCSRSS_PROCESS_DATA Process,
IN PCSR_THREAD Thread)
{
ULONG i;
/* Insert it into the Regular List */
InsertTailList(&Process->ThreadList, &Thread->Link);
/* Increase Thread Count */
Process->ThreadCount++;
/* Hash the Thread */
i = CsrHashThread(Thread->ClientId.UniqueThread);
// DPRINT1("TID %lx HASH: %lx\n", Thread->ClientId.UniqueThread, i);
/* Insert it there too */
InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
}
#define CsrAcquireProcessLock() LOCK
#define CsrReleaseProcessLock() UNLOCK
VOID
NTAPI
CsrDeallocateThread(IN PCSR_THREAD CsrThread)
{
/* Free the process object from the heap */
RtlFreeHeap(CsrHeap, 0, CsrThread);
}
VOID
NTAPI
CsrRemoveThread(IN PCSR_THREAD CsrThread)
{
/* Remove it from the List */
RemoveEntryList(&CsrThread->Link);
/* Decreate the thread count of the process */
CsrThread->Process->ThreadCount--;
/* Remove it from the Hash List as well */
if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
/* Check if this is the last Thread */
if (!CsrThread->Process->ThreadCount)
{
/* Check if it's not already been marked for deletion */
if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
{
/* Let everyone know this process is about to lose the thread */
//CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
/* Reference the Process */
//CsrLockedDereferenceProcess(CsrThread->Process);
}
}
/* Mark the thread for deletion */
CsrThread->Flags |= CsrThreadInTermination;
}
VOID
NTAPI
CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
{
/* Remove this thread */
CsrRemoveThread(CsrThread);
/* Release the Process Lock */
//CsrReleaseProcessLock();
/* Close the NT Thread Handle */
if (CsrThread->ThreadHandle) NtClose(CsrThread->ThreadHandle);
/* De-allocate the CSR Thread Object */
CsrDeallocateThread(CsrThread);
/* Remove a reference from the process */
//CsrDereferenceProcess(CsrProcess);
}
NTSTATUS
NTAPI
CsrCreateThreadData(IN PCSRSS_PROCESS_DATA CsrProcess,
IN HANDLE hThread,
IN PCLIENT_ID ClientId)
{
NTSTATUS Status;
PCSR_THREAD CsrThread;
//PCSRSS_PROCESS_DATA CurrentProcess;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
CLIENT_ID CurrentCid;
KERNEL_USER_TIMES KernelTimes;
// DPRINT1("CSRSRV: %s called\n", __FUNCTION__);
/* Get the current thread and CID */
CurrentCid = CurrentThread->ClientId;
// DPRINT1("CALLER PID/TID: %lx/%lx\n", CurrentCid.UniqueProcess, CurrentCid.UniqueThread);
/* Acquire the Process Lock */
CsrAcquireProcessLock();
#if 0
/* Get the current Process and make sure the Thread is valid with this CID */
CurrentThread = CsrLocateThreadByClientId(&CurrentProcess,
&CurrentCid);
/* Something is wrong if we get an empty thread back */
if (!CurrentThread)
{
DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
CsrReleaseProcessLock();
return STATUS_THREAD_IS_TERMINATING;
}
#endif
/* Get the Thread Create Time */
Status = NtQueryInformationThread(hThread,
ThreadTimes,
(PVOID)&KernelTimes,
sizeof(KernelTimes),
NULL);
/* Allocate a CSR Thread Structure */
if (!(CsrThread = CsrAllocateThread(CsrProcess)))
{
DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
/* Save the data we have */
CsrThread->CreateTime = KernelTimes.CreateTime;
CsrThread->ClientId = *ClientId;
CsrThread->ThreadHandle = hThread;
CsrThread->Flags = 0;
/* Insert the Thread into the Process */
CsrInsertThread(CsrProcess, CsrThread);
/* Release the lock and return */
CsrReleaseProcessLock();
return STATUS_SUCCESS;
}
PCSR_THREAD
NTAPI
CsrAddStaticServerThread(IN HANDLE hThread,
IN PCLIENT_ID ClientId,
IN ULONG ThreadFlags)
{
PCSR_THREAD CsrThread;
/* Get the Lock */
CsrAcquireProcessLock();
/* Allocate the Server Thread */
if ((CsrThread = CsrAllocateThread(CsrRootProcess)))
{
/* Setup the Object */
// DPRINT1("New CSR thread created: %lx PID/TID: %lx/%lx\n", CsrThread, ClientId->UniqueProcess, ClientId->UniqueThread);
CsrThread->ThreadHandle = hThread;
CsrThread->ClientId = *ClientId;
CsrThread->Flags = ThreadFlags;
/* Insert it into the Thread List */
InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
/* Increment the thread count */
CsrRootProcess->ThreadCount++;
}
/* Release the Process Lock and return */
CsrReleaseProcessLock();
return CsrThread;
}
VOID WINAPI CsrInitProcessData(VOID)
{
ULONG i;
@ -477,409 +198,6 @@ NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
return STATUS_INVALID_PARAMETER;
}
VOID
NTAPI
CsrSetToNormalPriority(VOID)
{
KPRIORITY BasePriority = (8 + 1) + 4;
/* Set the Priority */
NtSetInformationProcess(NtCurrentProcess(),
ProcessBasePriority,
&BasePriority,
sizeof(KPRIORITY));
}
VOID
NTAPI
CsrSetToShutdownPriority(VOID)
{
KPRIORITY SetBasePriority = (8 + 1) + 6;
BOOLEAN Old;
/* Get the shutdown privilege */
if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
TRUE,
FALSE,
&Old)))
{
/* Set the Priority */
NtSetInformationProcess(NtCurrentProcess(),
ProcessBasePriority,
&SetBasePriority,
sizeof(KPRIORITY));
}
}
NTSTATUS
NTAPI
CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
PLUID Luid)
{
HANDLE hToken = NULL;
NTSTATUS Status;
ULONG Length;
PTOKEN_STATISTICS TokenStats;
/* Check if we have a handle to a CSR Process */
if (!hProcess)
{
/* We don't, so try opening the Thread's Token */
Status = NtOpenThreadToken(NtCurrentThread(),
TOKEN_QUERY,
FALSE,
&hToken);
/* Check for success */
if (!NT_SUCCESS(Status))
{
/* If we got some other failure, then return and quit */
if (Status != STATUS_NO_TOKEN) return Status;
/* We don't have a Thread Token, use a Process Token */
hProcess = NtCurrentProcess();
hToken = NULL;
}
}
/* Check if we have a token by now */
if (!hToken)
{
/* No token yet, so open the Process Token */
Status = NtOpenProcessToken(hProcess,
TOKEN_QUERY,
&hToken);
if (!NT_SUCCESS(Status))
{
/* Still no token, return the error */
return Status;
}
}
/* Now get the size we'll need for the Token Information */
Status = NtQueryInformationToken(hToken,
TokenStatistics,
NULL,
0,
&Length);
/* Allocate memory for the Token Info */
if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
{
/* Fail and close the token */
NtClose(hToken);
return STATUS_NO_MEMORY;
}
/* Now query the information */
Status = NtQueryInformationToken(hToken,
TokenStatistics,
TokenStats,
Length,
&Length);
/* Close the handle */
NtClose(hToken);
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Return the LUID */
*Luid = TokenStats->AuthenticationId;
}
/* Free the query information */
RtlFreeHeap(CsrHeap, 0, TokenStats);
/* Return the Status */
return Status;
}
SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
{
sizeof(SECURITY_QUALITY_OF_SERVICE),
SecurityImpersonation,
SECURITY_STATIC_TRACKING,
FALSE
};
BOOLEAN
NTAPI
CsrImpersonateClient(IN PCSR_THREAD CsrThread)
{
NTSTATUS Status;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
/* Use the current thread if none given */
if (!CsrThread) CsrThread = CurrentThread;
/* Still no thread, something is wrong */
if (!CsrThread)
{
/* Failure */
return FALSE;
}
/* Make the call */
Status = NtImpersonateThread(NtCurrentThread(),
CsrThread->ThreadHandle,
&CsrSecurityQos);
if (!NT_SUCCESS(Status))
{
/* Failure */
return FALSE;
}
/* Increase the impersonation count for the current thread */
if (CurrentThread) ++CurrentThread->ImpersonationCount;
/* Return Success */
return TRUE;
}
BOOLEAN
NTAPI
CsrRevertToSelf(VOID)
{
NTSTATUS Status;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
HANDLE ImpersonationToken = NULL;
/* Check if we have a Current Thread */
if (CurrentThread)
{
/* Make sure impersonation is on */
if (!CurrentThread->ImpersonationCount)
{
return FALSE;
}
else if (--CurrentThread->ImpersonationCount > 0)
{
/* Success; impersonation count decreased but still not zero */
return TRUE;
}
}
/* Impersonation has been totally removed, revert to ourselves */
Status = NtSetInformationThread(NtCurrentThread(),
ThreadImpersonationToken,
&ImpersonationToken,
sizeof(HANDLE));
/* Return TRUE or FALSE */
return NT_SUCCESS(Status);
}
PCSRSS_PROCESS_DATA
NTAPI
FindProcessForShutdown(IN PLUID CallerLuid)
{
ULONG Hash;
PCSRSS_PROCESS_DATA CsrProcess, ReturnCsrProcess = NULL;
NTSTATUS Status;
ULONG Level = 0;
LUID ProcessLuid;
LUID SystemLuid = SYSTEM_LUID;
BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE;
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get this process hash bucket */
CsrProcess = ProcessData[Hash];
while (CsrProcess)
{
/* Skip this process if it's already been processed*/
if (CsrProcess->Flags & CsrProcessSkipShutdown) goto Next;
/* Get the LUID of this Process */
Status = CsrGetProcessLuid(CsrProcess->Process, &ProcessLuid);
/* Check if we didn't get access to the LUID */
if (Status == STATUS_ACCESS_DENIED)
{
/* FIXME:Check if we have any threads */
}
if (!NT_SUCCESS(Status))
{
/* We didn't have access, so skip it */
CsrProcess->Flags |= CsrProcessSkipShutdown;
goto Next;
}
/* Check if this is the System LUID */
if ((IsSystemLuid = RtlEqualLuid(&ProcessLuid, &SystemLuid)))
{
/* Mark this process */
CsrProcess->ShutdownFlags |= CsrShutdownSystem;
}
else if (!(IsOurLuid = RtlEqualLuid(&ProcessLuid, CallerLuid)))
{
/* Our LUID doesn't match with the caller's */
CsrProcess->ShutdownFlags |= CsrShutdownOther;
}
/* Check if we're past the previous level */
if (CsrProcess->ShutdownLevel > Level)
{
/* Update the level */
Level = CsrProcess->ShutdownLevel;
/* Set the final process */
ReturnCsrProcess = CsrProcess;
}
Next:
/* Next process */
CsrProcess = CsrProcess->next;
}
}
/* Check if we found a process */
if (ReturnCsrProcess)
{
/* Skip this one next time */
ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
}
return ReturnCsrProcess;
}
/* This is really "CsrShutdownProcess", mostly */
NTSTATUS
WINAPI
CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc,
IN PVOID Context)
{
PVOID* RealContext = (PVOID*)Context;
PLUID CallerLuid = RealContext[0];
PCSRSS_PROCESS_DATA CsrProcess = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN FirstTry;
ULONG Result = 0;
ULONG Hash;
/* Acquire process lock */
CsrAcquireProcessLock();
/* Start the loop */
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get the Process */
CsrProcess = ProcessData[Hash];
while (CsrProcess)
{
/* Remove the skip flag, set shutdown flags to 0*/
CsrProcess->Flags &= ~CsrProcessSkipShutdown;
CsrProcess->ShutdownFlags = 0;
/* Move to the next */
CsrProcess = CsrProcess->next;
}
}
/* Set shudown Priority */
CsrSetToShutdownPriority();
/* Loop all processes */
DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart);
/* Start looping */
while (TRUE)
{
/* Find the next process to shutdown */
FirstTry = TRUE;
if (!(CsrProcess = FindProcessForShutdown(CallerLuid)))
{
/* Done, quit */
CsrReleaseProcessLock();
Status = STATUS_SUCCESS;
goto Quickie;
}
LoopAgain:
/* Release the lock, make the callback, and acquire it back */
DPRINT1("Found process: %lx\n", CsrProcess->ProcessId);
CsrReleaseProcessLock();
Result = (ULONG)EnumProc(CsrProcess, (PVOID)((ULONG_PTR)Context | FirstTry));
CsrAcquireProcessLock();
/* Check the result */
DPRINT1("Result: %d\n", Result);
if (Result == CsrShutdownCsrProcess)
{
/* The callback unlocked the process */
break;
}
else if (Result == CsrShutdownNonCsrProcess)
{
/* A non-CSR process, the callback didn't touch it */
//continue;
}
else if (Result == CsrShutdownCancelled)
{
/* Shutdown was cancelled, unlock and exit */
CsrReleaseProcessLock();
Status = STATUS_CANCELLED;
goto Quickie;
}
/* No matches during the first try, so loop again */
if (FirstTry && Result == CsrShutdownNonCsrProcess)
{
FirstTry = FALSE;
goto LoopAgain;
}
}
Quickie:
/* Return to normal priority */
CsrSetToNormalPriority();
return Status;
}
NTSTATUS
NTAPI
CsrLockProcessByClientId(IN HANDLE Pid,
OUT PCSRSS_PROCESS_DATA *CsrProcess OPTIONAL)
{
ULONG Hash;
PCSRSS_PROCESS_DATA CurrentProcess = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Acquire the lock */
CsrAcquireProcessLock();
/* Start the loop */
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get the Process */
CurrentProcess = ProcessData[Hash];
while (CurrentProcess)
{
/* Check for PID match */
if (CurrentProcess->ProcessId == Pid)
{
/* Get out of here with success */
// DPRINT1("Found %p for PID %lx\n", CurrentProcess, Pid);
Status = STATUS_SUCCESS;
goto Found;
}
/* Move to the next */
CurrentProcess = CurrentProcess->next;
}
}
/* Nothing found, release the lock */
Found:
if (!CurrentProcess) CsrReleaseProcessLock();
/* Return the status and process */
if (CsrProcess) *CsrProcess = CurrentProcess;
return Status;
}
/**********************************************************************
* CSRSS API
*********************************************************************/
@ -920,7 +238,7 @@ CSR_API(CsrCreateProcess)
return(STATUS_SUCCESS);
}
CSR_API(CsrCreateThread)
CSR_API(CsrSrvCreateThread)
{
PCSR_THREAD CurrentThread;
HANDLE ThreadHandle;
@ -979,7 +297,7 @@ CSR_API(CsrCreateThread)
Status = STATUS_SUCCESS; // hack
if (NT_SUCCESS(Status))
{
Status = CsrCreateThreadData(CsrProcess,
Status = CsrCreateThread(CsrProcess,
ThreadHandle,
&Request->Data.CreateThreadRequest.ClientId);
// DPRINT1("Create status: %lx\n", Status);

View file

@ -15,6 +15,8 @@
<file>user.c</file>
<file>wapi.c</file>
</directory>
<file>procsup.c</file>
<file>thredsup.c</file>
<file>init.c</file>
<pch>srv.h</pch>
</module>

View file

@ -1,9 +1,9 @@
;@ stdcall CsrAddStaticServerThread(ptr ptr long)
@ stdcall CsrAddStaticServerThread(ptr ptr long)
;@ stdcall CsrCallServerFromServer(ptr ptr)
;@ stdcall CsrConnectToUser()
;@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr)
;@ stdcall CsrCreateRemoteThread(ptr ptr)
;@ stdcall CsrCreateThread(ptr ptr ptr)
@ stdcall CsrCreateThread(ptr ptr ptr)
;@ stdcall CsrCreateWait(ptr ptr ptr ptr ptr ptr)
;@ stdcall CsrDebugProcess(ptr)
;@ stdcall CsrDebugProcessStop(ptr)
@ -13,23 +13,23 @@
;@ stdcall CsrDestroyProcess(ptr long)
;@ stdcall CsrDestroyThread(ptr)
;@ stdcall CsrExecServerThread(ptr long)
;@ stdcall CsrGetProcessLuid(ptr ptr)
;@ stdcall CsrImpersonateClient(ptr)
;@ stdcall CsrLockProcessByClientId(ptr ptr)
@ stdcall CsrGetProcessLuid(ptr ptr)
@ stdcall CsrImpersonateClient(ptr)
@ stdcall CsrLockProcessByClientId(ptr ptr)
;@ stdcall CsrLockThreadByClientId(ptr ptr)
;@ stdcall CsrMoveSatisfiedWait(ptr ptr)
;@ stdcall CsrNotifyWait(ptr long ptr ptr)
;@ stdcall CsrPopulateDosDevices()
;@ stdcall CsrQueryApiPort()
;@ stdcall CsrReferenceThread(ptr)
;@ stdcall CsrRevertToSelf()
@ stdcall CsrRevertToSelf()
@ stdcall CsrServerInitialization(long ptr)
;@ stdcall CsrSetBackgroundPriority(ptr)
;@ stdcall CsrSetCallingSpooler(long)
;@ stdcall CsrSetForegroundPriority(ptr)
;@ stdcall CsrShutdownProcesses(ptr long)
;@ stdcall CsrUnhandledExceptionFilter(ptr)
;@ stdcall CsrUnlockProcess(ptr)
@ stdcall CsrUnlockProcess(ptr)
;@ stdcall CsrUnlockThread(ptr)
;@ stdcall CsrValidateMessageBuffer(ptr ptr long long)
;@ stdcall CsrValidateMessageString(ptr ptr)

View file

@ -364,7 +364,7 @@ CsrpInitWin32Csr (int argc, char ** argv, char ** envp)
CSRSS_API_DEFINITION NativeDefinitions[] =
{
CSRSS_DEFINE_API(CREATE_PROCESS, CsrCreateProcess),
CSRSS_DEFINE_API(CREATE_THREAD, CsrCreateThread),
CSRSS_DEFINE_API(CREATE_THREAD, CsrSrvCreateThread),
CSRSS_DEFINE_API(TERMINATE_PROCESS, CsrTerminateProcess),
CSRSS_DEFINE_API(CONNECT_PROCESS, CsrConnectProcess),
CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),

View file

@ -0,0 +1,447 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CSR Sub System
* FILE: subsys/csr/csrsrv/procsup.c
* PURPOSE: CSR Process Management
* PROGRAMMERS: ReactOS Portable Systems Group
* Alex Ionescu
*/
/* INCLUDES *******************************************************************/
#include <srv.h>
#define NDEBUG
#include <debug.h>
#define LOCK RtlEnterCriticalSection(&ProcessDataLock)
#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
#define CsrHeap RtlGetProcessHeap()
#define CsrAcquireProcessLock() LOCK
#define CsrReleaseProcessLock() UNLOCK
/* GLOBALS ********************************************************************/
extern RTL_CRITICAL_SECTION ProcessDataLock;
extern PCSRSS_PROCESS_DATA ProcessData[256];
PCSRSS_PROCESS_DATA CsrRootProcess;
LIST_ENTRY CsrThreadHashTable[256];
SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
{
sizeof(SECURITY_QUALITY_OF_SERVICE),
SecurityImpersonation,
SECURITY_STATIC_TRACKING,
FALSE
};
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
CsrSetToNormalPriority(VOID)
{
KPRIORITY BasePriority = (8 + 1) + 4;
/* Set the Priority */
NtSetInformationProcess(NtCurrentProcess(),
ProcessBasePriority,
&BasePriority,
sizeof(KPRIORITY));
}
VOID
NTAPI
CsrSetToShutdownPriority(VOID)
{
KPRIORITY SetBasePriority = (8 + 1) + 6;
BOOLEAN Old;
/* Get the shutdown privilege */
if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
TRUE,
FALSE,
&Old)))
{
/* Set the Priority */
NtSetInformationProcess(NtCurrentProcess(),
ProcessBasePriority,
&SetBasePriority,
sizeof(KPRIORITY));
}
}
NTSTATUS
NTAPI
CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
PLUID Luid)
{
HANDLE hToken = NULL;
NTSTATUS Status;
ULONG Length;
PTOKEN_STATISTICS TokenStats;
/* Check if we have a handle to a CSR Process */
if (!hProcess)
{
/* We don't, so try opening the Thread's Token */
Status = NtOpenThreadToken(NtCurrentThread(),
TOKEN_QUERY,
FALSE,
&hToken);
/* Check for success */
if (!NT_SUCCESS(Status))
{
/* If we got some other failure, then return and quit */
if (Status != STATUS_NO_TOKEN) return Status;
/* We don't have a Thread Token, use a Process Token */
hProcess = NtCurrentProcess();
hToken = NULL;
}
}
/* Check if we have a token by now */
if (!hToken)
{
/* No token yet, so open the Process Token */
Status = NtOpenProcessToken(hProcess,
TOKEN_QUERY,
&hToken);
if (!NT_SUCCESS(Status))
{
/* Still no token, return the error */
return Status;
}
}
/* Now get the size we'll need for the Token Information */
Status = NtQueryInformationToken(hToken,
TokenStatistics,
NULL,
0,
&Length);
/* Allocate memory for the Token Info */
if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
{
/* Fail and close the token */
NtClose(hToken);
return STATUS_NO_MEMORY;
}
/* Now query the information */
Status = NtQueryInformationToken(hToken,
TokenStatistics,
TokenStats,
Length,
&Length);
/* Close the handle */
NtClose(hToken);
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Return the LUID */
*Luid = TokenStats->AuthenticationId;
}
/* Free the query information */
RtlFreeHeap(CsrHeap, 0, TokenStats);
/* Return the Status */
return Status;
}
BOOLEAN
NTAPI
CsrImpersonateClient(IN PCSR_THREAD CsrThread)
{
NTSTATUS Status;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
/* Use the current thread if none given */
if (!CsrThread) CsrThread = CurrentThread;
/* Still no thread, something is wrong */
if (!CsrThread)
{
/* Failure */
return FALSE;
}
/* Make the call */
Status = NtImpersonateThread(NtCurrentThread(),
CsrThread->ThreadHandle,
&CsrSecurityQos);
if (!NT_SUCCESS(Status))
{
/* Failure */
return FALSE;
}
/* Increase the impersonation count for the current thread */
if (CurrentThread) ++CurrentThread->ImpersonationCount;
/* Return Success */
return TRUE;
}
BOOLEAN
NTAPI
CsrRevertToSelf(VOID)
{
NTSTATUS Status;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
HANDLE ImpersonationToken = NULL;
/* Check if we have a Current Thread */
if (CurrentThread)
{
/* Make sure impersonation is on */
if (!CurrentThread->ImpersonationCount)
{
return FALSE;
}
else if (--CurrentThread->ImpersonationCount > 0)
{
/* Success; impersonation count decreased but still not zero */
return TRUE;
}
}
/* Impersonation has been totally removed, revert to ourselves */
Status = NtSetInformationThread(NtCurrentThread(),
ThreadImpersonationToken,
&ImpersonationToken,
sizeof(HANDLE));
/* Return TRUE or FALSE */
return NT_SUCCESS(Status);
}
PCSRSS_PROCESS_DATA
NTAPI
FindProcessForShutdown(IN PLUID CallerLuid)
{
ULONG Hash;
PCSRSS_PROCESS_DATA CsrProcess, ReturnCsrProcess = NULL;
NTSTATUS Status;
ULONG Level = 0;
LUID ProcessLuid;
LUID SystemLuid = SYSTEM_LUID;
BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE;
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get this process hash bucket */
CsrProcess = ProcessData[Hash];
while (CsrProcess)
{
/* Skip this process if it's already been processed*/
if (CsrProcess->Flags & CsrProcessSkipShutdown) goto Next;
/* Get the LUID of this Process */
Status = CsrGetProcessLuid(CsrProcess->Process, &ProcessLuid);
/* Check if we didn't get access to the LUID */
if (Status == STATUS_ACCESS_DENIED)
{
/* FIXME:Check if we have any threads */
}
if (!NT_SUCCESS(Status))
{
/* We didn't have access, so skip it */
CsrProcess->Flags |= CsrProcessSkipShutdown;
goto Next;
}
/* Check if this is the System LUID */
if ((IsSystemLuid = RtlEqualLuid(&ProcessLuid, &SystemLuid)))
{
/* Mark this process */
CsrProcess->ShutdownFlags |= CsrShutdownSystem;
}
else if (!(IsOurLuid = RtlEqualLuid(&ProcessLuid, CallerLuid)))
{
/* Our LUID doesn't match with the caller's */
CsrProcess->ShutdownFlags |= CsrShutdownOther;
}
/* Check if we're past the previous level */
if (CsrProcess->ShutdownLevel > Level)
{
/* Update the level */
Level = CsrProcess->ShutdownLevel;
/* Set the final process */
ReturnCsrProcess = CsrProcess;
}
Next:
/* Next process */
CsrProcess = CsrProcess->next;
}
}
/* Check if we found a process */
if (ReturnCsrProcess)
{
/* Skip this one next time */
ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
}
return ReturnCsrProcess;
}
/* This is really "CsrShutdownProcess", mostly */
NTSTATUS
WINAPI
CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc,
IN PVOID Context)
{
PVOID* RealContext = (PVOID*)Context;
PLUID CallerLuid = RealContext[0];
PCSRSS_PROCESS_DATA CsrProcess = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN FirstTry;
ULONG Result = 0;
ULONG Hash;
/* Acquire process lock */
CsrAcquireProcessLock();
/* Start the loop */
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get the Process */
CsrProcess = ProcessData[Hash];
while (CsrProcess)
{
/* Remove the skip flag, set shutdown flags to 0*/
CsrProcess->Flags &= ~CsrProcessSkipShutdown;
CsrProcess->ShutdownFlags = 0;
/* Move to the next */
CsrProcess = CsrProcess->next;
}
}
/* Set shudown Priority */
CsrSetToShutdownPriority();
/* Loop all processes */
//DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart);
/* Start looping */
while (TRUE)
{
/* Find the next process to shutdown */
FirstTry = TRUE;
if (!(CsrProcess = FindProcessForShutdown(CallerLuid)))
{
/* Done, quit */
CsrReleaseProcessLock();
Status = STATUS_SUCCESS;
goto Quickie;
}
LoopAgain:
/* Release the lock, make the callback, and acquire it back */
//DPRINT1("Found process: %lx\n", CsrProcess->ProcessId);
CsrReleaseProcessLock();
Result = (ULONG)EnumProc(CsrProcess, (PVOID)((ULONG_PTR)Context | FirstTry));
CsrAcquireProcessLock();
/* Check the result */
//DPRINT1("Result: %d\n", Result);
if (Result == CsrShutdownCsrProcess)
{
/* The callback unlocked the process */
break;
}
else if (Result == CsrShutdownNonCsrProcess)
{
/* A non-CSR process, the callback didn't touch it */
//continue;
}
else if (Result == CsrShutdownCancelled)
{
/* Shutdown was cancelled, unlock and exit */
CsrReleaseProcessLock();
Status = STATUS_CANCELLED;
goto Quickie;
}
/* No matches during the first try, so loop again */
if (FirstTry && Result == CsrShutdownNonCsrProcess)
{
FirstTry = FALSE;
goto LoopAgain;
}
}
Quickie:
/* Return to normal priority */
CsrSetToNormalPriority();
return Status;
}
NTSTATUS
NTAPI
CsrLockProcessByClientId(IN HANDLE Pid,
OUT PCSRSS_PROCESS_DATA *CsrProcess OPTIONAL)
{
ULONG Hash;
PCSRSS_PROCESS_DATA CurrentProcess = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Acquire the lock */
CsrAcquireProcessLock();
/* Start the loop */
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
{
/* Get the Process */
CurrentProcess = ProcessData[Hash];
while (CurrentProcess)
{
/* Check for PID match */
if (CurrentProcess->ProcessId == Pid)
{
/* Get out of here with success */
// DPRINT1("Found %p for PID %lx\n", CurrentProcess, Pid);
Status = STATUS_SUCCESS;
goto Found;
}
/* Move to the next */
CurrentProcess = CurrentProcess->next;
}
}
/* Nothing found, release the lock */
Found:
if (!CurrentProcess) CsrReleaseProcessLock();
/* Return the status and process */
if (CsrProcess) *CsrProcess = CurrentProcess;
return Status;
}
NTSTATUS
NTAPI
CsrUnlockProcess(IN PCSRSS_PROCESS_DATA CsrProcess)
{
/* Dereference the process */
//CsrLockedDereferenceProcess(CsrProcess);
/* Release the lock and return */
CsrReleaseProcessLock();
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,306 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CSR Sub System
* FILE: subsys/csr/csrsrv/procsup.c
* PURPOSE: CSR Process Management
* PROGRAMMERS: ReactOS Portable Systems Group
* Alex Ionescu
*/
/* INCLUDES *******************************************************************/
#include <srv.h>
#define NDEBUG
#include <debug.h>
#define LOCK RtlEnterCriticalSection(&ProcessDataLock)
#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
#define CsrHeap RtlGetProcessHeap()
#define CsrHashThread(t) \
(HandleToUlong(t)&(256 - 1))
#define CsrAcquireProcessLock() LOCK
#define CsrReleaseProcessLock() UNLOCK
/* GLOBALS ********************************************************************/
LIST_ENTRY CsrThreadHashTable[256];
extern PCSRSS_PROCESS_DATA CsrRootProcess;
extern RTL_CRITICAL_SECTION ProcessDataLock;
extern PCSRSS_PROCESS_DATA ProcessData[256];
/* FUNCTIONS ******************************************************************/
PCSR_THREAD
NTAPI
CsrAllocateThread(IN PCSRSS_PROCESS_DATA CsrProcess)
{
PCSR_THREAD CsrThread;
/* Allocate the structure */
CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
if (!CsrThread) return(NULL);
/* Reference the Thread and Process */
CsrThread->ReferenceCount++;
// CsrProcess->ReferenceCount++;
/* Set the Parent Process */
CsrThread->Process = CsrProcess;
/* Return Thread */
return CsrThread;
}
PCSR_THREAD
NTAPI
CsrLocateThreadByClientId(OUT PCSRSS_PROCESS_DATA *Process OPTIONAL,
IN PCLIENT_ID ClientId)
{
ULONG i;
PLIST_ENTRY ListHead, NextEntry;
PCSR_THREAD FoundThread;
/* Hash the Thread */
i = CsrHashThread(ClientId->UniqueThread);
/* Set the list pointers */
ListHead = &CsrThreadHashTable[i];
NextEntry = ListHead->Flink;
/* Star the loop */
while (NextEntry != ListHead)
{
/* Get the thread */
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
/* Compare the CID */
if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
{
/* Match found, return the process */
*Process = FoundThread->Process;
/* Return thread too */
// DPRINT1("Found: %p %p\n", FoundThread, FoundThread->Process);
return FoundThread;
}
/* Next */
NextEntry = NextEntry->Flink;
}
/* Nothing found */
return NULL;
}
PCSR_THREAD
NTAPI
CsrLocateThreadInProcess(IN PCSRSS_PROCESS_DATA CsrProcess OPTIONAL,
IN PCLIENT_ID Cid)
{
PLIST_ENTRY ListHead, NextEntry;
PCSR_THREAD FoundThread = NULL;
/* Use the Root Process if none was specified */
if (!CsrProcess) CsrProcess = CsrRootProcess;
/* Save the List pointers */
// DPRINT1("Searching in: %p %d\n", CsrProcess, CsrProcess->ThreadCount);
ListHead = &CsrProcess->ThreadList;
NextEntry = ListHead->Flink;
/* Start the Loop */
while (NextEntry != ListHead)
{
/* Get Thread Entry */
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
/* Check for TID Match */
if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
/* Next entry */
NextEntry = NextEntry->Flink;
}
/* Return what we found */
// DPRINT1("Found: %p\n", FoundThread);
return FoundThread;
}
VOID
NTAPI
CsrInsertThread(IN PCSRSS_PROCESS_DATA Process,
IN PCSR_THREAD Thread)
{
ULONG i;
/* Insert it into the Regular List */
InsertTailList(&Process->ThreadList, &Thread->Link);
/* Increase Thread Count */
Process->ThreadCount++;
/* Hash the Thread */
i = CsrHashThread(Thread->ClientId.UniqueThread);
// DPRINT1("TID %lx HASH: %lx\n", Thread->ClientId.UniqueThread, i);
/* Insert it there too */
InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
}
VOID
NTAPI
CsrDeallocateThread(IN PCSR_THREAD CsrThread)
{
/* Free the process object from the heap */
RtlFreeHeap(CsrHeap, 0, CsrThread);
}
VOID
NTAPI
CsrRemoveThread(IN PCSR_THREAD CsrThread)
{
/* Remove it from the List */
RemoveEntryList(&CsrThread->Link);
/* Decreate the thread count of the process */
CsrThread->Process->ThreadCount--;
/* Remove it from the Hash List as well */
if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
/* Check if this is the last Thread */
if (!CsrThread->Process->ThreadCount)
{
/* Check if it's not already been marked for deletion */
if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
{
/* Let everyone know this process is about to lose the thread */
//CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
/* Reference the Process */
//CsrLockedDereferenceProcess(CsrThread->Process);
}
}
/* Mark the thread for deletion */
CsrThread->Flags |= CsrThreadInTermination;
}
VOID
NTAPI
CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
{
/* Remove this thread */
CsrRemoveThread(CsrThread);
/* Release the Process Lock */
//CsrReleaseProcessLock();
/* Close the NT Thread Handle */
if (CsrThread->ThreadHandle) NtClose(CsrThread->ThreadHandle);
/* De-allocate the CSR Thread Object */
CsrDeallocateThread(CsrThread);
/* Remove a reference from the process */
//CsrDereferenceProcess(CsrProcess);
}
NTSTATUS
NTAPI
CsrCreateThread(IN PCSRSS_PROCESS_DATA CsrProcess,
IN HANDLE hThread,
IN PCLIENT_ID ClientId)
{
NTSTATUS Status;
PCSR_THREAD CsrThread;
//PCSRSS_PROCESS_DATA CurrentProcess;
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
CLIENT_ID CurrentCid;
KERNEL_USER_TIMES KernelTimes;
// DPRINT1("CSRSRV: %s called\n", __FUNCTION__);
/* Get the current thread and CID */
CurrentCid = CurrentThread->ClientId;
// DPRINT1("CALLER PID/TID: %lx/%lx\n", CurrentCid.UniqueProcess, CurrentCid.UniqueThread);
/* Acquire the Process Lock */
CsrAcquireProcessLock();
#if 0
/* Get the current Process and make sure the Thread is valid with this CID */
CurrentThread = CsrLocateThreadByClientId(&CurrentProcess,
&CurrentCid);
/* Something is wrong if we get an empty thread back */
if (!CurrentThread)
{
DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
CsrReleaseProcessLock();
return STATUS_THREAD_IS_TERMINATING;
}
#endif
/* Get the Thread Create Time */
Status = NtQueryInformationThread(hThread,
ThreadTimes,
(PVOID)&KernelTimes,
sizeof(KernelTimes),
NULL);
/* Allocate a CSR Thread Structure */
if (!(CsrThread = CsrAllocateThread(CsrProcess)))
{
DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
/* Save the data we have */
CsrThread->CreateTime = KernelTimes.CreateTime;
CsrThread->ClientId = *ClientId;
CsrThread->ThreadHandle = hThread;
CsrThread->Flags = 0;
/* Insert the Thread into the Process */
CsrInsertThread(CsrProcess, CsrThread);
/* Release the lock and return */
CsrReleaseProcessLock();
return STATUS_SUCCESS;
}
PCSR_THREAD
NTAPI
CsrAddStaticServerThread(IN HANDLE hThread,
IN PCLIENT_ID ClientId,
IN ULONG ThreadFlags)
{
PCSR_THREAD CsrThread;
/* Get the Lock */
CsrAcquireProcessLock();
/* Allocate the Server Thread */
if ((CsrThread = CsrAllocateThread(CsrRootProcess)))
{
/* Setup the Object */
// DPRINT1("New CSR thread created: %lx PID/TID: %lx/%lx\n", CsrThread, ClientId->UniqueProcess, ClientId->UniqueThread);
CsrThread->ThreadHandle = hThread;
CsrThread->ClientId = *ClientId;
CsrThread->Flags = ThreadFlags;
/* Insert it into the Thread List */
InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
/* Increment the thread count */
CsrRootProcess->ThreadCount++;
}
/* Release the Process Lock and return */
CsrReleaseProcessLock();
return CsrThread;
}
/* EOF */

View file

@ -148,7 +148,7 @@ extern HANDLE hBootstrapOk;
CSR_API(CsrConnectProcess);
CSR_API(CsrCreateProcess);
CSR_API(CsrTerminateProcess);
CSR_API(CsrCreateThread);
CSR_API(CsrSrvCreateThread);
/* print.c */
VOID WINAPI DisplayString(LPCWSTR lpwString);
@ -181,7 +181,10 @@ NTSTATUS WINAPI CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags);
PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSRSS_PROCESS_DATA CsrProcess OPTIONAL, IN PCLIENT_ID Cid);
PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSRSS_PROCESS_DATA *Process OPTIONAL, IN PCLIENT_ID ClientId);
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSRSS_PROCESS_DATA *CsrProcess OPTIONAL);
NTSTATUS NTAPI CsrCreateThread(IN PCSRSS_PROCESS_DATA CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId);
NTSTATUS NTAPI CsrUnlockProcess(IN PCSRSS_PROCESS_DATA CsrProcess);
/* api/handle.c */
NTSTATUS FASTCALL CsrRegisterObjectDefinitions(PCSRSS_OBJECT_DEFINITION NewDefinitions);
NTSTATUS WINAPI CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object, DWORD Access, BOOL Inheritable );
@ -192,6 +195,9 @@ NTSTATUS WINAPI CsrReleaseObjectByPointer(Object_t *Object);
NTSTATUS WINAPI CsrReleaseObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object );
NTSTATUS WINAPI CsrVerifyObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object );
//hack
VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
CSR_API(CsrGetInputHandle);
CSR_API(CsrGetOutputHandle);
CSR_API(CsrCloseHandle);