Author: ion
Date: Sun Feb 19 19:40:28 2012
New Revision: 55718
URL:
http://svn.reactos.org/svn/reactos?rev=55718&view=rev
Log:
[CSRSRV]: Sometimes too much of a hybrid is no longer a good thing. Rewrite the CSRSRV API
loop to match (almost -- except the actual API conversion which is different in ReactOS)
the CSRSRV2 loop, with the correct handling of datagrams, errors, exceptions, death
messages, etc...
[CSRSRV]: Add special handling for certain messages (similar to how "Reply" is
used in CSRSRV2) so that we don't keep replying to the wrong thead. For example,
during an ExitProcess, special handling is needed at the end of the loop.
[CSRSRV]: Remove the last few remaining legacy process management function and use the
correct CsrLock/Unlock APIs instead. No longer leak references for every process like
crazy. Fully manage proc/thread/session reference counts now.
At this point it looks like there might just be one issue left before this thing works
right (minus potential regressions due to missed hacks).
Modified:
trunk/reactos/subsystems/csr/csrsrv/api.c
trunk/reactos/subsystems/win32/csrss/csrsrv/api/process.c
trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c
trunk/reactos/subsystems/win32/csrss/csrsrv/procsup.c
trunk/reactos/subsystems/win32/csrss/include/api.h
Modified: trunk/reactos/subsystems/csr/csrsrv/api.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/csr/csrsrv/api.…
==============================================================================
--- trunk/reactos/subsystems/csr/csrsrv/api.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/csr/csrsrv/api.c [iso-8859-1] Sun Feb 19 19:40:28 2012
@@ -446,7 +446,7 @@
continue;
}
- /* It's some other kind of request. Get the lock for the lookup*/
+ /* It's some other kind of request. Get the lock for the lookup */
CsrAcquireProcessLock();
/* Now do the lookup to get the CSR_THREAD */
Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/api/process.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csr…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/api/process.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/api/process.c [iso-8859-1] Sun Feb 19
19:40:28 2012
@@ -18,66 +18,6 @@
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
-
-PCSR_PROCESS WINAPI CsrGetProcessData(HANDLE ProcessId)
-{
- PCSR_PROCESS CsrProcess;
- NTSTATUS Status;
-
- Status = CsrLockProcessByClientId(ProcessId, &CsrProcess);
- if (!NT_SUCCESS(Status)) return NULL;
-
- UNLOCK;
- return CsrProcess;
-}
-
-NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
-{
- PCSR_PROCESS pProcessData;
- HANDLE Process;
- PLIST_ENTRY NextEntry;
- PCSR_THREAD Thread;
-
- pProcessData = CsrGetProcessData(Pid);
- if (!pProcessData) return STATUS_INVALID_PARAMETER;
-
- LOCK;
-
- Process = pProcessData->ProcessHandle;
-
- /* Dereference all process threads */
- NextEntry = pProcessData->ThreadList.Flink;
- while (NextEntry != &pProcessData->ThreadList)
- {
- Thread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
- NextEntry = NextEntry->Flink;
-
- ASSERT(ProcessStructureListLocked());
- CsrThreadRefcountZero(Thread);
- LOCK;
- }
-
- if (pProcessData->ClientViewBase)
- {
- NtUnmapViewOfSection(NtCurrentProcess(),
(PVOID)pProcessData->ClientViewBase);
- }
-
- if (pProcessData->ClientPort)
- {
- NtClose(pProcessData->ClientPort);
- }
-
- CsrRemoveProcess(pProcessData);
-
- CsrDeallocateProcess(pProcessData);
-
- if (Process)
- {
- NtClose(Process);
- }
-
- return STATUS_SUCCESS;
-}
/**********************************************************************
* CSRSS API
@@ -202,8 +142,14 @@
/* Get the current CSR thread */
CurrentThread = NtCurrentTeb()->CsrClientThread;
- if (!CurrentThread) return STATUS_SUCCESS; // server-to-server
-
+ if (!CurrentThread)
+ {
+ DPRINT1("Server Thread TID: [%lx.%lx]\n",
+ Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
+ Request->Data.CreateThreadRequest.ClientId.UniqueThread);
+ return STATUS_SUCCESS; // server-to-server
+ }
+
/* Get the CSR Process for this request */
CsrProcess = CurrentThread->Process;
if (CsrProcess->ClientId.UniqueProcess !=
@@ -215,7 +161,7 @@
/* Accept this without any further work */
return STATUS_SUCCESS;
}
-
+
/* Get the real CSR Process for the remote thread's process */
Status =
CsrLockProcessByClientId(Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
&CsrProcess);
@@ -247,7 +193,10 @@
{
PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
ASSERT(CsrThread != NULL);
-
+
+ /* Set magic flag so we don't reply this message back */
+ Request->Type = 0xBABE;
+
/* Remove the CSR_THREADs and CSR_PROCESS */
return CsrDestroyProcess(&CsrThread->ClientId,
(NTSTATUS)Request->Data.TerminateProcessRequest.uExitCode);
Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csr…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c [iso-8859-1] Sun Feb 19
19:40:28 2012
@@ -208,16 +208,16 @@
return STATUS_SUCCESS;
#else // Hacky reactos code
PCSR_PROCESS ProcessData;
-
+
/* Get the Process Data */
- ProcessData = CsrGetProcessData(ReceiveMsg->Header.ClientId.UniqueProcess);
+ CsrLockProcessByClientId(&ReceiveMsg->Header.ClientId.UniqueProcess,
&ProcessData);
if (!ProcessData)
{
DPRINT1("Message: Unable to find data for process 0x%x\n",
ReceiveMsg->Header.ClientId.UniqueProcess);
return STATUS_NOT_SUPPORTED;
}
-
+
/* Validation complete, start SEH */
_SEH2_TRY
{
@@ -230,6 +230,9 @@
ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
}
_SEH2_END;
+
+ /* Release the process reference */
+ CsrUnlockProcess(ProcessData);
/* Return success */
return STATUS_SUCCESS;
@@ -759,15 +762,12 @@
/* Save the process ID */
RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO));
- ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess);
+ CsrLockProcessByClientId(Request->ClientId.UniqueProcess, &ProcessData);
if (!ProcessData)
{
DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting
connection\n",
Request->ClientId.UniqueProcess);
}
-
- /* Acquire the Process Lock */
- CsrAcquireProcessLock();
if ((ProcessData) && (ProcessData != CsrRootProcess))
{
@@ -788,8 +788,8 @@
AllowConnection = TRUE;
}
- /* Release the lock */
- CsrReleaseProcessLock();
+ /* Release the process */
+ if (ProcessData) CsrUnlockProcess(ProcessData);
/* Setup the Port View Structure */
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
@@ -1004,12 +1004,13 @@
BYTE RawRequest[LPC_MAX_DATA_LENGTH];
PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
PCSR_API_MESSAGE Reply;
- PCSR_PROCESS ProcessData;
- PCSR_THREAD ServerThread;
+ PCSR_PROCESS CsrProcess;
+ PCSR_THREAD ServerThread, CsrThread;
ULONG MessageType;
HANDLE ReplyPort;
PDBGKM_MSG DebugMessage;
-
+ PHARDERROR_MSG HardErrorMsg;
+ PCLIENT_DIED_MSG ClientDiedMsg;
DPRINT("CSR: %s called\n", __FUNCTION__);
/* Setup LPC loop port and message */
@@ -1099,145 +1100,240 @@
/* Get the Message Type */
MessageType = Request->Header.u2.s2.Type;
-
- /* If the connection was closed, handle that */
- if (MessageType == LPC_PORT_CLOSED)
- {
- DPRINT("Port died, oh well\n");
- CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
- Reply = NULL;
- ReplyPort = CsrApiPort;
- continue;
- }
-
+
+ /* Handle connection requests */
if (MessageType == LPC_CONNECTION_REQUEST)
{
+ /* Handle the Connection Request */
DPRINT("Accepting new connection\n");
CsrpHandleConnectionRequest((PPORT_MESSAGE)Request);
Reply = NULL;
ReplyPort = CsrApiPort;
continue;
}
-
- if (MessageType == LPC_CLIENT_DIED)
- {
- DPRINT("Client died, oh well\n");
- Reply = NULL;
- ReplyPort = CsrApiPort;
+
+ /* It's some other kind of request. Get the lock for the lookup */
+ CsrAcquireProcessLock();
+
+ /* Now do the lookup to get the CSR_THREAD */
+ CsrThread = CsrLocateThreadByClientId(&CsrProcess,
+ &Request->Header.ClientId);
+
+ /* Did we find a thread? */
+ if (!CsrThread)
+ {
+ /* This wasn't a CSR Thread, release lock */
+ CsrReleaseProcessLock();
+
+ /* If this was an exception, handle it */
+ if (MessageType == LPC_EXCEPTION)
+ {
+ DPRINT1("Exception from unknown thread, just continue\n");
+ Reply = Request;
+ ReplyPort = CsrApiPort;
+ Reply->Status = DBG_CONTINUE;
+ }
+ else if (MessageType == LPC_PORT_CLOSED ||
+ MessageType == LPC_CLIENT_DIED)
+ {
+ /* The Client or Port are gone, loop again */
+ DPRINT1("Death from unknown thread, just continue\n");
+ Reply = NULL;
+ ReplyPort = CsrApiPort;
+ }
+ else if (MessageType == LPC_ERROR_EVENT)
+ {
+ /* If it's a hard error, handle this too */
+ DPRINT1("Hard error from unknown thread, call handlers\n");
+HandleHardError:
+ HardErrorMsg = (PHARDERROR_MSG)Request;
+
+ /* Default it to unhandled */
+ HardErrorMsg->Response = ResponseNotHandled;
+
+ /* Check if there are free api threads */
+ CsrpCheckRequestThreads();
+ if (CsrpStaticThreadCount)
+ {
+ CsrHandleHardError(CsrThread, (PHARDERROR_MSG)Request);
+ }
+
+ /* If the response was 0xFFFFFFFF, we'll ignore it */
+ if (HardErrorMsg->Response == 0xFFFFFFFF)
+ {
+ Reply = NULL;
+ ReplyPort = CsrApiPort;
+ }
+ else
+ {
+ if (CsrThread) CsrDereferenceThread(CsrThread);
+ Reply = Request;
+ ReplyPort = CsrApiPort;
+ }
+ }
+ else if (MessageType == LPC_REQUEST)
+ {
+ /* This is an API Message coming from a non-CSR Thread */
+ DPRINT1("No thread found for request %lx and clientID
%lx.%lx\n",
+ Request->Type & 0xFFFF,
+ Request->Header.ClientId.UniqueProcess,
+ Request->Header.ClientId.UniqueThread);
+ Reply = Request;
+ ReplyPort = CsrApiPort;
+ Reply->Status = STATUS_ILLEGAL_FUNCTION;
+ }
+ else if (MessageType == LPC_DATAGRAM)
+ {
+ DPRINT1("Kernel datagram: not yet supported\n");
+ Reply = NULL;
+ ReplyPort = CsrApiPort;
+ }
+ else
+ {
+ /* Some other ignored message type */
+ Reply = NULL;
+ ReplyPort = CsrApiPort;
+ }
+
+ /* Keep going */
continue;
}
-
+
+ /* We have a valid thread, was this an LPC Request? */
+ if (MessageType != LPC_REQUEST)
+ {
+ /* It's not an API, check if the client died */
+ if (MessageType == LPC_CLIENT_DIED)
+ {
+ /* Get the information and check if it matches our thread */
+ ClientDiedMsg = (PCLIENT_DIED_MSG)Request;
+ if (ClientDiedMsg->CreateTime.QuadPart ==
CsrThread->CreateTime.QuadPart)
+ {
+ /* Reference the thread */
+ CsrLockedReferenceThread(CsrThread);
+
+ /* Destroy the thread in the API Message */
+ CsrDestroyThread(&Request->Header.ClientId);
+
+ /* Check if the thread was actually ourselves */
+ if (CsrProcess->ThreadCount == 1)
+ {
+ /* Kill the process manually here */
+ DPRINT1("Last thread\n");
+ CsrDestroyProcess(&CsrThread->ClientId, 0);
+ }
+
+ /* Remove our extra reference */
+ CsrLockedDereferenceThread(CsrThread);
+ }
+
+ /* Release the lock and keep looping */
+ CsrReleaseProcessLock();
+ Reply = NULL;
+ ReplyPort = CsrApiPort;
+ continue;
+ }
+
+ /* Reference the thread and release the lock */
+ CsrLockedReferenceThread(CsrThread);
+ CsrReleaseProcessLock();
+
+ /* If this was an exception, handle it */
+ if (MessageType == LPC_EXCEPTION)
+ {
+ /* Kill the process */
+ DPRINT1("Exception in %lx.%lx. Killing...\n",
+ Request->Header.ClientId.UniqueProcess,
+ Request->Header.ClientId.UniqueThread);
+ NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
+
+ /* Destroy it from CSR */
+ CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED);
+
+ /* Return a Debug Message */
+ DebugMessage = (PDBGKM_MSG)&Request;
+ DebugMessage->ReturnedStatus = DBG_CONTINUE;
+ Reply = Request;
+ ReplyPort = CsrApiPort;
+
+ /* Remove our extra reference */
+ CsrDereferenceThread(CsrThread);
+ }
+ else if (MessageType == LPC_ERROR_EVENT)
+ {
+ DPRINT1("Hard error from known CSR thread... handling\n");
+ goto HandleHardError;
+ }
+ else
+ {
+ /* Something else */
+ DPRINT1("Unhandled message type: %lx\n", MessageType);
+ CsrDereferenceThread(CsrThread);
+ Reply = NULL;
+ }
+
+ /* Keep looping */
+ continue;
+ }
+
+ /* We got an API Request */
+ CsrLockedReferenceThread(CsrThread);
+ CsrReleaseProcessLock();
+
+ /* Assume success */
+ Reply = Request;
+ Request->Status = STATUS_SUCCESS;
+
+ /* Now we reply to a particular client */
+ ReplyPort = CsrThread->Process->ClientPort;
+
DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
Request->Type,
Request->Header.ClientId.UniqueThread);
- /* Get the Process Data */
- ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
- if (ProcessData == NULL)
- {
- DPRINT1("Message %d: Unable to find data for process 0x%x\n",
- MessageType,
- Request->Header.ClientId.UniqueProcess);
+ /* Validation complete, start SEH */
+ _SEH2_TRY
+ {
+ /* Make sure we have enough threads */
+ CsrpCheckRequestThreads();
+
+ /* Set the client thread pointer */
+ NtCurrentTeb()->CsrClientThread = CsrThread;
+
+ /* Call the Handler */
+ CsrApiCallHandler(CsrThread->Process, Request);
+
+ /* Increase the static thread count */
+ _InterlockedIncrement(&CsrpStaticThreadCount);
+
+ /* Restore the server thread */
+ NtCurrentTeb()->CsrClientThread = ServerThread;
+
+ /* Check if this is a dead client now */
+ if (Request->Type == 0xBABE)
+ {
+ /* Reply to the death message */
+ NtReplyPort(ReplyPort, &Reply->Header);
+
+ /* Reply back to the API port now */
+ ReplyPort = CsrApiPort;
+ Reply = NULL;
+
+ /* Drop the reference */
+ CsrDereferenceThread(CsrThread);
+ }
+ else
+ {
+ /* Drop the reference */
+ CsrDereferenceThread(CsrThread);
+ }
+ }
+ _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+ {
Reply = NULL;
ReplyPort = CsrApiPort;
- continue;
- }
- if (ProcessData->Flags & CsrProcessTerminated)
- {
- DPRINT1("Message %d: process %d already terminated\n",
- Request->Type, Request->Header.ClientId.UniqueProcess);
- Reply = NULL;
- ReplyPort = CsrApiPort;
- continue;
- }
-
- /* If this was an exception, handle it */
- if (MessageType == LPC_EXCEPTION)
- {
- /* Kill the process */
- DPRINT1("Exception in %lx.%lx. Killing...\n",
- Request->Header.ClientId.UniqueProcess,
- Request->Header.ClientId.UniqueThread);
- NtTerminateProcess(ProcessData->ProcessHandle, STATUS_ABANDONED);
-
- /* Destroy it from CSR */
- CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED);
-
- /* Return a Debug Message */
- DebugMessage = (PDBGKM_MSG)&Request;
- DebugMessage->ReturnedStatus = DBG_CONTINUE;
- Reply = Request;
- ReplyPort = CsrApiPort;
- continue;
- }
-
- /* Check if we got a hard error */
- if (MessageType == LPC_ERROR_EVENT)
- {
- /* Call the Handler */
- PCSR_THREAD Thread;
- Thread = CsrLocateThreadByClientId(NULL, &Request->Header.ClientId);
- CsrHandleHardError(Thread, (PHARDERROR_MSG)Request);
- ReplyPort = CsrApiPort;
- }
- else
- {
- PCSR_THREAD Thread;
- PCSR_PROCESS Process = NULL;
-
- /* Validation complete, start SEH */
- _SEH2_TRY
- {
- /* Make sure we have enough threads */
- CsrpCheckRequestThreads();
-
- //DPRINT1("locate thread %lx/%lx\n",
Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
- Thread = CsrLocateThreadByClientId(&Process,
&Request->Header.ClientId);
- if (!Thread)
- {
- DPRINT1("No thread found for request %lx and clientID
%lx.%lx\n",
- Request->Type & 0xFFFF,
- Request->Header.ClientId.UniqueProcess,
- Request->Header.ClientId.UniqueThread);
- }
- //DPRINT1("Thread found: %p %p\n", Thread, Process);
- if (Thread) CsrLockedReferenceThread(Thread);
-
- if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
-
- /* Now we reply to a particular client */
- if (Thread)
- {
- ReplyPort = Thread->Process->ClientPort;
- ASSERT(Thread->Process == ProcessData);
- }
- else
- {
- ReplyPort = ProcessData->ClientPort;
- }
-
- /* Call the Handler */
- CsrApiCallHandler(ProcessData, Request);
-
- /* Increase the static thread count */
- _InterlockedIncrement(&CsrpStaticThreadCount);
-
- if (Thread)
- {
- NtCurrentTeb()->CsrClientThread = ServerThread;
- CsrDereferenceThread(Thread);
- }
- }
- _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
- {
- Reply = NULL;
- ReplyPort = CsrApiPort;
- }
- _SEH2_END;
- }
-
- /* Send back the reply */
- Reply = Request;
+ }
+ _SEH2_END;
}
/* Close the port and exit the thread */
Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csr…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/procsup.c [iso-8859-1] Sun Feb 19 19:40:28
2012
@@ -413,7 +413,7 @@
if (CsrProcess->NtSession)
{
/* Dereference the Session */
- //CsrDereferenceNtSession(CsrProcess->NtSession, 0);
+ CsrDereferenceNtSession(CsrProcess->NtSession, 0);
}
/* Close the Client Port if there is one */
@@ -453,7 +453,7 @@
{
/* Call the generic cleanup code */
DPRINT1("Should kill process: %p\n", CsrProcess);
- //CsrProcessRefcountZero(CsrProcess);
+ CsrProcessRefcountZero(CsrProcess);
CsrAcquireProcessLock();
}
}
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] Sun Feb 19 19:40:28
2012
@@ -360,9 +360,7 @@
typedef NTSTATUS (WINAPI *CSRSS_ENUM_PROCESS_PROC)(PCSR_PROCESS ProcessData,
PVOID Context);
NTSTATUS WINAPI CsrInitializeProcessStructure(VOID);
-PCSR_PROCESS WINAPI CsrGetProcessData(HANDLE ProcessId);
-PCSR_PROCESS 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 PCSR_PROCESS CsrProcess OPTIONAL, IN
PCLIENT_ID Cid);
@@ -447,6 +445,11 @@
VOID
NTAPI
+CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
+IN NTSTATUS ExitStatus);
+
+VOID
+NTAPI
CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess);
VOID