mirror of
https://github.com/reactos/reactos.git
synced 2025-05-22 10:35:54 +00:00
[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:
parent
1cd9cb22ef
commit
34fa6fb97b
7 changed files with 778 additions and 699 deletions
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
447
reactos/subsystems/win32/csrss/csrsrv/procsup.c
Normal file
447
reactos/subsystems/win32/csrss/csrsrv/procsup.c
Normal 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 */
|
306
reactos/subsystems/win32/csrss/csrsrv/thredsup.c
Normal file
306
reactos/subsystems/win32/csrss/csrsrv/thredsup.c
Normal 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 */
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue