[KERNEL32/CSRSS]: Register new Win32 threads with CSRSS. Add a bunch of lookup, creation, allocation, hashing and CSR thread management routines from the unused CSRSRV in trunk.

[CSRSS]: Bang in the new thread support in a bunch of places, including creating static server threads. It's very hacked and handle duplication doesn't work 100% reliably, but it gets the job done.
[CSRSS]: Add CsrGetProcessLuid, CsrImpersonateClient, CsrRevertToSelf, CsrShutdownProcesses, CsrFindProcessForShutdown required for user-mode shutdown. Right now we are able to reliably enumerate user apps (in the user LUID) and then service/system apps (in the LOCAL SYSTEM LUID).

svn path=/trunk/; revision=46042
This commit is contained in:
Sir Richard 2010-03-09 20:23:22 +00:00
parent e2d31e88e4
commit 4f05a88e82
7 changed files with 899 additions and 43 deletions

View file

@ -110,7 +110,38 @@ BasepNotifyCsrOfCreation(ULONG dwCreationFlags,
return CsrRequest.Status;
}
/* REturn Success */
/* Return Success */
return STATUS_SUCCESS;
}
NTSTATUS
WINAPI
BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
IN PCLIENT_ID ClientId)
{
ULONG Request = CREATE_THREAD;
CSR_API_MESSAGE CsrRequest;
NTSTATUS Status;
DPRINT("BasepNotifyCsrOfThread: Thread: %lx, Handle %lx\n",
ClientId->UniqueThread, ThreadHandle);
/* Fill out the request */
CsrRequest.Data.CreateThreadRequest.ClientId = *ClientId;
CsrRequest.Data.CreateThreadRequest.ThreadHandle = ThreadHandle;
/* Call CSR */
Status = CsrClientCallServer(&CsrRequest,
NULL,
MAKE_CSR_API(Request, CSR_NATIVE),
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
DPRINT1("Failed to tell csrss about new thread\n");
return CsrRequest.Status;
}
/* Return Success */
return STATUS_SUCCESS;
}
@ -164,7 +195,13 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
{
return NULL;
}
Status = BasepNotifyCsrOfThread(hThread, ClientId);
if (!NT_SUCCESS(Status))
{
ASSERT(FALSE);
}
/* Success */
return hThread;
}
@ -1375,6 +1412,18 @@ GetAppName:
&RemoteParameters->StandardError);
}
/* Notify CSRSS */
Status = BasepNotifyCsrOfCreation(dwCreationFlags,
(HANDLE)ProcessBasicInfo.UniqueProcessId,
bInheritHandles);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR Notification Failed");
SetLastErrorByStatus(Status);
goto Cleanup;
}
/* Create the first thread */
DPRINT("Creating thread for process (EntryPoint = 0x%p)\n",
SectionImageInfo.TransferAddress);
@ -1390,18 +1439,6 @@ GetAppName:
goto Cleanup;
}
/* Notify CSRSS */
Status = BasepNotifyCsrOfCreation(dwCreationFlags,
(HANDLE)ProcessBasicInfo.UniqueProcessId,
bInheritHandles);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR Notification Failed");
SetLastErrorByStatus(Status);
goto Cleanup;
}
if (!(dwCreationFlags & CREATE_SUSPENDED))
{
NtResumeThread(hThread, &Dummy);

View file

@ -19,6 +19,11 @@
#define HIGH_PRIORITY 31
#define SXS_SUPPORT_FIXME
NTSTATUS
WINAPI
BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
IN PCLIENT_ID ClientId);
/* FUNCTIONS *****************************************************************/
static
LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
@ -219,8 +224,13 @@ CreateRemoteThread(HANDLE hProcess,
DPRINT1("RtlAllocateActivationContextStack failed %x\n", Status);
}
/* FIXME: Notify CSR */
/* Notify CSR */
Status = BasepNotifyCsrOfThread(hThread, &ClientId);
if (!NT_SUCCESS(Status))
{
ASSERT(FALSE);
}
/* Success */
if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;

View file

@ -38,6 +38,12 @@ typedef struct
BOOL bInheritHandles;
} CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS;
typedef struct
{
CLIENT_ID ClientId;
HANDLE ThreadHandle;
} CSRSS_CREATE_THREAD, *PCSRSS_CREATE_THREAD;
typedef struct
{
ULONG Dummy;
@ -544,6 +550,7 @@ typedef struct
#define GET_CONSOLE_ALIASES_EXES (0x3C)
#define GET_CONSOLE_ALIASES_EXES_LENGTH (0x3D)
#define GENERATE_CTRL_EVENT (0x3E)
#define CREATE_THREAD (0x3F)
/* Keep in sync with definition below. */
#define CSRSS_HEADER_SIZE (sizeof(PORT_MESSAGE) + sizeof(ULONG) + sizeof(NTSTATUS))
@ -557,6 +564,7 @@ typedef struct _CSR_API_MESSAGE
union
{
CSRSS_CREATE_PROCESS CreateProcessRequest;
CSRSS_CREATE_THREAD CreateThreadRequest;
CSRSS_CONNECT_PROCESS ConnectRequest;
CSRSS_WRITE_CONSOLE WriteConsoleRequest;
CSRSS_READ_CONSOLE ReadConsoleRequest;

View file

@ -24,11 +24,241 @@ RTL_CRITICAL_SECTION ProcessDataLock;
/* 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
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;
RtlZeroMemory (ProcessData, sizeof ProcessData);
NrProcess = sizeof ProcessData / sizeof ProcessData[0];
RtlInitializeCriticalSection( &ProcessDataLock );
CsrRootProcess = CsrCreateProcessData(NtCurrentTeb()->ClientId.UniqueProcess);
/* Initialize the Thread Hash List */
for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]);
}
PCSRSS_PROCESS_DATA WINAPI CsrGetProcessData(HANDLE ProcessId)
@ -89,8 +319,7 @@ PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId)
/* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
Status = NtOpenProcess(&pProcessData->Process,
PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | SYNCHRONIZE,
PROCESS_ALL_ACCESS,
&ObjectAttributes,
&ClientId);
if (!NT_SUCCESS(Status))
@ -122,6 +351,9 @@ PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId)
pProcessData->ShutdownLevel = 0x280;
pProcessData->ShutdownFlags = 0;
}
pProcessData->ThreadCount = 0;
InitializeListHead(&pProcessData->ThreadList);
return pProcessData;
}
@ -186,33 +418,406 @@ NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
return STATUS_INVALID_PARAMETER;
}
NTSTATUS WINAPI
CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context)
VOID
NTAPI
CsrSetToNormalPriority(VOID)
{
UINT Hash;
PCSRSS_PROCESS_DATA pProcessData;
NTSTATUS Status = STATUS_SUCCESS;
KPRIORITY BasePriority = (8 + 1) + 4;
LOCK;
/* Set the Priority */
NtSetInformationProcess(NtCurrentProcess(),
ProcessBasePriority,
&BasePriority,
sizeof(KPRIORITY));
}
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
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)))
{
pProcessData = ProcessData[Hash];
while (NULL != pProcessData)
/* 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))
{
Status = EnumProc(pProcessData, Context);
if (STATUS_SUCCESS != Status)
{
UNLOCK;
return Status;
}
pProcessData = pProcessData->next;
/* 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;
}
}
UNLOCK;
/* 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;
}
}
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 = TRUE;
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 */
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, Context);
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;
}
/**********************************************************************
@ -255,6 +860,76 @@ CSR_API(CsrCreateProcess)
return(STATUS_SUCCESS);
}
CSR_API(CsrCreateThread)
{
PCSR_THREAD CurrentThread;
HANDLE ThreadHandle;
NTSTATUS Status;
PCSRSS_PROCESS_DATA CsrProcess;
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
CurrentThread = NtCurrentTeb()->CsrClientThread;
CsrProcess = CurrentThread->Process;
// DPRINT1("Current thread: %p %p\n", CurrentThread, CsrProcess);
// DPRINT1("Request CID: %lx %lx %lx\n",
// CsrProcess->ProcessId,
// NtCurrentTeb()->ClientId.UniqueProcess,
// Request->Data.CreateThreadRequest.ClientId.UniqueProcess);
if (CsrProcess->ProcessId != Request->Data.CreateThreadRequest.ClientId.UniqueProcess)
{
if (Request->Data.CreateThreadRequest.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
{
return STATUS_SUCCESS;
}
Status = CsrLockProcessByClientId(Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
&CsrProcess);
// DPRINT1("Found matching process: %p\n", CsrProcess);
if (!NT_SUCCESS(Status)) return Status;
}
// DPRINT1("PIDs: %lx %lx\n", CurrentThread->Process->ProcessId, CsrProcess->ProcessId);
// DPRINT1("Thread handle is: %lx Process Handle is: %lx %lx\n",
// Request->Data.CreateThreadRequest.ThreadHandle,
// CurrentThread->Process->Process,
// CsrProcess->Process);
Status = NtDuplicateObject(CsrProcess->Process,
Request->Data.CreateThreadRequest.ThreadHandle,
NtCurrentProcess(),
&ThreadHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
//DPRINT1("Duplicate status: %lx\n", Status);
if (!NT_SUCCESS(Status))
{
Status = NtDuplicateObject(CurrentThread->Process->Process,
Request->Data.CreateThreadRequest.ThreadHandle,
NtCurrentProcess(),
&ThreadHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
// DPRINT1("Duplicate status: %lx\n", Status);
}
Status = STATUS_SUCCESS; // hack
if (NT_SUCCESS(Status))
{
Status = CsrCreateThreadData(CsrProcess,
ThreadHandle,
&Request->Data.CreateThreadRequest.ClientId);
// DPRINT1("Create status: %lx\n", Status);
}
if (CsrProcess != CurrentThread->Process) CsrReleaseProcessLock();
return Status;
}
CSR_API(CsrTerminateProcess)
{
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);

View file

@ -126,6 +126,7 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
HANDLE ServerPort = NULL, ServerThread = NULL;
PCSRSS_PROCESS_DATA ProcessData = NULL;
REMOTE_PORT_VIEW LpcRead;
CLIENT_ID ClientId;
LpcRead.Length = sizeof(LpcRead);
ServerPort = NULL;
@ -169,19 +170,23 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
TRUE,
0,
0,
0,
(PTHREAD_START_ROUTINE)ClientConnectionThread,
ServerPort,
& ServerThread,
NULL);
&ClientId);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR: Unable to create server thread\n");
return Status;
}
CsrAddStaticServerThread(ServerThread, &ClientId, 0);
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
@ -190,6 +195,53 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
return Status;
}
PCSR_THREAD
NTAPI
CsrConnectToUser(VOID)
{
PTEB Teb = NtCurrentTeb();
PCSR_THREAD CsrThread;
#if 0
NTSTATUS Status;
ANSI_STRING DllName;
UNICODE_STRING TempName;
HANDLE hUser32;
STRING StartupName;
/* Check if we didn't already find it */
if (!CsrClientThreadSetup)
{
/* Get the DLL Handle for user32.dll */
RtlInitAnsiString(&DllName, "user32");
RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
Status = LdrGetDllHandle(NULL,
NULL,
&TempName,
&hUser32);
RtlFreeUnicodeString(&TempName);
/* If we got teh handle, get the Client Thread Startup Entrypoint */
if (NT_SUCCESS(Status))
{
RtlInitAnsiString(&StartupName,"ClientThreadSetup");
Status = LdrGetProcedureAddress(hUser32,
&StartupName,
0,
(PVOID)&CsrClientThreadSetup);
}
}
/* Connect to user32 */
CsrClientThreadSetup();
#endif
/* Save pointer to this thread in TEB */
CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
if (CsrThread) Teb->CsrClientThread = CsrThread;
/* Return it */
return CsrThread;
}
VOID
WINAPI
ClientConnectionThread(HANDLE ServerPort)
@ -199,10 +251,20 @@ ClientConnectionThread(HANDLE ServerPort)
PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
PCSR_API_MESSAGE Reply;
PCSRSS_PROCESS_DATA ProcessData;
PCSR_THREAD ServerThread;
DPRINT("CSR: %s called\n", __FUNCTION__);
/* Connect to user32 */
while (!CsrConnectToUser())
{
/* Keep trying until we get a response */
NtCurrentTeb()->Win32ClientInfo[0] = 0;
//NtDelayExecution(FALSE, &TimeOut);
}
/* Reply must be NULL at the first call to NtReplyWaitReceivePort */
ServerThread = NtCurrentTeb()->CsrClientThread;
Reply = NULL;
/* Loop and reply/wait for a new message */
@ -271,7 +333,7 @@ ClientConnectionThread(HANDLE ServerPort)
}
if (ProcessData->Terminated)
{
DPRINT1("Message %d: process %p already terminated\n",
DPRINT1("Message %d: process %d already terminated\n",
Request->Type, Request->Header.ClientId.UniqueProcess);
continue;
}
@ -284,8 +346,17 @@ ClientConnectionThread(HANDLE ServerPort)
}
else
{
PCSR_THREAD Thread;
PCSRSS_PROCESS_DATA Process = NULL;
//DPRINT1("locate thread %lx/%lx\n", Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
Thread = CsrLocateThreadByClientId(&Process, &Request->Header.ClientId);
//DPRINT1("Thread found: %p %p\n", Thread, Process);
/* Call the Handler */
if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
CsrApiCallHandler(ProcessData, Request);
if (Thread) NtCurrentTeb()->CsrClientThread = ServerThread;
}
/* Send back the reply */

View file

@ -13,6 +13,29 @@
#include <csrss/csrss.h>
typedef enum _SHUTDOWN_RESULT
{
CsrShutdownCsrProcess = 1,
CsrShutdownNonCsrProcess,
CsrShutdownCancelled
} SHUTDOWN_RESULT, *PSHUTDOWN_RESULT;
typedef enum _CSR_SHUTDOWN_FLAGS
{
CsrShutdownSystem = 4,
CsrShutdownOther = 8
} CSR_SHUTDOWN_FLAGS, *PCSR_SHUTDOWN_FLAGS;
typedef enum _CSR_PROCESS_FLAGS
{
CsrProcessTerminating = 0x1,
CsrProcessSkipShutdown = 0x2,
CsrProcessCreateNewGroup = 0x100,
CsrProcessTerminated = 0x200,
CsrProcessLastThreadTerminated = 0x400,
CsrProcessIsConsoleApp = 0x800
} CSR_PROCESS_FLAGS, *PCSR_PROCESS_FLAGS;
typedef struct Object_tt
{
LONG Type;
@ -59,8 +82,25 @@ typedef struct _CSRSS_PROCESS_DATA
LIST_ENTRY ProcessEntry;
PCONTROLDISPATCHER CtrlDispatcher;
BOOL Terminated;
ULONG Flags;
ULONG ThreadCount;
LIST_ENTRY ThreadList;
} CSRSS_PROCESS_DATA, *PCSRSS_PROCESS_DATA;
typedef struct _CSR_THREAD
{
LARGE_INTEGER CreateTime;
LIST_ENTRY Link;
LIST_ENTRY HashLinks;
CLIENT_ID ClientId;
PCSRSS_PROCESS_DATA Process;
//struct _CSR_WAIT_BLOCK *WaitBlock;
HANDLE ThreadHandle;
ULONG Flags;
ULONG ReferenceCount;
ULONG ImpersonationCount;
} CSR_THREAD, *PCSR_THREAD;
typedef VOID (WINAPI *CSR_CLEANUP_OBJECT_PROC)(Object_t *Object);
typedef struct tagCSRSS_OBJECT_DEFINITION
@ -100,6 +140,7 @@ extern HANDLE hBootstrapOk;
CSR_API(CsrConnectProcess);
CSR_API(CsrCreateProcess);
CSR_API(CsrTerminateProcess);
CSR_API(CsrCreateThread);
/* print.c */
VOID WINAPI DisplayString(LPCWSTR lpwString);
@ -129,7 +170,10 @@ PCSRSS_PROCESS_DATA WINAPI CsrGetProcessData(HANDLE ProcessId);
PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId);
NTSTATUS WINAPI CsrFreeProcessData( HANDLE Pid );
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);
/* 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 );

View file

@ -283,6 +283,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(TERMINATE_PROCESS, CsrTerminateProcess),
CSRSS_DEFINE_API(CONNECT_PROCESS, CsrConnectProcess),
CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),
@ -305,6 +306,8 @@ CsrpCreateListenPort (IN LPWSTR Name,
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES PortAttributes;
UNICODE_STRING PortName;
HANDLE ServerThread;
CLIENT_ID ClientId;
DPRINT("CSR: %s called\n", __FUNCTION__);
@ -327,14 +330,22 @@ CsrpCreateListenPort (IN LPWSTR Name,
}
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
TRUE,
0,
0,
0,
(PTHREAD_START_ROUTINE) ListenThread,
*Port,
NULL,
NULL);
&ServerThread,
&ClientId);
if (ListenThread == (PVOID)ClientConnectionThread)
{
CsrAddStaticServerThread(ServerThread, &ClientId, 0);
}
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
return Status;
}