reactos/subsystems/win32/csrss/csrsrv/api/wapi.c
Amine Khaldi c424146e2c Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
2010-07-24 18:52:44 +00:00

467 lines
14 KiB
C

/* $Id$
*
* reactos/subsys/csrss/api/wapi.c
*
* CSRSS port message processing
*
* ReactOS Operating System
*
*/
/* INCLUDES ******************************************************************/
#include <srv.h>
#define NDEBUG
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
extern HANDLE hApiPort;
HANDLE CsrssApiHeap = (HANDLE) 0;
static unsigned ApiDefinitionsCount = 0;
static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
/* FUNCTIONS *****************************************************************/
NTSTATUS FASTCALL
CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
{
unsigned NewCount;
PCSRSS_API_DEFINITION Scan;
PCSRSS_API_DEFINITION New;
DPRINT("CSR: %s called\n", __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)
{
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; 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
{
Request->Status = (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
}
return;
}
}
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;
}
BOOL
CallHardError(IN PCSRSS_PROCESS_DATA ProcessData,
IN PHARDERROR_MSG HardErrorMessage);
static
VOID
NTAPI
CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData,
IN OUT PHARDERROR_MSG Message)
{
DPRINT1("CSR: received hard error %lx\n", Message->Status);
/* Call the hard error handler in win32csr */
(VOID)CallHardError(ProcessData, Message);
}
NTSTATUS WINAPI
CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
IN HANDLE hApiListenPort)
{
NTSTATUS Status;
HANDLE ServerPort = NULL, ServerThread = NULL;
PCSRSS_PROCESS_DATA ProcessData = NULL;
REMOTE_PORT_VIEW LpcRead;
CLIENT_ID ClientId;
LpcRead.Length = sizeof(LpcRead);
ServerPort = NULL;
DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
Status = NtAcceptConnectPort(&ServerPort,
NULL,
Request,
TRUE,
0,
& LpcRead);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR: NtAcceptConnectPort() failed\n");
return Status;
}
ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess);
if (ProcessData == NULL)
{
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;
return Status;
}
}
ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
ProcessData->ServerCommunicationPort = ServerPort;
Status = NtCompleteConnectPort(ServerPort);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR: NtCompleteConnectPort() failed\n");
return Status;
}
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
(PTHREAD_START_ROUTINE)ClientConnectionThread,
ServerPort,
& ServerThread,
&ClientId);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR: Unable to create server thread\n");
return Status;
}
CsrAddStaticServerThread(ServerThread, &ClientId, 0);
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
Status = STATUS_SUCCESS;
DPRINT("CSR: %s done\n", __FUNCTION__);
return Status;
}
PCSR_THREAD
NTAPI
CsrConnectToUser(VOID)
{
PTEB Teb = NtCurrentTeb();
PCSR_THREAD CsrThread;
#if 0
NTSTATUS Status;
ANSI_STRING DllName;
UNICODE_STRING TempName;
HANDLE hUser32;
STRING StartupName;
/* Check if we didn't already find it */
if (!CsrClientThreadSetup)
{
/* Get the DLL Handle for user32.dll */
RtlInitAnsiString(&DllName, "user32");
RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
Status = LdrGetDllHandle(NULL,
NULL,
&TempName,
&hUser32);
RtlFreeUnicodeString(&TempName);
/* If we got teh handle, get the Client Thread Startup Entrypoint */
if (NT_SUCCESS(Status))
{
RtlInitAnsiString(&StartupName,"ClientThreadSetup");
Status = LdrGetProcedureAddress(hUser32,
&StartupName,
0,
(PVOID)&CsrClientThreadSetup);
}
}
/* Connect to user32 */
CsrClientThreadSetup();
#endif
/* Save pointer to this thread in TEB */
CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
if (CsrThread) Teb->CsrClientThread = CsrThread;
/* Return it */
return CsrThread;
}
VOID
WINAPI
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;
PCSR_THREAD ServerThread;
DPRINT("CSR: %s called\n", __FUNCTION__);
/* Connect to user32 */
while (!CsrConnectToUser())
{
/* Keep trying until we get a response */
NtCurrentTeb()->Win32ClientInfo[0] = 0;
//NtDelayExecution(FALSE, &TimeOut);
}
/* Reply must be NULL at the first call to NtReplyWaitReceivePort */
ServerThread = NtCurrentTeb()->CsrClientThread;
Reply = NULL;
/* Loop and reply/wait for a new message */
for (;;)
{
/* 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)
{
Reply = NULL;
continue;
}
if (!NT_SUCCESS(Status))
{
DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
break;
}
/* If the connection was closed, handle that */
if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
{
DPRINT("Port died, oh well\n");
CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
break;
}
if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
{
CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
Reply = NULL;
continue;
}
if (Request->Header.u2.s2.Type == 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))
{
DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
Reply = NULL;
continue;
}
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",
Request->Header.u2.s2.Type,
Request->Header.ClientId.UniqueProcess);
break;
}
if (ProcessData->Terminated)
{
DPRINT1("Message %d: process %d already terminated\n",
Request->Type, Request->Header.ClientId.UniqueProcess);
continue;
}
/* Check if we got a hard error */
if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
{
/* Call the Handler */
CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
}
else
{
PCSR_THREAD Thread;
PCSRSS_PROCESS_DATA Process = NULL;
//DPRINT1("locate thread %lx/%lx\n", Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
Thread = CsrLocateThreadByClientId(&Process, &Request->Header.ClientId);
//DPRINT1("Thread found: %p %p\n", Thread, Process);
/* Call the Handler */
if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
CsrApiCallHandler(ProcessData, Request);
if (Thread) NtCurrentTeb()->CsrClientThread = ServerThread;
}
/* Send back the reply */
Reply = Request;
}
/* Close the port and exit the thread */
// NtClose(ServerPort);
DPRINT("CSR: %s done\n", __FUNCTION__);
RtlExitUserThread(STATUS_SUCCESS);
}
/**********************************************************************
* 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 WINAPI
ServerSbApiPortThread (HANDLE hSbApiPortListen)
{
HANDLE hConnectedPort = (HANDLE) 0;
PORT_MESSAGE Request;
PVOID Context = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PPORT_MESSAGE Reply = NULL;
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,
NULL,
&Request,
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");
/*
* 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");
}
}
}
}
DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
if(hConnectedPort) NtClose (hConnectedPort);
NtClose (hSbApiPortListen);
NtTerminateThread (NtCurrentThread(), Status);
return 0;
}
/* EOF */