mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
29fa274d6d
- TSVN choked repeatedly when attempting to merge ~9000 revs into the branch (tried 3 times on 2 different computers) - If someone wants to delete aicom-network-fixes, they are welcome to - Lesson learned: Letting a branch get thousands of revs out of date is a horrible idea svn path=/branches/aicom-network-branch/; revision=44353
292 lines
7.6 KiB
C
292 lines
7.6 KiB
C
/*
|
|
* PROJECT: ReactOS Session Manager
|
|
* LICENSE: GPL v2 or later - See COPYING in the top level directory
|
|
* FILE: base/system/smss/smapiexec.c
|
|
* PURPOSE: SM_API_EXECUTE_PROGRAM.
|
|
* PROGRAMMERS: ReactOS Development Team
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
#include "smss.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
static const WCHAR szSystemDirectory[] = L"\\System32";
|
|
|
|
/**********************************************************************
|
|
* SmCreateUserProcess/5
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* ARGUMENTS
|
|
* ImagePath: absolute path of the image to run;
|
|
* CommandLine: arguments and options for ImagePath;
|
|
* Flags: Wait flag: Set for boot time processes and unset for
|
|
* subsystems bootstrapping;
|
|
* 1Mb reserve flag: Set for subsystems, unset for everything
|
|
* else
|
|
* Timeout: optional: used if WaitForIt==TRUE;
|
|
* ProcessHandle: optional: a duplicated handle for
|
|
the child process (storage provided by the caller).
|
|
*
|
|
* RETURN VALUE
|
|
* NTSTATUS:
|
|
*
|
|
*/
|
|
NTSTATUS NTAPI
|
|
SmCreateUserProcess (LPWSTR ImagePath,
|
|
LPWSTR CommandLine,
|
|
ULONG Flags,
|
|
PLARGE_INTEGER Timeout OPTIONAL,
|
|
PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL)
|
|
{
|
|
UNICODE_STRING ImagePathString = { 0, 0, NULL };
|
|
UNICODE_STRING CommandLineString = { 0, 0, NULL };
|
|
UNICODE_STRING SystemDirectory = { 0, 0, NULL };
|
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
|
|
RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
|
|
PRTL_USER_PROCESS_INFORMATION pProcessInfo = & ProcessInfo;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
|
|
|
if (NULL != UserProcessInfo)
|
|
{
|
|
pProcessInfo = UserProcessInfo;
|
|
}
|
|
|
|
RtlInitUnicodeString (& ImagePathString, ImagePath);
|
|
RtlInitUnicodeString (& CommandLineString, CommandLine);
|
|
|
|
SystemDirectory.MaximumLength = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR)) + sizeof(szSystemDirectory);
|
|
SystemDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
SystemDirectory.MaximumLength);
|
|
if (SystemDirectory.Buffer == NULL)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = RtlAppendUnicodeToString(& SystemDirectory,
|
|
SharedUserData->NtSystemRoot);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto FailProcParams;
|
|
}
|
|
|
|
Status = RtlAppendUnicodeToString(& SystemDirectory,
|
|
szSystemDirectory);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto FailProcParams;
|
|
}
|
|
|
|
|
|
Status = RtlCreateProcessParameters(& ProcessParameters,
|
|
& ImagePathString,
|
|
NULL,
|
|
& SystemDirectory,
|
|
& CommandLineString,
|
|
SmSystemEnvironment,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
0,
|
|
SystemDirectory.Buffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
FailProcParams:
|
|
DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, Status);
|
|
return Status;
|
|
}
|
|
#ifdef ROS_DOESNT_SUCK
|
|
/* Reserve lower 1Mb, if requested */
|
|
if (Flags & SM_CREATE_FLAG_RESERVE_1MB)
|
|
ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
|
|
#endif
|
|
/* Create the user process */
|
|
Status = RtlCreateUserProcess (& ImagePathString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ProcessParameters,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
pProcessInfo);
|
|
|
|
RtlDestroyProcessParameters (ProcessParameters);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, ImagePathString.Buffer, Status);
|
|
return Status;
|
|
}
|
|
/*
|
|
* It the caller is *not* interested in the child info,
|
|
* resume it immediately.
|
|
*/
|
|
if (NULL == UserProcessInfo)
|
|
{
|
|
Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, Status);
|
|
}
|
|
}
|
|
|
|
/* Wait for process termination */
|
|
if (Flags & SM_CREATE_FLAG_WAIT)
|
|
{
|
|
Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
|
|
FALSE,
|
|
Timeout);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
|
|
__FUNCTION__, Status);
|
|
}
|
|
}
|
|
|
|
if (NULL == UserProcessInfo)
|
|
{
|
|
NtClose(pProcessInfo->ProcessHandle);
|
|
NtClose(pProcessInfo->ThreadHandle);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* SmExecPgm/1 API
|
|
*/
|
|
SMAPI(SmExecPgm)
|
|
{
|
|
PSM_PORT_MESSAGE_EXECPGM ExecPgm = NULL;
|
|
WCHAR Name [SM_EXEXPGM_MAX_LENGTH + 1];
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DPRINT("SM: %s called\n",__FUNCTION__);
|
|
|
|
if(NULL == Request)
|
|
{
|
|
DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
DPRINT("SM: %s called from CID(%p|%p)\n",
|
|
__FUNCTION__, Request->Header.ClientId.UniqueProcess,
|
|
Request->Header.ClientId.UniqueThread);
|
|
ExecPgm = & Request->Request.ExecPgm;
|
|
/* Check if the name lenght is valid */
|
|
if((ExecPgm->NameLength > 0) &&
|
|
(ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&
|
|
TRUE /* TODO: check LPC payload size */)
|
|
{
|
|
WCHAR Data [MAX_PATH + 1] = {0};
|
|
ULONG DataLength = sizeof Data;
|
|
ULONG DataType = REG_EXPAND_SZ;
|
|
|
|
|
|
RtlZeroMemory (Name, sizeof Name);
|
|
RtlCopyMemory (Name,
|
|
ExecPgm->Name,
|
|
(sizeof ExecPgm->Name[0] * ExecPgm->NameLength));
|
|
DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);
|
|
/* Lookup Name in the registry */
|
|
Status = SmLookupSubsystem (Name,
|
|
Data,
|
|
& DataLength,
|
|
& DataType,
|
|
SmSystemEnvironment /* expand */);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
/* Is the subsystem definition non-empty? */
|
|
if (DataLength > sizeof Data[0])
|
|
{
|
|
WCHAR ImagePath [MAX_PATH + 1] = {0};
|
|
PWCHAR CommandLine = ImagePath;
|
|
RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
|
|
|
|
wcscpy (ImagePath, L"\\??\\");
|
|
wcscat (ImagePath, Data);
|
|
/*
|
|
* Look for the beginning of the command line.
|
|
*/
|
|
for (; (*CommandLine != L'\0') && (*CommandLine != L' ');
|
|
CommandLine ++);
|
|
for (; *CommandLine == L' '; CommandLine ++)
|
|
{
|
|
*CommandLine = L'\0';
|
|
}
|
|
/*
|
|
* Create a native process (suspended).
|
|
*/
|
|
ProcessInfo.Size = sizeof ProcessInfo;
|
|
Request->SmHeader.Status =
|
|
SmCreateUserProcess(ImagePath,
|
|
CommandLine,
|
|
SM_CREATE_FLAG_RESERVE_1MB,
|
|
NULL, /* timeout */
|
|
& ProcessInfo);
|
|
if (NT_SUCCESS(Request->SmHeader.Status))
|
|
{
|
|
Status = SmCreateClient (& ProcessInfo, Name);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, Status);
|
|
//Status = SmDestroyClient TODO
|
|
}
|
|
} else {
|
|
DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
|
|
__FUNCTION__, Status);
|
|
}
|
|
NtClose(ProcessInfo.ThreadHandle);
|
|
NtClose(ProcessInfo.ProcessHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* OK, the definition is empty, but check
|
|
* if it is the name of an embedded subsystem.
|
|
*/
|
|
if(0 == _wcsicmp(L"DEBUG", Name))
|
|
{
|
|
/*
|
|
* Initialize the embedded DBGSS.
|
|
*/
|
|
Request->SmHeader.Status = SmInitializeDbgSs();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Badly defined subsystem. Check the registry!
|
|
*/
|
|
Request->SmHeader.Status = STATUS_NOT_FOUND;
|
|
}
|
|
}
|
|
} else {
|
|
/* It couldn't lookup the Name! */
|
|
Request->SmHeader.Status = Status;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|