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.

293 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. concreat.c
  5. Abstract:
  6. This module handles the request to create a session for PSXSES.
  7. Author:
  8. Avi Nathan (avin) 17-Jul-1991
  9. Revision History:
  10. Ellen Aycock-Wright (ellena) 15-Sept-1991 Modified for POSIX
  11. --*/
  12. #include <stdio.h>
  13. #include "psxsrv.h"
  14. #define NTPSX_ONLY
  15. #include "sesport.h"
  16. VOID
  17. SetDefaultLibPath(
  18. OUT PANSI_STRING LibPath,
  19. IN PCHAR EnvStrings
  20. )
  21. {
  22. PCHAR p;
  23. // BUGBUG: Unicode
  24. for (p = EnvStrings; '\0' != *p; p += strlen(p) + 1) {
  25. if (0 == _strnicmp(p, "_PSXLIBPATH=",
  26. sizeof("_PSXLIBPATH=") - 1)) {
  27. p += sizeof("_PSXLIBPATH=") - 1;
  28. break;
  29. }
  30. }
  31. RtlInitAnsiString(LibPath, p);
  32. }
  33. //
  34. // PsxCreateConSession -- Create a new Posix session, with a process
  35. // to run in it. The new process inherits security info and quota
  36. // stuff from the Posix session manager, which is identified in the
  37. // RequestMsg that's passed in.
  38. //
  39. NTSTATUS
  40. PsxCreateConSession(
  41. IN OUT PVOID RequestMsg
  42. )
  43. {
  44. NTSTATUS Status;
  45. PSCREQ_CREATE Create = &((PPSXSESREQUESTMSG)RequestMsg)->d.Create;
  46. PPSX_PROCESS NewProcess;
  47. PCHAR BaseAddress;
  48. PSX_EXEC_INFO ExecInfo;
  49. HANDLE SectionHandle = NULL;
  50. HANDLE ParentProc; // a handle on the psxses process
  51. OBJECT_ATTRIBUTES Obj; // used for opening psxses process
  52. PPSX_SESSION pS;
  53. PPSX_CONTROLLING_TTY Terminal;
  54. BOOLEAN PsxCreateOk;
  55. int i;
  56. Terminal = GetConnectingTerminal(Create->SessionUniqueId);
  57. if (NULL == Terminal) {
  58. KdPrint(("PSXSS: Connect by session not connecting\n"));
  59. return STATUS_UNSUCCESSFUL;
  60. }
  61. BaseAddress = PsxViewSessionData(Create->SessionUniqueId,
  62. &SectionHandle);
  63. if (NULL == BaseAddress) {
  64. RtlDeleteCriticalSection(&Terminal->Lock);
  65. NtClose(Terminal->ConsoleCommPort);
  66. NtClose(Terminal->ConsolePort);
  67. RtlFreeHeap(PsxHeap, 0, Terminal);
  68. return STATUS_UNSUCCESSFUL;
  69. }
  70. pS = PsxAllocateSession(Terminal, 0);
  71. if (NULL == pS) {
  72. RtlDeleteCriticalSection(&Terminal->Lock);
  73. NtClose(Terminal->ConsoleCommPort);
  74. NtClose(Terminal->ConsolePort);
  75. RtlFreeHeap(PsxHeap, 0, Terminal);
  76. if (NULL != BaseAddress) {
  77. NtUnmapViewOfSection(NtCurrentProcess(),
  78. BaseAddress);
  79. }
  80. if (NULL != SectionHandle) {
  81. NtClose(SectionHandle);
  82. }
  83. return STATUS_UNSUCCESSFUL;
  84. }
  85. pS->Terminal->ConsolePort = Create->SessionPort;
  86. pS->Terminal->IoBuffer = BaseAddress;
  87. RtlInitAnsiString(&ExecInfo.Path, BaseAddress + Create->PgmNameOffset);
  88. RtlInitAnsiString(&ExecInfo.CWD,
  89. BaseAddress + Create->CurrentDirOffset);
  90. ExecInfo.Argv.Buffer = BaseAddress + Create->ArgsOffset;
  91. ExecInfo.Argv.Length = 0x4000; // XXX.mjb: use real length
  92. ExecInfo.Argv.MaximumLength = 0x4000; // XXX.mjb: use real length
  93. SetDefaultLibPath(&ExecInfo.LibPath,
  94. BaseAddress + Create->EnvironmentOffset);
  95. InitializeObjectAttributes(&Obj, NULL, 0, NULL, NULL);
  96. Status = NtOpenProcess(&ParentProc, PROCESS_CREATE_PROCESS,
  97. &Obj, &((PPORT_MESSAGE)RequestMsg)->ClientId);
  98. if (!NT_SUCCESS(Status)) {
  99. RtlEnterCriticalSection(&PsxNtSessionLock);
  100. PsxDeallocateSession(pS);
  101. if (NULL != SectionHandle) {
  102. NtClose(SectionHandle);
  103. }
  104. KdPrint(("PSXSS: NtOpenProcess: 0x%x\n", Status));
  105. return Status;
  106. }
  107. //
  108. // create a process for the new session.
  109. //
  110. Status = NtImpersonateClientOfPort(pS->Terminal->ConsoleCommPort,
  111. RequestMsg);
  112. if (NT_SUCCESS(Status)) {
  113. PsxCreateOk = PsxCreateProcess(&ExecInfo, &NewProcess, ParentProc, pS);
  114. EndImpersonation();
  115. if (!PsxCreateOk) {
  116. Status = STATUS_UNSUCCESSFUL;
  117. }
  118. }
  119. NtClose(ParentProc);
  120. if (!NT_SUCCESS(Status)) {
  121. //
  122. // Must hold PsxNtSessionLock when calling DeallocSession.
  123. //
  124. RtlEnterCriticalSection(&PsxNtSessionLock);
  125. PsxDeallocateSession(pS);
  126. if (NULL != SectionHandle) {
  127. (void)NtClose(SectionHandle);
  128. }
  129. return Status;
  130. }
  131. pS->Terminal->ForegroundProcessGroup = NewProcess->ProcessGroupId;
  132. //
  133. // Open file descriptors for stdin, stdout, and stderr.
  134. //
  135. for (i = 0; i < Create->OpenFiles; ++i) {
  136. ULONG fd, Error = 0;
  137. PFILEDESCRIPTOR Fd;
  138. Fd = AllocateFd(NewProcess, 0, &fd);
  139. ASSERT(NULL != Fd);
  140. Error += OpenTty(NewProcess, Fd,
  141. FILE_READ_DATA|FILE_WRITE_DATA, 0, FALSE);
  142. Fd->SystemOpenFileDesc->NtIoHandle = (HANDLE)i;
  143. ASSERT(0 == Error);
  144. }
  145. if (NULL != SectionHandle) {
  146. NtClose(SectionHandle);
  147. }
  148. Status = NtResumeThread(NewProcess->Thread, NULL);
  149. ASSERT(NT_SUCCESS(Status));
  150. return STATUS_SUCCESS;
  151. }
  152. NTSTATUS
  153. PsxTerminateConSession(
  154. IN PPSX_SESSION Session,
  155. IN ULONG ExitStatus
  156. )
  157. {
  158. NTSTATUS Status;
  159. SCREQUESTMSG Request;
  160. if (NULL == Session || NULL == Session->Terminal) {
  161. return STATUS_UNSUCCESSFUL;
  162. }
  163. Request.Request = TaskManRequest;
  164. Request.d.Tm.Request = TmExit;
  165. Request.d.Tm.ExitStatus = ExitStatus;
  166. PORT_MSG_TOTAL_LENGTH(Request) = sizeof(SCREQUESTMSG);
  167. PORT_MSG_DATA_LENGTH(Request) = sizeof(SCREQUESTMSG) - sizeof(PORT_MESSAGE);
  168. PORT_MSG_ZERO_INIT(Request) = 0L;
  169. if (NULL == Session->Terminal)
  170. return STATUS_UNSUCCESSFUL;
  171. Status = NtRequestPort(Session->Terminal->ConsolePort,
  172. (PPORT_MESSAGE)&Request);
  173. if (!NT_SUCCESS(Status)) {
  174. KdPrint(("PSXSS: Unable to send terminate request: Status == %X\n",
  175. Status));
  176. }
  177. Status = NtClose(Session->Terminal->ConsolePort);
  178. if (!NT_SUCCESS(Status)) {
  179. KdPrint(("PSXSS: Close ConsolePort: 0x%x\n", Status));
  180. }
  181. Status = NtClose(Session->Terminal->ConsoleCommPort);
  182. if (!NT_SUCCESS(Status)) {
  183. KdPrint(("PSXSS: Close ConsoleCommPort: 0x%x\n", Status));
  184. }
  185. return STATUS_SUCCESS;
  186. }
  187. PVOID
  188. PsxViewSessionData(
  189. IN ULONG SessionId,
  190. OUT PHANDLE RetSection
  191. )
  192. {
  193. CHAR SessionName[PSX_SES_BASE_PORT_NAME_LENGTH];
  194. STRING SessionDataName;
  195. UNICODE_STRING SessionDataName_U;
  196. NTSTATUS Status;
  197. HANDLE SectionHandle;
  198. SIZE_T ViewSize = 0L;
  199. OBJECT_ATTRIBUTES ObjectAttributes;
  200. PVOID SessionDataBaseAddress;
  201. PSX_GET_SESSION_DATA_NAME(SessionName, SessionId);
  202. RtlInitAnsiString(&SessionDataName, SessionName);
  203. Status = RtlAnsiStringToUnicodeString(&SessionDataName_U, &SessionDataName,
  204. TRUE);
  205. if (!NT_SUCCESS(Status)) {
  206. return NULL;
  207. }
  208. InitializeObjectAttributes(&ObjectAttributes, &SessionDataName_U, 0,
  209. NULL, NULL);
  210. Status = NtOpenSection(&SectionHandle, SECTION_MAP_WRITE,
  211. &ObjectAttributes);
  212. RtlFreeUnicodeString(&SessionDataName_U);
  213. if (!NT_SUCCESS(Status)) {
  214. KdPrint(("PSXSS: NtOpenSection: 0x%x\n", Status));
  215. return NULL;
  216. }
  217. //
  218. // Let MM locate the view
  219. //
  220. SessionDataBaseAddress = 0;
  221. Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(),
  222. &SessionDataBaseAddress, 0L, 0L, NULL,
  223. &ViewSize, ViewUnmap, 0L, PAGE_READWRITE);
  224. if (!NT_SUCCESS(Status)) {
  225. NtClose(SectionHandle);
  226. return NULL;
  227. }
  228. *RetSection = SectionHandle;
  229. return SessionDataBaseAddress;
  230. }