2025-04-27 07:49:33 -04:00

192 lines
5.9 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
apilistn.c
Abstract:
This module implements the main loop servicing API RPC's.
Author:
Mark Lucovsky (markl) 05-Apr-1989
Revision History:
--*/
#include "psxsrv.h"
NTSTATUS
PsxApiHandleConnectionRequest(
IN PPSX_API_MSG Message
)
{
NTSTATUS Status;
REMOTE_PORT_VIEW ClientView;
BOOLEAN AcceptConnection;
PPSX_API_CONNECTINFO ConnectionInformation = &Message->ConnectionRequest;
HANDLE PortHandle;
PPSX_PROCESS Process;
BOOLEAN TerminateProcess;
AcceptConnection = TRUE;
TerminateProcess = FALSE;
Process = PsxLocateProcessByClientId(&Message->h.ClientId);
if (Process == NULL ||
Message->h.ClientViewSize > PSX_CLIENT_PORT_MEMORY_SIZE) {
AcceptConnection = FALSE;
goto accept;
}
ConnectionInformation->InitialPebPsxData =
Process->InitialPebPsxData;
//
// Now set up Directory Prefixes. There are two cases.
// Process->DirectoryPrefix is remote
// the process is connecting as a result of a fork.
// No action is needed.
// Process->DirectoryPrefix is local
// process is connecting as a result of an exec,
// or the process is connecting as a result of a new
// session. The local directory prefix's are
// propagated to the client
//
if (!IS_DIRECTORY_PREFIX_REMOTE(Process->DirectoryPrefix)) {
PSX_DIRECTORY_PREFIX ClientDirectoryPrefix;
//
// Get the client's directory prefix structure
// so we can figure out where he wants the strings
//
Status = NtReadVirtualMemory(Process->Process,
ConnectionInformation->DirectoryPrefix,
&ClientDirectoryPrefix,
sizeof(ClientDirectoryPrefix), NULL);
if (!NT_SUCCESS(Status)) {
TerminateProcess = TRUE;
goto accept;
}
//
// Make sure the buffer lengths are in sync.
//
if (ClientDirectoryPrefix.NtCurrentWorkingDirectory.MaximumLength
< Process->DirectoryPrefix->NtCurrentWorkingDirectory.Length ||
ClientDirectoryPrefix.PsxRoot.MaximumLength <
Process->DirectoryPrefix->PsxRoot.Length) {
TerminateProcess = TRUE;
goto accept;
}
//
// Push the pathname prefixes out
//
Status = NtWriteVirtualMemory(Process->Process,
ClientDirectoryPrefix.NtCurrentWorkingDirectory.Buffer,
Process->DirectoryPrefix->NtCurrentWorkingDirectory.Buffer,
Process->DirectoryPrefix->NtCurrentWorkingDirectory.Length,
NULL);
if (!NT_SUCCESS(Status)) {
TerminateProcess = TRUE;
goto accept;
}
ClientDirectoryPrefix.NtCurrentWorkingDirectory.Length =
Process->DirectoryPrefix->NtCurrentWorkingDirectory.Length;
Status = NtWriteVirtualMemory(Process->Process,
ClientDirectoryPrefix.PsxRoot.Buffer,
Process->DirectoryPrefix->PsxRoot.Buffer,
Process->DirectoryPrefix->PsxRoot.Length, NULL);
if (!NT_SUCCESS(Status)) {
TerminateProcess = TRUE;
goto accept;
}
ClientDirectoryPrefix.PsxRoot.Length =
Process->DirectoryPrefix->PsxRoot.Length;
//
// Now Push out the modified version of the client's
// directory prefix. We set the length to 0 so getcwd()
// will know to recomput the Posix version of the directory.
//
ClientDirectoryPrefix.PsxCurrentWorkingDirectory.Length = 0;
Status = NtWriteVirtualMemory(Process->Process,
ConnectionInformation->DirectoryPrefix,
&ClientDirectoryPrefix,
sizeof(ClientDirectoryPrefix), NULL);
if (!NT_SUCCESS(Status)) {
TerminateProcess = TRUE;
goto accept;
}
//
// Deallocate the local directory prefix
//
RtlFreeHeap(PsxHeap, 0, Process->DirectoryPrefix->NtCurrentWorkingDirectory.Buffer);
RtlFreeHeap(PsxHeap, 0, Process->DirectoryPrefix->PsxRoot.Buffer);
RtlFreeHeap(PsxHeap, 0, Process->DirectoryPrefix);
Process->DirectoryPrefix = MAKE_DIRECTORY_PREFIX_REMOTE(ConnectionInformation->DirectoryPrefix);
}
accept:
ClientView.Length = sizeof(ClientView);
ClientView.ViewSize = 0;
ClientView.ViewBase = 0;
if (!AcceptConnection) {
KdPrint(( "PSXSS: Refusing connection from client %x.%x (Process %x)\n",
Message->h.ClientId.UniqueProcess,
Message->h.ClientId.UniqueThread,
Process
));
}
Status = NtAcceptConnectPort(&PortHandle, (PVOID)Process,
(PPORT_MESSAGE) Message, AcceptConnection,
NULL, &ClientView);
if (NT_SUCCESS(Status) && AcceptConnection) {
Process->SignalDeliverer =
ConnectionInformation->SignalDeliverer;
Process->NullApiCaller = ConnectionInformation->NullApiCaller;
Process->State = Active;
Process->ClientPort = PortHandle;
Process->ClientViewBase = (PCH)ClientView.ViewBase;
Process->ClientViewBounds = (PCH)ClientView.ViewBase +
ClientView.ViewSize;
Status = NtCompleteConnectPort(PortHandle);
if (!NT_SUCCESS(Status)) {
KdPrint(("PSXSS: NtCompleteConnectPort: 0x%x\n", Status));
}
if (TerminateProcess) {
PsxSignalProcess(Process,SIGKILL);
}
}
return Status;
}