Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

519 lines
10 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. apireqst.c
  5. Abstract:
  6. This module implements the main loop servicing API RPC's.
  7. Author:
  8. Mark Lucovsky (markl) 05-Apr-1989
  9. Revision History:
  10. --*/
  11. #include "psxsrv.h"
  12. #define NOEXTAPI
  13. #include "wdbgexts.h"
  14. #include "ntdbg.h"
  15. //
  16. // API Dispatch Table
  17. //
  18. PPSX_API_ROUTINE PsxServerApiDispatch[PsxMaxApiNumber] = {
  19. PsxFork,
  20. PsxExec,
  21. PsxWaitPid,
  22. PsxExit,
  23. PsxKill,
  24. PsxSigAction,
  25. PsxSigProcMask,
  26. PsxSigPending,
  27. PsxSigSuspend,
  28. PsxAlarm,
  29. PsxGetIds,
  30. PsxSetUid,
  31. PsxSetGid,
  32. PsxGetGroups,
  33. PsxGetLogin,
  34. PsxCUserId,
  35. PsxSetSid,
  36. PsxSetPGroupId,
  37. PsxUname,
  38. PsxTime,
  39. PsxGetProcessTimes,
  40. PsxTtyName,
  41. PsxIsatty,
  42. PsxSysconf,
  43. PsxOpen,
  44. PsxUmask,
  45. PsxLink,
  46. PsxMkDir,
  47. PsxMkFifo,
  48. PsxRmDir,
  49. PsxRename,
  50. PsxStat,
  51. PsxFStat,
  52. PsxAccess,
  53. PsxChmod,
  54. PsxChown,
  55. PsxUtime,
  56. PsxPathConf,
  57. PsxFPathConf,
  58. PsxPipe,
  59. PsxDup,
  60. PsxDup2,
  61. PsxClose,
  62. PsxRead,
  63. PsxWrite,
  64. PsxFcntl,
  65. PsxLseek,
  66. PsxTcGetAttr,
  67. PsxTcSetAttr,
  68. PsxTcSendBreak,
  69. PsxTcDrain,
  70. PsxTcFlush,
  71. PsxTcFlow,
  72. PsxTcGetPGrp,
  73. PsxTcSetPGrp,
  74. PsxGetPwUid,
  75. PsxGetPwNam,
  76. PsxGetGrGid,
  77. PsxGetGrNam,
  78. PsxUnlink,
  79. PsxReadDir,
  80. PsxFtruncate,
  81. PsxNull
  82. #ifdef PSX_SOCKET
  83. ,
  84. PsxSocket,
  85. PsxAccept,
  86. PsxBind,
  87. PsxConnect,
  88. PsxGetPeerName,
  89. PsxGetSockName,
  90. PsxGetSockOpt,
  91. PsxListen,
  92. PsxRecv,
  93. PsxSend,
  94. PsxSendTo,
  95. PsxSetSockOpt,
  96. PsxShutdown
  97. #endif // PSX_SOCKET
  98. };
  99. #if DBG
  100. PSZ PsxServerApiName[PsxMaxApiNumber] = {
  101. "PsxFork",
  102. "PsxExec",
  103. "PsxWaitPid",
  104. "PsxExit",
  105. "PsxKill",
  106. "PsxSigAction",
  107. "PsxSigProcMask",
  108. "PsxSigPending",
  109. "PsxSigSuspend",
  110. "PsxAlarm",
  111. "PsxGetIds",
  112. "PsxSetUid",
  113. "PsxSetGid",
  114. "PsxGetGroups",
  115. "PsxGetLogin",
  116. "PsxCUserId",
  117. "PsxSetSid",
  118. "PsxSetPGroupId",
  119. "PsxUname",
  120. "PsxTime",
  121. "PsxGetProcessTimes",
  122. "PsxTtyName",
  123. "PsxIsatty",
  124. "PsxSysconf",
  125. "PsxOpen",
  126. "PsxUmask",
  127. "PsxLink",
  128. "PsxMkDir",
  129. "PsxMkFifo",
  130. "PsxRmDir",
  131. "PsxRename",
  132. "PsxStat",
  133. "PsxFStat",
  134. "PsxAccess",
  135. "PsxChmod",
  136. "PsxChown",
  137. "PsxUtime",
  138. "PsxPathConf",
  139. "PsxFPathConf",
  140. "PsxPipe",
  141. "PsxDup",
  142. "PsxDup2",
  143. "PsxClose",
  144. "PsxRead",
  145. "PsxWrite",
  146. "PsxFcntl",
  147. "PsxLseek",
  148. "PsxTcGetAttr",
  149. "PsxTcSetAttr",
  150. "PsxTcSendBreak",
  151. "PsxTcDrain",
  152. "PsxTcFlush",
  153. "PsxTcFlow",
  154. "PsxTcGetPGrp",
  155. "PsxTcSetPGrp",
  156. "PsxGetPwUid",
  157. "PsxGetPwNam",
  158. "PsxGetGrGid",
  159. "PsxGetGrNam",
  160. "PsxUnlink",
  161. "PsxReadDir",
  162. "PsxFtruncate",
  163. "PsxNull"
  164. #ifdef PSX_SOCKET
  165. ,
  166. "PsxSocket",
  167. "PsxAccept",
  168. "PsxBind",
  169. "PsxConnect",
  170. "PsxGetPeerName",
  171. "PsxGetSockName",
  172. "PsxGetSockOpt",
  173. "PsxListen",
  174. "PsxRecv",
  175. "PsxRecvFrom",
  176. "PsxSend",
  177. "PsxSendTo",
  178. "PsxSetSockOpt",
  179. "PsxShutdown"
  180. #endif // PSX_SOCKET
  181. };
  182. VOID dumpmsg( IN PPSX_API_MSG ReplyMsg);
  183. #endif //DBG
  184. #if _MSC_FULL_VER >= 13008827
  185. #pragma warning(push)
  186. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  187. #endif
  188. NTSTATUS
  189. PsxApiRequestThread(
  190. IN PVOID Parameter
  191. )
  192. {
  193. NTSTATUS Status;
  194. PPSX_PROCESS Process;
  195. PSX_API_MSG ReceiveMsg;
  196. PPSX_API_MSG ReplyMsg;
  197. USHORT MessageType;
  198. PVOID PortContext; // pointer to process structure
  199. KERNEL_USER_TIMES ThreadTime;
  200. ULONG PosixUTime1, PosixUTime2, Remainder, LengthNeeded;
  201. ULONG PosixSTime1, PosixSTime2;
  202. BOOLEAN Reply;
  203. UNREFERENCED_PARAMETER(Parameter);
  204. ReplyMsg = NULL;
  205. while (TRUE) {
  206. Status = NtQueryInformationThread(NtCurrentThread(),
  207. ThreadTimes,
  208. (PVOID)&ThreadTime, sizeof(ThreadTime), &LengthNeeded);
  209. ASSERT(NT_SUCCESS(Status));
  210. PosixUTime1 = RtlExtendedLargeIntegerDivide(
  211. ThreadTime.UserTime, 10000, &Remainder).LowPart;
  212. PosixSTime1 = RtlExtendedLargeIntegerDivide(
  213. ThreadTime.KernelTime, 10000, &Remainder).LowPart;
  214. Status = NtReplyWaitReceivePort(PsxApiPort,
  215. &PortContext, (PPORT_MESSAGE)ReplyMsg,
  216. (PPORT_MESSAGE)&ReceiveMsg);
  217. if (Status != 0) {
  218. if (NT_SUCCESS(Status)) {
  219. continue;
  220. }
  221. if (STATUS_INVALID_CID == Status) {
  222. ReplyMsg = NULL;
  223. continue;
  224. }
  225. KdPrint(("PSXSS: ReceivePort failed: 0x%x\n",
  226. Status));
  227. ReplyMsg = NULL;
  228. continue;
  229. }
  230. MessageType = ReceiveMsg.h.u2.s2.Type;
  231. if (MessageType == LPC_CONNECTION_REQUEST) {
  232. PsxApiHandleConnectionRequest( &ReceiveMsg );
  233. ReplyMsg = NULL;
  234. continue;
  235. }
  236. Process = PsxLocateProcessByClientId(&ReceiveMsg.h.ClientId);
  237. if (NULL == Process) {
  238. if (LPC_CLIENT_DIED == MessageType ||
  239. LPC_PORT_CLOSED == MessageType ||
  240. LPC_ERROR_EVENT == MessageType
  241. ) {
  242. ReplyMsg = NULL;
  243. continue;
  244. }
  245. if (LPC_EXCEPTION == MessageType) {
  246. ReplyMsg = &ReceiveMsg;
  247. ReplyMsg->ReturnValue = DBG_CONTINUE;
  248. continue;
  249. }
  250. KdPrint(("PSXSS: msg %d from unknown client: %d, %d\n",
  251. ReceiveMsg.ApiNumber,
  252. ReceiveMsg.h.ClientId.UniqueProcess,
  253. ReceiveMsg.h.ClientId.UniqueThread));
  254. ReceiveMsg.Error = ESRCH;
  255. ReplyMsg = NULL;
  256. continue;
  257. }
  258. //
  259. // For each POSIX API message
  260. // - Validate the API Number
  261. // - Dispatch the call
  262. // - Optionally Reply
  263. //
  264. if (LPC_CLIENT_DIED == MessageType) {
  265. // XXX.mjb: do we need to increment InPsx here?
  266. // XXX.mjb: this exit status should be meaningful.
  267. Exit(Process, (ULONG)-1);
  268. ReplyMsg = NULL; // no one to reply to.
  269. continue;
  270. }
  271. if (LPC_EXCEPTION == MessageType) {
  272. PDBGKM_APIMSG m;
  273. KdPrint(("PSXSS: Pid 0x%x has taken an exception\n",
  274. Process->Pid));
  275. Exit(Process, (ULONG)-1);
  276. //
  277. // XXX.mjb: would be nice to print an error
  278. // message.
  279. //
  280. m = (PDBGKM_APIMSG)&ReceiveMsg;
  281. m->ReturnedStatus = DBG_CONTINUE;
  282. ReplyMsg = &ReceiveMsg;
  283. ReplyMsg->ReturnValue = DBG_CONTINUE;
  284. continue;
  285. }
  286. if (LPC_ERROR_EVENT == MessageType) {
  287. PHARDERROR_MSG m;
  288. m = (PHARDERROR_MSG)&ReceiveMsg;
  289. m->Response = (ULONG)ResponseNotHandled;
  290. Exit(Process, (ULONG)-1);
  291. ReplyMsg = NULL; // no one to reply to.
  292. continue;
  293. }
  294. if (LPC_REQUEST != MessageType) {
  295. KdPrint(("PSXSS: Unknown message type 0x%x\n",
  296. MessageType));
  297. ReplyMsg = NULL; // no one to reply to.
  298. continue;
  299. }
  300. if (Process != PortContext) {
  301. //
  302. // This message was sent by a diffferent process than
  303. // the one that now has this ClientId. We discard
  304. // the message.
  305. //
  306. ReplyMsg = NULL;
  307. continue;
  308. }
  309. AcquireProcessLock(Process);
  310. Process->InPsx++;
  311. Process->IntControlBlock = (PINTCB) NULL;
  312. ReleaseProcessLock(Process);
  313. if (ReceiveMsg.ApiNumber >= PsxMaxApiNumber) {
  314. KdPrint(("PSXSS: %lx is invalid ApiNumber\n",
  315. ReceiveMsg.ApiNumber));
  316. ReceiveMsg.Error = ENOSYS;
  317. ReplyMsg = &ReceiveMsg;
  318. continue;
  319. }
  320. ReplyMsg = &ReceiveMsg;
  321. ReceiveMsg.Error = 0L;
  322. ReceiveMsg.ReturnValue = 0L;
  323. Reply = (*PsxServerApiDispatch[ReceiveMsg.ApiNumber])
  324. (Process, &ReceiveMsg);
  325. if (!(Process->Flags & P_FREE)) {
  326. //
  327. // the process has exited, don't try to fiddle
  328. // with times.
  329. //
  330. if (!Reply) {
  331. ReplyMsg = NULL;
  332. continue;
  333. }
  334. }
  335. //
  336. // the user and system time for the posix server are added to
  337. // the process *system* time (the system is executing in user
  338. // and kernel mode on behalf of the process).
  339. //
  340. Status = NtQueryInformationThread(NtCurrentThread(),
  341. ThreadTimes,
  342. (PVOID)&ThreadTime, sizeof(ThreadTime), &LengthNeeded);
  343. ASSERT(NT_SUCCESS(Status));
  344. PosixUTime2 = RtlExtendedLargeIntegerDivide(
  345. ThreadTime.UserTime, 10000, &Remainder).LowPart;
  346. PosixSTime2 = RtlExtendedLargeIntegerDivide(
  347. ThreadTime.KernelTime, 10000, &Remainder).LowPart;
  348. Process->ProcessTimes.tms_stime += (PosixUTime2 - PosixUTime1);
  349. Process->ProcessTimes.tms_stime += (PosixSTime2 - PosixSTime1);
  350. if (!Reply) {
  351. ReplyMsg = NULL;
  352. continue;
  353. }
  354. if (PendingSignalHandledInside(Process, &ReceiveMsg, NULL)) {
  355. ReplyMsg = NULL; // Don't reply
  356. continue;
  357. }
  358. AcquireProcessLock(Process);
  359. --Process->InPsx;
  360. ReleaseProcessLock(Process);
  361. }
  362. NtTerminateThread(NtCurrentThread(), Status);
  363. return Status;
  364. }
  365. #if _MSC_FULL_VER >= 13008827
  366. #pragma warning(pop)
  367. #endif
  368. VOID
  369. ApiReply(
  370. IN PPSX_PROCESS Process,
  371. IN PPSX_API_MSG ReplyMsg,
  372. IN sigset_t *RestoreBlockSigset OPTIONAL
  373. )
  374. /*++
  375. Routine Description:
  376. This routine issues a reply for the specified message on behalf of the
  377. specified process.
  378. Arguments:
  379. Process - Supplies the address of the process on whose behalf the reply
  380. is being made.
  381. ReplyMsg - Supplies the value of the reply message.
  382. RestoreBlockSigset - Supplies an optional blocked signal mask that
  383. should be restored after the signal completes
  384. Return Value:
  385. None.
  386. --*/
  387. {
  388. NTSTATUS Status;
  389. HANDLE ReplyPort;
  390. if (!PendingSignalHandledInside(Process, ReplyMsg, RestoreBlockSigset)) {
  391. #if DBG
  392. IF_PSX_DEBUG( MSGDUMP ) {
  393. KdPrint(("--- REPLY TebServicer %lx Message... Pid %lx\n",
  394. NtCurrentTeb(), Process->Pid));
  395. dumpmsg(ReplyMsg);
  396. }
  397. #endif //DBG
  398. ReplyPort = Process->ClientPort;
  399. Status = NtReplyPort(ReplyPort, (PPORT_MESSAGE)ReplyMsg);
  400. if (!NT_SUCCESS(Status)) {
  401. //
  402. // We can get here, if, for instance, somebody shoots a
  403. // process out from under us.
  404. //
  405. KdPrint(("PSXSS: ReplyPort: 0x%x\n", Status));
  406. }
  407. --Process->InPsx;
  408. return;
  409. }
  410. }
  411. #if DBG
  412. VOID
  413. dumpmsg(
  414. IN PPSX_API_MSG Msg
  415. )
  416. {
  417. PULONG l;
  418. ULONG p1,p2,p3;
  419. KdPrint(("Length %lx\n",Msg->h.u1.Length));
  420. KdPrint(("MapInfo and Type %lx\n",Msg->h.u2.ZeroInit));
  421. KdPrint(("ClientId %lx.%lx\n",
  422. Msg->h.ClientId.UniqueProcess,
  423. Msg->h.ClientId.UniqueThread));
  424. KdPrint(("ApiName %lx %s\n",Msg->ApiNumber,PsxServerApiName[Msg->ApiNumber]));
  425. KdPrint(("Error %lx\n",Msg->Error));
  426. KdPrint(("ReturnValue %lx\n",Msg->ReturnValue));
  427. l = (PULONG) (&Msg->u.Fork);
  428. p1 = *l++;
  429. p2 = *l++;
  430. p3 = *l++;
  431. KdPrint(("Args[0..2] \t%lx\n\t\t%lx\n\t\t%lx\n",p1,p2,p3));
  432. }
  433. #endif //DBG