windows-nt/Source/XPSP1/NT/base/subsys/posix/psxss/concreat.c
2020-09-26 16:20:57 +08:00

294 lines
7.1 KiB
C

/*++
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;
}