520 lines
10 KiB
C
520 lines
10 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
|