- Missed one change
[reactos.git] / reactos / subsys / csrss / api / wapi.c
index 888eb98..9a0f83d 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: wapi.c,v 1.30 2003/08/07 11:47:33 silverblade 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.ClientId.UniqueProcess );
-            NtClose(ServerPort);
-            NtTerminateThread(NtCurrentThread(), STATUS_SUCCESS);
-            continue;
-         }
-       
-       Request = (PCSRSS_API_REQUEST)&LpcRequest;
-       Reply = (PCSRSS_API_REPLY)&LpcReply;
-       
-       ProcessData = CsrGetProcessData(
-                                 (ULONG)LpcRequest.Header.ClientId.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.ClientId.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 */