|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
concreat.c
Abstract:
This module handles the request to create a session for PSXSES.
Author:
Avi Nathan (avin) 17-Jul-1991
Revision History:
Ellen Aycock-Wright (ellena) 15-Sept-1991 Modified for POSIX
--*/
#include <stdio.h>
#include "psxsrv.h"
#define NTPSX_ONLY
#include "sesport.h"
VOID SetDefaultLibPath( OUT PANSI_STRING LibPath, IN PCHAR EnvStrings ) { PCHAR p;
// BUGBUG: Unicode
for (p = EnvStrings; '\0' != *p; p += strlen(p) + 1) { if (0 == _strnicmp(p, "_PSXLIBPATH=", sizeof("_PSXLIBPATH=") - 1)) { p += sizeof("_PSXLIBPATH=") - 1; break; } } RtlInitAnsiString(LibPath, p); }
//
// PsxCreateConSession -- Create a new Posix session, with a process
// to run in it. The new process inherits security info and quota
// stuff from the Posix session manager, which is identified in the
// RequestMsg that's passed in.
//
NTSTATUS PsxCreateConSession( IN OUT PVOID RequestMsg ) { NTSTATUS Status; PSCREQ_CREATE Create = &((PPSXSESREQUESTMSG)RequestMsg)->d.Create; PPSX_PROCESS NewProcess; PCHAR BaseAddress; PSX_EXEC_INFO ExecInfo; HANDLE SectionHandle = NULL; HANDLE ParentProc; // a handle on the psxses process
OBJECT_ATTRIBUTES Obj; // used for opening psxses process
PPSX_SESSION pS; PPSX_CONTROLLING_TTY Terminal; BOOLEAN PsxCreateOk; int i;
Terminal = GetConnectingTerminal(Create->SessionUniqueId); if (NULL == Terminal) { KdPrint(("PSXSS: Connect by session not connecting\n")); return STATUS_UNSUCCESSFUL; }
BaseAddress = PsxViewSessionData(Create->SessionUniqueId, &SectionHandle); if (NULL == BaseAddress) { RtlDeleteCriticalSection(&Terminal->Lock); NtClose(Terminal->ConsoleCommPort); NtClose(Terminal->ConsolePort); RtlFreeHeap(PsxHeap, 0, Terminal);
return STATUS_UNSUCCESSFUL; }
pS = PsxAllocateSession(Terminal, 0); if (NULL == pS) { RtlDeleteCriticalSection(&Terminal->Lock); NtClose(Terminal->ConsoleCommPort); NtClose(Terminal->ConsolePort); RtlFreeHeap(PsxHeap, 0, Terminal); if (NULL != BaseAddress) { NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } if (NULL != SectionHandle) { NtClose(SectionHandle); } return STATUS_UNSUCCESSFUL; } pS->Terminal->ConsolePort = Create->SessionPort; pS->Terminal->IoBuffer = BaseAddress;
RtlInitAnsiString(&ExecInfo.Path, BaseAddress + Create->PgmNameOffset);
RtlInitAnsiString(&ExecInfo.CWD, BaseAddress + Create->CurrentDirOffset);
ExecInfo.Argv.Buffer = BaseAddress + Create->ArgsOffset; ExecInfo.Argv.Length = 0x4000; // XXX.mjb: use real length
ExecInfo.Argv.MaximumLength = 0x4000; // XXX.mjb: use real length
SetDefaultLibPath(&ExecInfo.LibPath, BaseAddress + Create->EnvironmentOffset);
InitializeObjectAttributes(&Obj, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&ParentProc, PROCESS_CREATE_PROCESS, &Obj, &((PPORT_MESSAGE)RequestMsg)->ClientId); if (!NT_SUCCESS(Status)) { RtlEnterCriticalSection(&PsxNtSessionLock); PsxDeallocateSession(pS);
if (NULL != SectionHandle) { NtClose(SectionHandle); } KdPrint(("PSXSS: NtOpenProcess: 0x%x\n", Status)); return Status; }
//
// create a process for the new session.
//
Status = NtImpersonateClientOfPort(pS->Terminal->ConsoleCommPort, RequestMsg); if (NT_SUCCESS(Status)) {
PsxCreateOk = PsxCreateProcess(&ExecInfo, &NewProcess, ParentProc, pS); EndImpersonation(); if (!PsxCreateOk) { Status = STATUS_UNSUCCESSFUL; } }
NtClose(ParentProc);
if (!NT_SUCCESS(Status)) { //
// Must hold PsxNtSessionLock when calling DeallocSession.
//
RtlEnterCriticalSection(&PsxNtSessionLock); PsxDeallocateSession(pS); if (NULL != SectionHandle) { (void)NtClose(SectionHandle); } return Status; }
pS->Terminal->ForegroundProcessGroup = NewProcess->ProcessGroupId;
//
// Open file descriptors for stdin, stdout, and stderr.
//
for (i = 0; i < Create->OpenFiles; ++i) { ULONG fd, Error = 0; PFILEDESCRIPTOR Fd;
Fd = AllocateFd(NewProcess, 0, &fd); ASSERT(NULL != Fd);
Error += OpenTty(NewProcess, Fd, FILE_READ_DATA|FILE_WRITE_DATA, 0, FALSE); Fd->SystemOpenFileDesc->NtIoHandle = (HANDLE)i;
ASSERT(0 == Error); }
if (NULL != SectionHandle) { NtClose(SectionHandle); } Status = NtResumeThread(NewProcess->Thread, NULL); ASSERT(NT_SUCCESS(Status));
return STATUS_SUCCESS; }
NTSTATUS PsxTerminateConSession( IN PPSX_SESSION Session, IN ULONG ExitStatus ) { NTSTATUS Status; SCREQUESTMSG Request;
if (NULL == Session || NULL == Session->Terminal) { return STATUS_UNSUCCESSFUL; }
Request.Request = TaskManRequest; Request.d.Tm.Request = TmExit; Request.d.Tm.ExitStatus = ExitStatus;
PORT_MSG_TOTAL_LENGTH(Request) = sizeof(SCREQUESTMSG); PORT_MSG_DATA_LENGTH(Request) = sizeof(SCREQUESTMSG) - sizeof(PORT_MESSAGE); PORT_MSG_ZERO_INIT(Request) = 0L;
if (NULL == Session->Terminal) return STATUS_UNSUCCESSFUL;
Status = NtRequestPort(Session->Terminal->ConsolePort, (PPORT_MESSAGE)&Request); if (!NT_SUCCESS(Status)) { KdPrint(("PSXSS: Unable to send terminate request: Status == %X\n", Status)); }
Status = NtClose(Session->Terminal->ConsolePort); if (!NT_SUCCESS(Status)) { KdPrint(("PSXSS: Close ConsolePort: 0x%x\n", Status)); } Status = NtClose(Session->Terminal->ConsoleCommPort); if (!NT_SUCCESS(Status)) { KdPrint(("PSXSS: Close ConsoleCommPort: 0x%x\n", Status)); } return STATUS_SUCCESS; }
PVOID PsxViewSessionData( IN ULONG SessionId, OUT PHANDLE RetSection ) { CHAR SessionName[PSX_SES_BASE_PORT_NAME_LENGTH]; STRING SessionDataName; UNICODE_STRING SessionDataName_U;
NTSTATUS Status; HANDLE SectionHandle; SIZE_T ViewSize = 0L; OBJECT_ATTRIBUTES ObjectAttributes; PVOID SessionDataBaseAddress;
PSX_GET_SESSION_DATA_NAME(SessionName, SessionId);
RtlInitAnsiString(&SessionDataName, SessionName); Status = RtlAnsiStringToUnicodeString(&SessionDataName_U, &SessionDataName, TRUE); if (!NT_SUCCESS(Status)) { return NULL; }
InitializeObjectAttributes(&ObjectAttributes, &SessionDataName_U, 0, NULL, NULL);
Status = NtOpenSection(&SectionHandle, SECTION_MAP_WRITE, &ObjectAttributes);
RtlFreeUnicodeString(&SessionDataName_U);
if (!NT_SUCCESS(Status)) { KdPrint(("PSXSS: NtOpenSection: 0x%x\n", Status)); return NULL; }
//
// Let MM locate the view
//
SessionDataBaseAddress = 0;
Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &SessionDataBaseAddress, 0L, 0L, NULL, &ViewSize, ViewUnmap, 0L, PAGE_READWRITE);
if (!NT_SUCCESS(Status)) { NtClose(SectionHandle); return NULL; }
*RetSection = SectionHandle; return SessionDataBaseAddress; }
|