diff --git a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c index 4955a89ab71..41a11181c45 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c +++ b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c @@ -19,6 +19,7 @@ static unsigned ApiDefinitionsCount = 0; static PCSRSS_API_DEFINITION ApiDefinitions = NULL; +UNICODE_STRING CsrApiPortName; /* FUNCTIONS *****************************************************************/ @@ -303,6 +304,129 @@ CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL, return STATUS_SUCCESS; } +/*++ + * @name CsrApiPortInitialize + * + * The CsrApiPortInitialize routine initializes the LPC Port used for + * communications with the Client/Server Runtime (CSR) and initializes the + * static thread that will handle connection requests and APIs. + * + * @param None + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrApiPortInitialize(VOID) +{ + ULONG Size; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE hRequestEvent, hThread; + CLIENT_ID ClientId; + PLIST_ENTRY ListHead, NextEntry; + PCSR_THREAD ServerThread; + + /* Calculate how much space we'll need for the Port Name */ + Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR); + + /* Create the buffer for it */ + CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); + if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY; + + /* Setup the rest of the empty string */ + CsrApiPortName.Length = 0; + CsrApiPortName.MaximumLength = (USHORT)Size; + RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName); + RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP); + RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME); + if (CsrDebug & 1) + { + DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName); + DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n", + sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE)); + } + + /* FIXME: Create a Security Descriptor */ + + /* Initialize the Attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &CsrApiPortName, + 0, + NULL, + NULL /* FIXME*/); + + /* Create the Port Object */ + Status = NtCreatePort(&hApiPort, //&CsrApiPort, + &ObjectAttributes, + sizeof(CSR_CONNECTION_INFO), + sizeof(CSR_API_MESSAGE), + 16 * PAGE_SIZE); + if (NT_SUCCESS(Status)) + { + /* Create the event the Port Thread will use */ + Status = NtCreateEvent(&hRequestEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (NT_SUCCESS(Status)) + { + /* Create the Request Thread */ + Status = RtlCreateUserThread(NtCurrentProcess(), + NULL, + TRUE, + 0, + 0, + 0, + (PVOID)ClientConnectionThread,//CsrApiRequestThread, + (PVOID)hRequestEvent, + &hThread, + &ClientId); + if (NT_SUCCESS(Status)) + { + /* Add this as a static thread to CSRSRV */ + CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread); + + /* Get the Thread List Pointers */ + ListHead = &CsrRootProcess->ThreadList; + NextEntry = ListHead->Flink; + + /* Start looping the list */ + while (NextEntry != ListHead) + { + /* Get the Thread */ + ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link); + + /* Start it up */ + Status = NtResumeThread(ServerThread->ThreadHandle, NULL); + + /* Is this a Server Thread? */ + if (ServerThread->Flags & CsrThreadIsServerThread) + { + /* If so, then wait for it to initialize */ + Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL); + ASSERT(NT_SUCCESS(Status)); + } + + /* Next thread */ + NextEntry = NextEntry->Flink; + } + + /* We don't need this anymore */ + NtClose(hRequestEvent); + } + } + } + + /* Return */ + return Status; +} + PBASE_STATIC_SERVER_DATA BaseStaticServerData; NTSTATUS @@ -685,8 +809,7 @@ BasepFakeStaticServerData(VOID) } NTSTATUS WINAPI -CsrpHandleConnectionRequest (PPORT_MESSAGE Request, - IN HANDLE hApiListenPort) +CsrpHandleConnectionRequest (PPORT_MESSAGE Request) { NTSTATUS Status; HANDLE ServerPort = NULL, ServerThread = NULL; @@ -780,7 +903,7 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request, 0, 0, (PTHREAD_START_ROUTINE)ClientConnectionThread, - ServerPort, + NULL, & ServerThread, &ClientId); if (!NT_SUCCESS(Status)) @@ -849,74 +972,130 @@ CsrConnectToUser(VOID) VOID WINAPI -ClientConnectionThread(HANDLE ServerPort) +ClientConnectionThread(IN PVOID Parameter) { + PTEB Teb = NtCurrentTeb(); + LARGE_INTEGER TimeOut; NTSTATUS Status; BYTE RawRequest[LPC_MAX_DATA_LENGTH]; PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest; PCSR_API_MESSAGE Reply; PCSR_PROCESS ProcessData; PCSR_THREAD ServerThread; + ULONG MessageType; DPRINT("CSR: %s called\n", __FUNCTION__); + /* Setup LPC loop port and message */ + Reply = NULL; +// ReplyPort = CsrApiPort; + /* Connect to user32 */ while (!CsrConnectToUser()) { + /* Set up the timeout for the connect (30 seconds) */ + TimeOut.QuadPart = -30 * 1000 * 1000 * 10; + /* Keep trying until we get a response */ - NtCurrentTeb()->Win32ClientInfo[0] = 0; - //NtDelayExecution(FALSE, &TimeOut); + Teb->Win32ClientInfo[0] = 0; + NtDelayExecution(FALSE, &TimeOut); } - /* Reply must be NULL at the first call to NtReplyWaitReceivePort */ - ServerThread = NtCurrentTeb()->CsrClientThread; - Reply = NULL; + /* Get our thread */ + ServerThread = Teb->CsrClientThread; - /* Loop and reply/wait for a new message */ - for (;;) + /* If we got an event... */ + if (Parameter) { + /* Set it, to let stuff waiting on us load */ + Status = NtSetEvent((HANDLE)Parameter, NULL); + ASSERT(NT_SUCCESS(Status)); + + /* Increase the Thread Counts */ + //_InterlockedIncrement(&CsrpStaticThreadCount); + //_InterlockedIncrement(&CsrpDynamicThreadTotal); + } + + /* Now start the loop */ + while (TRUE) + { + /* Make sure the real CID is set */ + Teb->RealClientId = Teb->ClientId; + + /* Debug check */ + if (Teb->CountOfOwnedCriticalSections) + { + DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n", + Teb->CountOfOwnedCriticalSections); + DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n", + &Request, Reply); + DbgBreakPoint(); + } + /* Send the reply and wait for a new request */ Status = NtReplyWaitReceivePort(hApiPort, 0, &Reply->Header, &Request->Header); - /* Client died, continue */ - if (Status == STATUS_INVALID_CID) + /* Check if we didn't get success */ + if (Status != STATUS_SUCCESS) { - Reply = NULL; - continue; - } + /* Was it a failure or another success code? */ + if (!NT_SUCCESS(Status)) + { + /* Check for specific status cases */ + if ((Status != STATUS_INVALID_CID) && + (Status != STATUS_UNSUCCESSFUL))// && +// ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort))) + { + /* Notify the debugger */ + DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); + //DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort); + } - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status); - break; + /* We failed big time, so start out fresh */ + Reply = NULL; + //ReplyPort = CsrApiPort; + continue; + } + else + { + /* A bizare "success" code, just try again */ + DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status); + continue; + } } + + /* Use whatever Client ID we got */ + Teb->RealClientId = Request->Header.ClientId; + + /* Get the Message Type */ + MessageType = Request->Header.u2.s2.Type; /* If the connection was closed, handle that */ - if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED) + if (MessageType == LPC_PORT_CLOSED) { DPRINT("Port died, oh well\n"); CsrFreeProcessData( Request->Header.ClientId.UniqueProcess ); break; } - if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST) + if (MessageType == LPC_CONNECTION_REQUEST) { - CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort); + CsrpHandleConnectionRequest((PPORT_MESSAGE)Request); Reply = NULL; continue; } - if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED) + if (MessageType == LPC_CLIENT_DIED) { DPRINT("Client died, oh well\n"); Reply = NULL; continue; } - if ((Request->Header.u2.s2.Type != LPC_ERROR_EVENT) && - (Request->Header.u2.s2.Type != LPC_REQUEST)) + if ((MessageType != LPC_ERROR_EVENT) && + (MessageType != LPC_REQUEST)) { DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type); Reply = NULL; @@ -932,7 +1111,7 @@ ClientConnectionThread(HANDLE ServerPort) if (ProcessData == NULL) { DPRINT1("Message %d: Unable to find data for process 0x%x\n", - Request->Header.u2.s2.Type, + MessageType, Request->Header.ClientId.UniqueProcess); break; } @@ -944,7 +1123,7 @@ ClientConnectionThread(HANDLE ServerPort) } /* Check if we got a hard error */ - if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT) + if (MessageType == LPC_ERROR_EVENT) { /* Call the Handler */ CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request); @@ -972,7 +1151,9 @@ ClientConnectionThread(HANDLE ServerPort) // NtClose(ServerPort); DPRINT("CSR: %s done\n", __FUNCTION__); - RtlExitUserThread(STATUS_SUCCESS); + /* We're out of the loop for some reason, terminate! */ + NtTerminateThread(NtCurrentThread(), Status); + //return Status; } /*++ diff --git a/reactos/subsystems/win32/csrss/csrsrv/init.c b/reactos/subsystems/win32/csrss/csrsrv/init.c index 3bdedb3b52a..84b324aee53 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/init.c +++ b/reactos/subsystems/win32/csrss/csrsrv/init.c @@ -176,57 +176,6 @@ CSRSS_API_DEFINITION NativeDefinitions[] = { 0, 0, NULL } }; -static NTSTATUS WINAPI -CsrpCreateListenPort (IN LPWSTR Name, - IN OUT PHANDLE Port, - IN PTHREAD_START_ROUTINE ListenThread) -{ - NTSTATUS Status = STATUS_SUCCESS; - OBJECT_ATTRIBUTES PortAttributes; - UNICODE_STRING PortName; - HANDLE ServerThread; - CLIENT_ID ClientId; - - DPRINT("CSR: %s called\n", __FUNCTION__); - - RtlInitUnicodeString (& PortName, Name); - InitializeObjectAttributes (& PortAttributes, - & PortName, - 0, - NULL, - NULL); - Status = NtCreatePort ( Port, - & PortAttributes, - sizeof(SB_CONNECTION_INFO), - sizeof(SB_API_MSG), - 32 * sizeof(SB_API_MSG)); - if(!NT_SUCCESS(Status)) - { - DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n", - __FUNCTION__, Status); - return Status; - } - Status = RtlCreateUserThread(NtCurrentProcess(), - NULL, - TRUE, - 0, - 0, - 0, - (PTHREAD_START_ROUTINE) ListenThread, - *Port, - &ServerThread, - &ClientId); - - if (ListenThread == (PVOID)ClientConnectionThread) - { - CsrAddStaticServerThread(ServerThread, &ClientId, 0); - } - - NtResumeThread(ServerThread, NULL); - NtClose(ServerThread); - return Status; -} - /* === INIT ROUTINES === */ VOID @@ -1150,10 +1099,13 @@ CsrServerInitialization(IN ULONG ArgumentCount, DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrApiRegisterDefinitions", Status); } - Status = CsrpCreateListenPort(L"\\Windows\\ApiPort", &hApiPort, (PTHREAD_START_ROUTINE)ClientConnectionThread); + /* Now initialize our API Port */ + Status = CsrApiPortInitialize(); if (!NT_SUCCESS(Status)) { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateApiPort", Status); + DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; } Status = CsrpInitWin32Csr(); diff --git a/reactos/subsystems/win32/csrss/include/api.h b/reactos/subsystems/win32/csrss/include/api.h index fb742716375..d9e3cdac356 100644 --- a/reactos/subsystems/win32/csrss/include/api.h +++ b/reactos/subsystems/win32/csrss/include/api.h @@ -235,6 +235,12 @@ extern HANDLE CsrSbApiPort; extern LIST_ENTRY CsrThreadHashTable[256]; extern PCSR_PROCESS CsrRootProcess; extern RTL_CRITICAL_SECTION ProcessDataLock, CsrWaitListsLock; +extern UNICODE_STRING CsrDirectoryName; +extern ULONG CsrDebug; + +NTSTATUS +NTAPI +CsrApiPortInitialize(VOID); BOOLEAN NTAPI