WindowsXP-SP1/base/subsys/posix/psxss/apireqst.c
2020-09-30 16:53:49 +02:00

520 lines
11 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
apireqst.c
Abstract:
This module implements the main loop servicing API RPC's.
Author:
Mark Lucovsky (markl) 05-Apr-1989
Revision History:
--*/
#include "psxsrv.h"
#define NOEXTAPI
#include "wdbgexts.h"
#include "ntdbg.h"
//
// API Dispatch Table
//
PPSX_API_ROUTINE PsxServerApiDispatch[PsxMaxApiNumber] = {
PsxFork,
PsxExec,
PsxWaitPid,
PsxExit,
PsxKill,
PsxSigAction,
PsxSigProcMask,
PsxSigPending,
PsxSigSuspend,
PsxAlarm,
PsxGetIds,
PsxSetUid,
PsxSetGid,
PsxGetGroups,
PsxGetLogin,
PsxCUserId,
PsxSetSid,
PsxSetPGroupId,
PsxUname,
PsxTime,
PsxGetProcessTimes,
PsxTtyName,
PsxIsatty,
PsxSysconf,
PsxOpen,
PsxUmask,
PsxLink,
PsxMkDir,
PsxMkFifo,
PsxRmDir,
PsxRename,
PsxStat,
PsxFStat,
PsxAccess,
PsxChmod,
PsxChown,
PsxUtime,
PsxPathConf,
PsxFPathConf,
PsxPipe,
PsxDup,
PsxDup2,
PsxClose,
PsxRead,
PsxWrite,
PsxFcntl,
PsxLseek,
PsxTcGetAttr,
PsxTcSetAttr,
PsxTcSendBreak,
PsxTcDrain,
PsxTcFlush,
PsxTcFlow,
PsxTcGetPGrp,
PsxTcSetPGrp,
PsxGetPwUid,
PsxGetPwNam,
PsxGetGrGid,
PsxGetGrNam,
PsxUnlink,
PsxReadDir,
PsxFtruncate,
PsxNull
#ifdef PSX_SOCKET
,
PsxSocket,
PsxAccept,
PsxBind,
PsxConnect,
PsxGetPeerName,
PsxGetSockName,
PsxGetSockOpt,
PsxListen,
PsxRecv,
PsxSend,
PsxSendTo,
PsxSetSockOpt,
PsxShutdown
#endif // PSX_SOCKET
};
#if DBG
PSZ PsxServerApiName[PsxMaxApiNumber] = {
"PsxFork",
"PsxExec",
"PsxWaitPid",
"PsxExit",
"PsxKill",
"PsxSigAction",
"PsxSigProcMask",
"PsxSigPending",
"PsxSigSuspend",
"PsxAlarm",
"PsxGetIds",
"PsxSetUid",
"PsxSetGid",
"PsxGetGroups",
"PsxGetLogin",
"PsxCUserId",
"PsxSetSid",
"PsxSetPGroupId",
"PsxUname",
"PsxTime",
"PsxGetProcessTimes",
"PsxTtyName",
"PsxIsatty",
"PsxSysconf",
"PsxOpen",
"PsxUmask",
"PsxLink",
"PsxMkDir",
"PsxMkFifo",
"PsxRmDir",
"PsxRename",
"PsxStat",
"PsxFStat",
"PsxAccess",
"PsxChmod",
"PsxChown",
"PsxUtime",
"PsxPathConf",
"PsxFPathConf",
"PsxPipe",
"PsxDup",
"PsxDup2",
"PsxClose",
"PsxRead",
"PsxWrite",
"PsxFcntl",
"PsxLseek",
"PsxTcGetAttr",
"PsxTcSetAttr",
"PsxTcSendBreak",
"PsxTcDrain",
"PsxTcFlush",
"PsxTcFlow",
"PsxTcGetPGrp",
"PsxTcSetPGrp",
"PsxGetPwUid",
"PsxGetPwNam",
"PsxGetGrGid",
"PsxGetGrNam",
"PsxUnlink",
"PsxReadDir",
"PsxFtruncate",
"PsxNull"
#ifdef PSX_SOCKET
,
"PsxSocket",
"PsxAccept",
"PsxBind",
"PsxConnect",
"PsxGetPeerName",
"PsxGetSockName",
"PsxGetSockOpt",
"PsxListen",
"PsxRecv",
"PsxRecvFrom",
"PsxSend",
"PsxSendTo",
"PsxSetSockOpt",
"PsxShutdown"
#endif // PSX_SOCKET
};
VOID dumpmsg( IN PPSX_API_MSG ReplyMsg);
#endif //DBG
#if _MSC_FULL_VER >= 13008827
#pragma warning(push)
#pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
#endif
NTSTATUS
PsxApiRequestThread(
IN PVOID Parameter
)
{
NTSTATUS Status;
PPSX_PROCESS Process;
PSX_API_MSG ReceiveMsg;
PPSX_API_MSG ReplyMsg;
USHORT MessageType;
PVOID PortContext; // pointer to process structure
KERNEL_USER_TIMES ThreadTime;
ULONG PosixUTime1, PosixUTime2, Remainder, LengthNeeded;
ULONG PosixSTime1, PosixSTime2;
BOOLEAN Reply;
UNREFERENCED_PARAMETER(Parameter);
ReplyMsg = NULL;
while (TRUE) {
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadTimes,
(PVOID)&ThreadTime, sizeof(ThreadTime), &LengthNeeded);
ASSERT(NT_SUCCESS(Status));
PosixUTime1 = RtlExtendedLargeIntegerDivide(
ThreadTime.UserTime, 10000, &Remainder).LowPart;
PosixSTime1 = RtlExtendedLargeIntegerDivide(
ThreadTime.KernelTime, 10000, &Remainder).LowPart;
Status = NtReplyWaitReceivePort(PsxApiPort,
&PortContext, (PPORT_MESSAGE)ReplyMsg,
(PPORT_MESSAGE)&ReceiveMsg);
if (Status != 0) {
if (NT_SUCCESS(Status)) {
continue;
}
if (STATUS_INVALID_CID == Status) {
ReplyMsg = NULL;
continue;
}
KdPrint(("PSXSS: ReceivePort failed: 0x%x\n",
Status));
ReplyMsg = NULL;
continue;
}
MessageType = ReceiveMsg.h.u2.s2.Type;
if (MessageType == LPC_CONNECTION_REQUEST) {
PsxApiHandleConnectionRequest( &ReceiveMsg );
ReplyMsg = NULL;
continue;
}
Process = PsxLocateProcessByClientId(&ReceiveMsg.h.ClientId);
if (NULL == Process) {
if (LPC_CLIENT_DIED == MessageType ||
LPC_PORT_CLOSED == MessageType ||
LPC_ERROR_EVENT == MessageType
) {
ReplyMsg = NULL;
continue;
}
if (LPC_EXCEPTION == MessageType) {
ReplyMsg = &ReceiveMsg;
ReplyMsg->ReturnValue = DBG_CONTINUE;
continue;
}
KdPrint(("PSXSS: msg %d from unknown client: %d, %d\n",
ReceiveMsg.ApiNumber,
ReceiveMsg.h.ClientId.UniqueProcess,
ReceiveMsg.h.ClientId.UniqueThread));
ReceiveMsg.Error = ESRCH;
ReplyMsg = NULL;
continue;
}
//
// For each POSIX API message
// - Validate the API Number
// - Dispatch the call
// - Optionally Reply
//
if (LPC_CLIENT_DIED == MessageType) {
// XXX.mjb: do we need to increment InPsx here?
// XXX.mjb: this exit status should be meaningful.
Exit(Process, (ULONG)-1);
ReplyMsg = NULL; // no one to reply to.
continue;
}
if (LPC_EXCEPTION == MessageType) {
PDBGKM_APIMSG m;
KdPrint(("PSXSS: Pid 0x%x has taken an exception\n",
Process->Pid));
Exit(Process, (ULONG)-1);
//
// XXX.mjb: would be nice to print an error
// message.
//
m = (PDBGKM_APIMSG)&ReceiveMsg;
m->ReturnedStatus = DBG_CONTINUE;
ReplyMsg = &ReceiveMsg;
ReplyMsg->ReturnValue = DBG_CONTINUE;
continue;
}
if (LPC_ERROR_EVENT == MessageType) {
PHARDERROR_MSG m;
m = (PHARDERROR_MSG)&ReceiveMsg;
m->Response = (ULONG)ResponseNotHandled;
Exit(Process, (ULONG)-1);
ReplyMsg = NULL; // no one to reply to.
continue;
}
if (LPC_REQUEST != MessageType) {
KdPrint(("PSXSS: Unknown message type 0x%x\n",
MessageType));
ReplyMsg = NULL; // no one to reply to.
continue;
}
if (Process != PortContext) {
//
// This message was sent by a diffferent process than
// the one that now has this ClientId. We discard
// the message.
//
ReplyMsg = NULL;
continue;
}
AcquireProcessLock(Process);
Process->InPsx++;
Process->IntControlBlock = (PINTCB) NULL;
ReleaseProcessLock(Process);
if (ReceiveMsg.ApiNumber >= PsxMaxApiNumber) {
KdPrint(("PSXSS: %lx is invalid ApiNumber\n",
ReceiveMsg.ApiNumber));
ReceiveMsg.Error = ENOSYS;
ReplyMsg = &ReceiveMsg;
continue;
}
ReplyMsg = &ReceiveMsg;
ReceiveMsg.Error = 0L;
ReceiveMsg.ReturnValue = 0L;
Reply = (*PsxServerApiDispatch[ReceiveMsg.ApiNumber])
(Process, &ReceiveMsg);
if (!(Process->Flags & P_FREE)) {
//
// the process has exited, don't try to fiddle
// with times.
//
if (!Reply) {
ReplyMsg = NULL;
continue;
}
}
//
// the user and system time for the posix server are added to
// the process *system* time (the system is executing in user
// and kernel mode on behalf of the process).
//
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadTimes,
(PVOID)&ThreadTime, sizeof(ThreadTime), &LengthNeeded);
ASSERT(NT_SUCCESS(Status));
PosixUTime2 = RtlExtendedLargeIntegerDivide(
ThreadTime.UserTime, 10000, &Remainder).LowPart;
PosixSTime2 = RtlExtendedLargeIntegerDivide(
ThreadTime.KernelTime, 10000, &Remainder).LowPart;
Process->ProcessTimes.tms_stime += (PosixUTime2 - PosixUTime1);
Process->ProcessTimes.tms_stime += (PosixSTime2 - PosixSTime1);
if (!Reply) {
ReplyMsg = NULL;
continue;
}
if (PendingSignalHandledInside(Process, &ReceiveMsg, NULL)) {
ReplyMsg = NULL; // Don't reply
continue;
}
AcquireProcessLock(Process);
--Process->InPsx;
ReleaseProcessLock(Process);
}
NtTerminateThread(NtCurrentThread(), Status);
return Status;
}
#if _MSC_FULL_VER >= 13008827
#pragma warning(pop)
#endif
VOID
ApiReply(
IN PPSX_PROCESS Process,
IN PPSX_API_MSG ReplyMsg,
IN sigset_t *RestoreBlockSigset OPTIONAL
)
/*++
Routine Description:
This routine issues a reply for the specified message on behalf of the
specified process.
Arguments:
Process - Supplies the address of the process on whose behalf the reply
is being made.
ReplyMsg - Supplies the value of the reply message.
RestoreBlockSigset - Supplies an optional blocked signal mask that
should be restored after the signal completes
Return Value:
None.
--*/
{
NTSTATUS Status;
HANDLE ReplyPort;
if (!PendingSignalHandledInside(Process, ReplyMsg, RestoreBlockSigset)) {
#if DBG
IF_PSX_DEBUG( MSGDUMP ) {
KdPrint(("--- REPLY TebServicer %lx Message... Pid %lx\n",
NtCurrentTeb(), Process->Pid));
dumpmsg(ReplyMsg);
}
#endif //DBG
ReplyPort = Process->ClientPort;
Status = NtReplyPort(ReplyPort, (PPORT_MESSAGE)ReplyMsg);
if (!NT_SUCCESS(Status)) {
//
// We can get here, if, for instance, somebody shoots a
// process out from under us.
//
KdPrint(("PSXSS: ReplyPort: 0x%x\n", Status));
}
--Process->InPsx;
return;
}
}
#if DBG
VOID
dumpmsg(
IN PPSX_API_MSG Msg
)
{
PULONG l;
ULONG p1,p2,p3;
KdPrint(("Length %lx\n",Msg->h.u1.Length));
KdPrint(("MapInfo and Type %lx\n",Msg->h.u2.ZeroInit));
KdPrint(("ClientId %lx.%lx\n",
Msg->h.ClientId.UniqueProcess,
Msg->h.ClientId.UniqueThread));
KdPrint(("ApiName %lx %s\n",Msg->ApiNumber,PsxServerApiName[Msg->ApiNumber]));
KdPrint(("Error %lx\n",Msg->Error));
KdPrint(("ReturnValue %lx\n",Msg->ReturnValue));
l = (PULONG) (&Msg->u.Fork);
p1 = *l++;
p2 = *l++;
p3 = *l++;
KdPrint(("Args[0..2] \t%lx\n\t\t%lx\n\t\t%lx\n",p1,p2,p3));
}
#endif //DBG