Author: sir_richard
Date: Tue Mar 9 21:23:22 2010
New Revision: 46042
URL:
http://svn.reactos.org/svn/reactos?rev=46042&view=rev
Log:
[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).
Modified:
trunk/reactos/dll/win32/kernel32/process/procsup.c
trunk/reactos/dll/win32/kernel32/thread/thread.c
trunk/reactos/include/reactos/subsys/csrss/csrss.h
trunk/reactos/subsystems/win32/csrss/api/process.c
trunk/reactos/subsystems/win32/csrss/api/wapi.c
trunk/reactos/subsystems/win32/csrss/include/api.h
trunk/reactos/subsystems/win32/csrss/init.c
Modified: trunk/reactos/dll/win32/kernel32/process/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/process…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/process/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/process/procsup.c [iso-8859-1] Tue Mar 9 21:23:22
2010
@@ -110,7 +110,38 @@
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 @@
{
return NULL;
}
-
+
+ Status = BasepNotifyCsrOfThread(hThread, ClientId);
+ if (!NT_SUCCESS(Status))
+ {
+ ASSERT(FALSE);
+ }
+
/* Success */
return hThread;
}
@@ -1375,6 +1412,18 @@
&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);
@@ -1387,18 +1436,6 @@
{
DPRINT1("Could not create Initial Thread\n");
/* FIXME - set last error code */
- goto Cleanup;
- }
-
- /* Notify CSRSS */
- Status = BasepNotifyCsrOfCreation(dwCreationFlags,
- (HANDLE)ProcessBasicInfo.UniqueProcessId,
- bInheritHandles);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CSR Notification Failed");
- SetLastErrorByStatus(Status);
goto Cleanup;
}
Modified: trunk/reactos/dll/win32/kernel32/thread/thread.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/thread/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/thread/thread.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/thread/thread.c [iso-8859-1] Tue Mar 9 21:23:22
2010
@@ -18,6 +18,11 @@
/* FIXME: NDK */
#define HIGH_PRIORITY 31
#define SXS_SUPPORT_FIXME
+
+NTSTATUS
+WINAPI
+BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
+ IN PCLIENT_ID ClientId);
/* FUNCTIONS *****************************************************************/
static
@@ -219,8 +224,13 @@
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;
Modified: trunk/reactos/include/reactos/subsys/csrss/csrss.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/csr…
==============================================================================
--- trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] Tue Mar 9 21:23:22
2010
@@ -37,6 +37,12 @@
ULONG Flags;
BOOL bInheritHandles;
} CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS;
+
+typedef struct
+{
+ CLIENT_ID ClientId;
+ HANDLE ThreadHandle;
+} CSRSS_CREATE_THREAD, *PCSRSS_CREATE_THREAD;
typedef struct
{
@@ -544,6 +550,7 @@
#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 @@
union
{
CSRSS_CREATE_PROCESS CreateProcessRequest;
+ CSRSS_CREATE_THREAD CreateThreadRequest;
CSRSS_CONNECT_PROCESS ConnectRequest;
CSRSS_WRITE_CONSOLE WriteConsoleRequest;
CSRSS_READ_CONSOLE ReadConsoleRequest;
Modified: trunk/reactos/subsystems/win32/csrss/api/process.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/api…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/api/process.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/api/process.c [iso-8859-1] Tue Mar 9 21:23:22
2010
@@ -24,11 +24,241 @@
/* 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 @@
/* 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 @@
pProcessData->ShutdownLevel = 0x280;
pProcessData->ShutdownFlags = 0;
}
+
+ pProcessData->ThreadCount = 0;
+ InitializeListHead(&pProcessData->ThreadList);
return pProcessData;
}
@@ -186,33 +418,406 @@
return STATUS_INVALID_PARAMETER;
}
-NTSTATUS WINAPI
-CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context)
-{
- UINT Hash;
- PCSRSS_PROCESS_DATA pProcessData;
- NTSTATUS Status = STATUS_SUCCESS;
-
- LOCK;
-
- for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
- {
- pProcessData = ProcessData[Hash];
- while (NULL != pProcessData)
- {
- Status = EnumProc(pProcessData, Context);
- if (STATUS_SUCCESS != Status)
+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)
{
- UNLOCK;
- return Status;
+ /* FIXME:Check if we have any threads */
}
- pProcessData = pProcessData->next;
- }
- }
-
- UNLOCK;
-
- return Status;
+
+ 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;
}
/**********************************************************************
@@ -253,6 +858,76 @@
}
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)
Modified: trunk/reactos/subsystems/win32/csrss/api/wapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/api…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/api/wapi.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/api/wapi.c [iso-8859-1] Tue Mar 9 21:23:22 2010
@@ -126,6 +126,7 @@
HANDLE ServerPort = NULL, ServerThread = NULL;
PCSRSS_PROCESS_DATA ProcessData = NULL;
REMOTE_PORT_VIEW LpcRead;
+ CLIENT_ID ClientId;
LpcRead.Length = sizeof(LpcRead);
ServerPort = NULL;
@@ -169,25 +170,76 @@
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);
Status = STATUS_SUCCESS;
DPRINT("CSR: %s done\n", __FUNCTION__);
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
@@ -199,10 +251,20 @@
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 @@
}
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 @@
}
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 */
Modified: trunk/reactos/subsystems/win32/csrss/include/api.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/inc…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/include/api.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/include/api.h [iso-8859-1] Tue Mar 9 21:23:22
2010
@@ -12,6 +12,29 @@
#include <ndk/ntndk.h>
#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
{
@@ -59,7 +82,24 @@
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);
@@ -100,6 +140,7 @@
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 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 );
Modified: trunk/reactos/subsystems/win32/csrss/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/ini…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/init.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/init.c [iso-8859-1] Tue Mar 9 21:23:22 2010
@@ -283,6 +283,7 @@
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 @@
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 @@
}
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;
}