From e5f337a82b559bbc1d5a2e28eaa6e7caacf91eae Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sat, 18 Feb 2012 01:27:50 +0000 Subject: [PATCH] [CSRSRV]: Port CsrCallServerFromServer (and hackplement a reactos-compatible implememntation) from CSRSRV2. [CSRSRV/CSRSRV2]: Fix CsrLockProcessByPid -- it was skipping the root process itself, so requests coming from a CSRSS-hosted DLL would fail (which is exactly what server-to-server depends on). [NTDLL]: Enable support for server-to-server calls! Server-to-server calls work now, and one of the multiple mapping hacks is gone. User32 and kernel32 still need a bit of fixes to get rid of the other hacks, though. Also, Perf++. svn path=/trunk/; revision=55677 --- reactos/dll/ntdll/csr/connect.c | 7 +- reactos/dll/win32/kernel32/client/proc.c | 2 +- reactos/subsystems/csr/csrsrv/process.c | 30 +++-- .../subsystems/win32/csrss/csrsrv/api/wapi.c | 122 ++++++++++++++++++ .../subsystems/win32/csrss/csrsrv/csrsrv.spec | 2 +- .../subsystems/win32/csrss/csrsrv/procsup.c | 30 +++-- 6 files changed, 164 insertions(+), 29 deletions(-) diff --git a/reactos/dll/ntdll/csr/connect.c b/reactos/dll/ntdll/csr/connect.c index 92227d0bf84..e356cc772d5 100644 --- a/reactos/dll/ntdll/csr/connect.c +++ b/reactos/dll/ntdll/csr/connect.c @@ -19,7 +19,6 @@ HANDLE CsrProcessId; HANDLE CsrPortHeap; ULONG_PTR CsrPortMemoryDelta; BOOLEAN InsideCsrProcess = FALSE; -BOOLEAN UsingOldCsr = TRUE; typedef NTSTATUS (NTAPI *PCSR_SERVER_API_ROUTINE)(IN PPORT_MESSAGE Request, @@ -151,7 +150,7 @@ CsrClientCallServer(PCSR_API_MESSAGE ApiMessage, else { /* This is a server-to-server call. Save our CID and do a direct call */ - DbgBreakPoint(); + DPRINT1("Next gen server-to-server call\n"); ApiMessage->Header.ClientId = NtCurrentTeb()->ClientId; Status = CsrServerApiRoutine(&ApiMessage->Header, &ApiMessage->Header); @@ -366,10 +365,10 @@ CsrClientConnectToServer(PWSTR ObjectDirectory, InsideCsrProcess = (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE); /* Now we can check if we are inside or not */ - if (InsideCsrProcess && !UsingOldCsr) + if (InsideCsrProcess) { /* We're inside, so let's find csrsrv */ - DbgBreakPoint(); + DPRINT1("Next-GEN CSRSS support\n"); RtlInitUnicodeString(&CsrSrvName, L"csrsrv"); Status = LdrGetDllHandle(NULL, NULL, diff --git a/reactos/dll/win32/kernel32/client/proc.c b/reactos/dll/win32/kernel32/client/proc.c index f4f54b4eff4..b3e200ea194 100644 --- a/reactos/dll/win32/kernel32/client/proc.c +++ b/reactos/dll/win32/kernel32/client/proc.c @@ -513,7 +513,7 @@ BasepNotifyCsrOfCreation(ULONG dwCreationFlags, sizeof(CSR_API_MESSAGE)); if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) { - DPRINT1("Failed to tell csrss about new process\n"); + DPRINT1("Failed to tell csrss about new process: %lx %lx\n", Status, CsrRequest.Status); return CsrRequest.Status; } diff --git a/reactos/subsystems/csr/csrsrv/process.c b/reactos/subsystems/csr/csrsrv/process.c index 91fe42bef98..87201a85b3c 100644 --- a/reactos/subsystems/csr/csrsrv/process.c +++ b/reactos/subsystems/csr/csrsrv/process.c @@ -1074,7 +1074,7 @@ CsrLockProcessByClientId(IN HANDLE Pid, { PLIST_ENTRY NextEntry; PCSR_PROCESS CurrentProcess = NULL; - NTSTATUS Status = STATUS_UNSUCCESSFUL; + NTSTATUS Status; /* Acquire the lock */ CsrAcquireProcessLock(); @@ -1084,31 +1084,37 @@ CsrLockProcessByClientId(IN HANDLE Pid, *CsrProcess = NULL; /* Setup the List Pointers */ - NextEntry = CsrRootProcess->ListLink.Flink; - while (NextEntry != &CsrRootProcess->ListLink) + NextEntry = &CsrRootProcess->ListLink; + do { /* Get the Process */ CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); /* Check for PID Match */ - if (CurrentProcess->ClientId.UniqueProcess == Pid) break; + if (CurrentProcess->ClientId.UniqueProcess == Pid) + { + Status = STATUS_SUCCESS; + break; + } /* Next entry */ NextEntry = NextEntry->Flink; - } + } while (NextEntry != &CsrRootProcess->ListLink); /* Check if we didn't find it in the list */ - if (NextEntry == &CsrRootProcess->ListLink) + if (!NT_SUCCESS(Status)) { /* Nothing found, release the lock */ CsrReleaseProcessLock(); - return Status; } - - /* Lock the found process and return it */ - Status = STATUS_SUCCESS; - CurrentProcess->ReferenceCount++; - *CsrProcess = CurrentProcess; + else + { + /* Lock the found process and return it */ + CsrLockedReferenceProcess(CurrentProcess); + *CsrProcess = CurrentProcess; + } + + /* Return the result */ return Status; } diff --git a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c index 57782fd9815..a6eb0dd09e4 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c +++ b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c @@ -113,6 +113,128 @@ CsrHandleHardError(IN PCSR_THREAD ThreadData, CallHardError(ThreadData, Message); } +/*++ + * @name CsrCallServerFromServer + * @implemented NT4 + * + * The CsrCallServerFromServer routine calls a CSR API from within a server. + * It avoids using LPC messages since the request isn't coming from a client. + * + * @param ReceiveMsg + * Pointer to the CSR API Message to send to the server. + * + * @param ReplyMsg + * Pointer to the CSR API Message to receive from the server. + * + * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION + * if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there + * was a problem executing the API. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg, + PCSR_API_MESSAGE ReplyMsg) +{ +#if 0 // real code + ULONG ServerId; + PCSR_SERVER_DLL ServerDll; + ULONG ApiId; + ULONG Reply; + NTSTATUS Status; + + /* Get the Server ID */ + ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode); + + /* Make sure that the ID is within limits, and the Server DLL loaded */ + if ((ServerId >= CSR_SERVER_DLL_MAX) || + (!(ServerDll = CsrLoadedServerDll[ServerId]))) + { + /* We are beyond the Maximum Server ID */ + DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll); + ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; + return STATUS_ILLEGAL_FUNCTION; + } + else + { + /* Get the API ID */ + ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode); + + /* Normalize it with our Base ID */ + ApiId -= ServerDll->ApiBase; + + /* Make sure that the ID is within limits, and the entry exists */ + if ((ApiId >= ServerDll->HighestApiSupported) || + ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId]))) + { + /* We are beyond the Maximum API ID, or it doesn't exist */ + DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an " + "invalid API to call from the server.\n", + ServerDll->ValidTable[ApiId], + ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ? + ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name); + DbgBreakPoint(); + ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; + return STATUS_ILLEGAL_FUNCTION; + } + } + + if (CsrDebug & 2) + { + DPRINT1("CSRSS: %s Api Request received from server process\n", + ServerDll->NameTable[ApiId]); + } + + /* Validation complete, start SEH */ + _SEH2_TRY + { + /* Call the API and get the result */ + Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply); + + /* Return the result, no matter what it is */ + ReplyMsg->Status = Status; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* If we got an exception, return access violation */ + ReplyMsg->Status = STATUS_ACCESS_VIOLATION; + } + _SEH2_END; + + /* Return success */ + return STATUS_SUCCESS; +#else // Hacky reactos code + PCSR_PROCESS ProcessData; + + /* Get the Process Data */ + ProcessData = CsrGetProcessData(ReceiveMsg->Header.ClientId.UniqueProcess); + 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 + { + /* Call the API and get the result */ + CsrApiCallHandler(ProcessData, ReplyMsg); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* If we got an exception, return access violation */ + ReplyMsg->Status = STATUS_ACCESS_VIOLATION; + } + _SEH2_END; + + /* Return success */ + return STATUS_SUCCESS; +#endif +} + /*++ * @name CsrApiPortInitialize * diff --git a/reactos/subsystems/win32/csrss/csrsrv/csrsrv.spec b/reactos/subsystems/win32/csrss/csrsrv/csrsrv.spec index 0be8c898aba..51e4b1fe9d0 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/csrsrv.spec +++ b/reactos/subsystems/win32/csrss/csrsrv/csrsrv.spec @@ -1,5 +1,5 @@ @ stdcall CsrAddStaticServerThread(ptr ptr long) -;@ stdcall CsrCallServerFromServer(ptr ptr) +@ stdcall CsrCallServerFromServer(ptr ptr) ;@ stdcall CsrConnectToUser() ;@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr) ;@ stdcall CsrCreateRemoteThread(ptr ptr) diff --git a/reactos/subsystems/win32/csrss/csrsrv/procsup.c b/reactos/subsystems/win32/csrss/csrsrv/procsup.c index f2e33ba31fa..712e3b47b4d 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/procsup.c +++ b/reactos/subsystems/win32/csrss/csrsrv/procsup.c @@ -810,6 +810,7 @@ CsrLockProcessByClientId(IN HANDLE Pid, { PLIST_ENTRY NextEntry; PCSR_PROCESS CurrentProcess = NULL; + NTSTATUS Status; /* Acquire the lock */ CsrAcquireProcessLock(); @@ -819,31 +820,38 @@ CsrLockProcessByClientId(IN HANDLE Pid, *CsrProcess = NULL; /* Setup the List Pointers */ - NextEntry = CsrRootProcess->ListLink.Flink; - while (NextEntry != &CsrRootProcess->ListLink) + NextEntry = &CsrRootProcess->ListLink; + do { /* Get the Process */ CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); /* Check for PID Match */ - if (CurrentProcess->ClientId.UniqueProcess == Pid) break; + if (CurrentProcess->ClientId.UniqueProcess == Pid) + { + Status = STATUS_SUCCESS; + break; + } /* Next entry */ NextEntry = NextEntry->Flink; - } + } while (NextEntry != &CsrRootProcess->ListLink); /* Check if we didn't find it in the list */ - if (NextEntry == &CsrRootProcess->ListLink) + if (!NT_SUCCESS(Status)) { /* Nothing found, release the lock */ CsrReleaseProcessLock(); - return STATUS_UNSUCCESSFUL; } - - /* Lock the found process and return it */ - CsrLockedReferenceProcess(CurrentProcess); - *CsrProcess = CurrentProcess; - return STATUS_SUCCESS; + else + { + /* Lock the found process and return it */ + CsrLockedReferenceProcess(CurrentProcess); + *CsrProcess = CurrentProcess; + } + + /* Return the result */ + return Status; } /* EOF */