-/* $Id: wapi.c,v 1.29 2003/07/29 23:03:01 jimtabor Exp $
- *
+/* $Id$
+ *
* reactos/subsys/csrss/api/wapi.c
*
- * Initialize the CSRSS subsystem server process.
+ * CSRSS port message processing
*
* ReactOS Operating System
*
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
-#include <windows.h>
-#include <ntdll/rtl.h>
-#include <csrss/csrss.h>
-#include <debug.h>
+#include <csrss.h>
-#include "api.h"
+#define NDEBUG
+#include <debug.h>
/* GLOBALS *******************************************************************/
-HANDLE CsrssApiHeap;
+HANDLE CsrssApiHeap = (HANDLE) 0;
+
+static unsigned ApiDefinitionsCount = 0;
+static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
/* FUNCTIONS *****************************************************************/
-typedef NTSTATUS (*CsrFunc)( PCSRSS_PROCESS_DATA, PCSRSS_API_REQUEST, PCSRSS_API_REPLY );
-
-static const CsrFunc CsrFuncs[] = {
- CsrCreateProcess,
- CsrTerminateProcess,
- CsrWriteConsole,
- CsrReadConsole,
- CsrAllocConsole,
- CsrFreeConsole,
- CsrConnectProcess,
- CsrGetScreenBufferInfo,
- CsrSetCursor,
- CsrFillOutputChar,
- CsrReadInputEvent,
- CsrWriteConsoleOutputChar,
- CsrWriteConsoleOutputAttrib,
- CsrFillOutputAttrib,
- CsrGetCursorInfo,
- CsrSetCursorInfo,
- CsrSetTextAttrib,
- CsrGetConsoleMode,
- CsrSetConsoleMode,
- CsrCreateScreenBuffer,
- CsrSetScreenBuffer,
- CsrSetTitle,
- CsrGetTitle,
- CsrWriteConsoleOutput,
- CsrFlushInputBuffer,
- CsrScrollConsoleScreenBuffer,
- CsrReadConsoleOutputChar,
- CsrReadConsoleOutputAttrib,
- CsrGetNumberOfConsoleInputEvents,
- CsrRegisterServicesProcess,
- CsrExitReactos,
- CsrGetShutdownParameters,
- CsrSetShutdownParameters,
- CsrPeekConsoleInput,
- CsrReadConsoleOutput,
- CsrWriteConsoleInput,
- CsrGetInputHandle,
- CsrGetOutputHandle,
- CsrCloseHandle,
- CsrVerifyHandle,
- CsrDuplicateHandle,
- CsrHardwareStateProperty,
- 0 };
-
-static void Thread_Api2(HANDLE ServerPort)
+NTSTATUS FASTCALL
+CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
{
- NTSTATUS Status;
- LPC_MAX_MESSAGE LpcReply;
- LPC_MAX_MESSAGE LpcRequest;
- PCSRSS_API_REQUEST Request;
- PCSRSS_PROCESS_DATA ProcessData;
- PCSRSS_API_REPLY Reply;
-
- Reply = NULL;
-
- for (;;)
- {
- Status = NtReplyWaitReceivePort(ServerPort,
- 0,
- &Reply->Header,
- &LpcRequest.Header);
- if ( !NT_SUCCESS( Status ) )
- {
- DisplayString(L"CSR: NtReplyWaitReceivePort failed\n");
- }
-
- if ( LpcRequest.Header.MessageType == LPC_PORT_CLOSED )
+ unsigned NewCount;
+ PCSRSS_API_DEFINITION Scan;
+ PCSRSS_API_DEFINITION New;
- {
- CsrFreeProcessData( (ULONG)LpcRequest.Header.Cid.UniqueProcess );
- NtClose(ServerPort);
- NtTerminateThread(NtCurrentThread(), STATUS_SUCCESS);
- continue;
- }
-
- Request = (PCSRSS_API_REQUEST)&LpcRequest;
- Reply = (PCSRSS_API_REPLY)&LpcReply;
-
- ProcessData = CsrGetProcessData(
- (ULONG)LpcRequest.Header.Cid.UniqueProcess);
-
-// DisplayString(L"CSR: Received request\n");
- if( Request->Type >= (sizeof( CsrFuncs ) / sizeof( CsrFunc )) - 1 )
- Reply->Status = STATUS_INVALID_SYSTEM_SERVICE;
- else CsrFuncs[ Request->Type ]( ProcessData, Request, Reply );
- }
+ DPRINT("CSR: %s called", __FUNCTION__);
+
+ NewCount = 0;
+ for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
+ {
+ NewCount++;
+ }
+
+ New = RtlAllocateHeap(CsrssApiHeap, 0,
+ (ApiDefinitionsCount + NewCount)
+ * sizeof(CSRSS_API_DEFINITION));
+ if (NULL == New)
+ {
+ DPRINT1("Unable to allocate memory\n");
+ return STATUS_NO_MEMORY;
+ }
+ if (0 != ApiDefinitionsCount)
+ {
+ RtlCopyMemory(New, ApiDefinitions,
+ ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
+ RtlFreeHeap(CsrssApiHeap, 0, ApiDefinitions);
+ }
+ RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
+ NewCount * sizeof(CSRSS_API_DEFINITION));
+ ApiDefinitions = New;
+ ApiDefinitionsCount += NewCount;
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+FASTCALL
+CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData,
+ PCSR_API_MESSAGE Request)
+{
+ BOOL Found = FALSE;
+ unsigned DefIndex;
+ ULONG Type;
+
+ DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
+ Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
+ DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
+
+ /* FIXME: Extract DefIndex instead of looping */
+ for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++)
+ {
+ if (ApiDefinitions[DefIndex].Type == Type)
+ {
+ if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize)
+ {
+ DPRINT1("Request type %d min request size %d actual %d\n",
+ Type, ApiDefinitions[DefIndex].MinRequestSize,
+ Request->Header.u1.s1.DataLength);
+ Request->Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
+ Found = TRUE;
+ }
+ }
+ }
+ if (! Found)
+ {
+ DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
+ Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+ Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+ Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
+ }
+}
+
+static
+VOID
+STDCALL
+ClientConnectionThread(HANDLE ServerPort)
+{
+ NTSTATUS Status;
+ BYTE RawRequest[LPC_MAX_DATA_LENGTH];
+ PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
+ PCSR_API_MESSAGE Reply;
+ PCSRSS_PROCESS_DATA ProcessData;
+
+ DPRINT("CSR: %s called", __FUNCTION__);
+
+ /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
+ Reply = NULL;
+
+ /* Loop and reply/wait for a new message */
+ for (;;)
+ {
+ /* Send the reply and wait for a new request */
+ Status = NtReplyWaitReceivePort(ServerPort,
+ 0,
+ &Reply->Header,
+ &Request->Header);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: NtReplyWaitReceivePort failed\n");
+ break;
+ }
+
+ /* If the connection was closed, handle that */
+ if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
+ {
+ CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
+ break;
+ }
+
+ DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
+ Request->Type,
+ Request->Header.ClientId.UniqueProcess);
+
+ /* Get the Process Data */
+ ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
+ if (ProcessData == NULL)
+ {
+ DPRINT1("CSR: Message %d: Unable to find data for process 0x%x\n",
+ Request->Header.u2.s2.Type,
+ Request->Header.ClientId.UniqueProcess);
+ break;
+ }
+
+ /* Call the Handler */
+ CsrApiCallHandler(ProcessData, Request);
+
+ /* Send back the reply */
+ Reply = Request;
+ }
+
+ /* Close the port and exit the thread */
+ NtClose(ServerPort);
+ RtlExitUserThread(STATUS_SUCCESS);
}
/**********************************************************************
* NAME
- * Thread_Api
+ * ServerApiPortThread/1
*
* DESCRIPTION
* Handle connection requests from clients to the port
* "\Windows\ApiPort".
*/
-void Thread_Api(PVOID PortHandle)
+DWORD STDCALL
+ServerApiPortThread (PVOID PortHandle)
{
- NTSTATUS Status;
- LPC_MAX_MESSAGE Request;
- HANDLE ServerPort;
- HANDLE ServerThread;
- PCSRSS_PROCESS_DATA ProcessData;
-
+ NTSTATUS Status = STATUS_SUCCESS;
+ BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)];
+ PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest;
+ HANDLE hApiListenPort = * (PHANDLE) PortHandle;
+ HANDLE ServerPort = (HANDLE) 0;
+ HANDLE ServerThread = (HANDLE) 0;
+ PCSRSS_PROCESS_DATA ProcessData = NULL;
+
CsrInitProcessData();
-
+
+ DPRINT("CSR: %s called", __FUNCTION__);
+
for (;;)
{
- LPC_SECTION_READ LpcRead;
+ REMOTE_PORT_VIEW LpcRead;
+ ServerPort = NULL;
- Status = NtListenPort(PortHandle, &Request.Header);
+ Status = NtListenPort (hApiListenPort, Request);
if (!NT_SUCCESS(Status))
{
- DisplayString(L"CSR: NtListenPort() failed\n");
- NtTerminateThread(NtCurrentThread(), Status);
+ DPRINT1("CSR: NtListenPort() failed, status=%x\n", Status);
+ break;
}
-
- Status = NtAcceptConnectPort(&ServerPort,
- PortHandle,
+ Status = NtAcceptConnectPort(& ServerPort,
+ hApiListenPort,
NULL,
- 1,
+ TRUE,
0,
- &LpcRead);
+ & LpcRead);
if (!NT_SUCCESS(Status))
{
- DisplayString(L"CSR: NtAcceptConnectPort() failed\n");
- NtTerminateThread(NtCurrentThread(), Status);
+ DPRINT1("CSR: NtAcceptConnectPort() failed\n");
+ break;
}
- ProcessData = CsrGetProcessData((ULONG)Request.Header.Cid.UniqueProcess);
+ ProcessData = CsrCreateProcessData(Request->ClientId.UniqueProcess);
+ if (ProcessData == NULL)
+ {
+ DPRINT1("Unable to allocate or find data for process 0x%x\n",
+ Request->ClientId.UniqueProcess);
+ Status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+
ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
-
+
Status = NtCompleteConnectPort(ServerPort);
if (!NT_SUCCESS(Status))
{
- DisplayString(L"CSR: NtCompleteConnectPort() failed\n");
- NtTerminateThread(NtCurrentThread(), Status);
+ DPRINT1("CSR: NtCompleteConnectPort() failed\n");
+ break;
}
-
+
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
0,
- NULL,
- NULL,
- (PTHREAD_START_ROUTINE)Thread_Api2,
+ 0,
+ 0,
+ (PTHREAD_START_ROUTINE)ClientConnectionThread,
ServerPort,
- &ServerThread,
+ & ServerThread,
NULL);
if (!NT_SUCCESS(Status))
{
- DisplayString(L"CSR: Unable to create server thread\n");
- NtClose(ServerPort);
- NtTerminateThread(NtCurrentThread(), Status);
+ DPRINT1("CSR: Unable to create server thread\n");
+ break;
}
NtClose(ServerThread);
}
+ if (ServerPort)
+ {
+ NtClose(ServerPort);
+ }
+ NtClose(PortHandle);
+ NtTerminateThread(NtCurrentThread(), Status);
+ return 0;
+}
+
+/**********************************************************************
+ * NAME
+ * ServerSbApiPortThread/1
+ *
+ * DESCRIPTION
+ * Handle connection requests from SM to the port
+ * "\Windows\SbApiPort". We will accept only one
+ * connection request (from the SM).
+ */
+DWORD STDCALL
+ServerSbApiPortThread (PVOID PortHandle)
+{
+ HANDLE hSbApiPortListen = * (PHANDLE) PortHandle;
+ HANDLE hConnectedPort = (HANDLE) 0;
+ PORT_MESSAGE Request;
+ PVOID Context = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("CSR: %s called\n", __FUNCTION__);
+
+ RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
+ Status = NtListenPort (hSbApiPortListen, & Request);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
+ __FUNCTION__, Status);
+ } else {
+DPRINT("-- 1\n");
+ Status = NtAcceptConnectPort (& hConnectedPort,
+ hSbApiPortListen,
+ NULL,
+ TRUE,
+ NULL,
+ NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
+ __FUNCTION__, Status);
+ } else {
+DPRINT("-- 2\n");
+ Status = NtCompleteConnectPort (hConnectedPort);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
+ __FUNCTION__, Status);
+ } else {
+DPRINT("-- 3\n");
+ PPORT_MESSAGE Reply = NULL;
+ /*
+ * Tell the init thread the SM gave the
+ * green light for boostrapping.
+ */
+ Status = NtSetEvent (hBootstrapOk, NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
+ __FUNCTION__, Status);
+ }
+ /* Wait for messages from the SM */
+DPRINT("-- 4\n");
+ while (TRUE)
+ {
+ Status = NtReplyWaitReceivePort(hConnectedPort,
+ Context,
+ Reply,
+ & Request);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
+ __FUNCTION__, Status);
+ break;
+ }
+ switch (Request.u2.s2.Type)//fix .h PORT_MESSAGE_TYPE(Request))
+ {
+ /* TODO */
+ default:
+ DPRINT1("CSR: %s received message (type=%d)\n",
+ __FUNCTION__, Request.u2.s2.Type);
+ }
+DPRINT("-- 5\n");
+ }
+ }
+ }
+ }
+ DPRINT1("CSR: %s: terminating!\n", __FUNCTION__);
+ if(hConnectedPort) NtClose (hConnectedPort);
+ NtClose (hSbApiPortListen);
+ NtTerminateThread (NtCurrentThread(), Status);
+ return 0;
}
/* EOF */