2008-09-23 10:47:10 +00:00
|
|
|
/*
|
|
|
|
* 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
|
2005-05-22 16:10:10 +00:00
|
|
|
*/
|
2008-09-23 10:47:10 +00:00
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
2005-05-22 16:10:10 +00:00
|
|
|
#include "smss.h"
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2006-04-26 04:49:11 +00:00
|
|
|
static const WCHAR szSystemDirectory[] = L"\\System32";
|
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* SmCreateUserProcess/5
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
2005-08-27 09:55:27 +00:00
|
|
|
* ImagePath: absolute path of the image to run;
|
2005-05-22 16:10:10 +00:00
|
|
|
* CommandLine: arguments and options for ImagePath;
|
2008-09-24 08:12:41 +00:00
|
|
|
* Flags: Wait flag: Set for boot time processes and unset for
|
|
|
|
* subsystems bootstrapping;
|
|
|
|
* 1Mb reserve flag: Set for subsystems, unset for everything
|
|
|
|
* else
|
2005-05-22 16:10:10 +00:00
|
|
|
* Timeout: optional: used if WaitForIt==TRUE;
|
|
|
|
* ProcessHandle: optional: a duplicated handle for
|
|
|
|
the child process (storage provided by the caller).
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* NTSTATUS:
|
|
|
|
*
|
|
|
|
*/
|
2008-11-30 11:16:55 +00:00
|
|
|
NTSTATUS NTAPI
|
2005-05-22 16:10:10 +00:00
|
|
|
SmCreateUserProcess (LPWSTR ImagePath,
|
|
|
|
LPWSTR CommandLine,
|
2008-09-24 08:12:41 +00:00
|
|
|
ULONG Flags,
|
2005-05-22 16:10:10 +00:00
|
|
|
PLARGE_INTEGER Timeout OPTIONAL,
|
2005-07-12 01:56:14 +00:00
|
|
|
PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL)
|
2005-05-22 16:10:10 +00:00
|
|
|
{
|
2008-12-03 17:34:49 +00:00
|
|
|
UNICODE_STRING ImagePathString = { 0, 0, NULL };
|
|
|
|
UNICODE_STRING CommandLineString = { 0, 0, NULL };
|
|
|
|
UNICODE_STRING SystemDirectory = { 0, 0, NULL };
|
2005-05-22 16:10:10 +00:00
|
|
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
|
2008-12-03 17:34:49 +00:00
|
|
|
RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
|
|
|
|
PRTL_USER_PROCESS_INFORMATION pProcessInfo = & ProcessInfo;
|
2005-05-22 16:10:10 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
DPRINT("SM: %s called\n", __FUNCTION__);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
if (NULL != UserProcessInfo)
|
|
|
|
{
|
|
|
|
pProcessInfo = UserProcessInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitUnicodeString (& ImagePathString, ImagePath);
|
|
|
|
RtlInitUnicodeString (& CommandLineString, CommandLine);
|
|
|
|
|
2006-04-26 04:49:11 +00:00
|
|
|
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;
|
|
|
|
}
|
[SMSS]: Remove the ROS_DOESNT_SUCK hack, and correctly started subsystem processes with the first MB reserved.
[CSRSRV]: CSRSS was started with a free address space, and was able to map 0xA0000 into it by luck, because the ReactOS Mm allocator picks address ranges randomly, and it somehow managed to avoid the low 1MB addresses. Were this algorithm to change, or perhaps, were we to implement VADs for VM allocations, the 0xA0000 region might already be allocated (by an early-process-initialization allocation, such as the heap). This is what the flag referenced above was designed for, but it was not used. Using this flag, on the other hand, now makes CSRSS fail, because it attempts to map the RAM into 0xA0000, which fails since you can map a section on top of reserved memory. To work around this Brobdingnagian annoyance, CSRSS simply releases the first MB of memory that SMSS has nicely reserved for it, and then proceeds with the mapping. This fixes the issue of getting 0xA0000 by luck and now guarantees it can be mapped.
svn path=/trunk/; revision=49133
2010-10-12 21:17:58 +00:00
|
|
|
|
2008-09-24 08:12:41 +00:00
|
|
|
/* Reserve lower 1Mb, if requested */
|
|
|
|
if (Flags & SM_CREATE_FLAG_RESERVE_1MB)
|
|
|
|
ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
|
[SMSS]: Remove the ROS_DOESNT_SUCK hack, and correctly started subsystem processes with the first MB reserved.
[CSRSRV]: CSRSS was started with a free address space, and was able to map 0xA0000 into it by luck, because the ReactOS Mm allocator picks address ranges randomly, and it somehow managed to avoid the low 1MB addresses. Were this algorithm to change, or perhaps, were we to implement VADs for VM allocations, the 0xA0000 region might already be allocated (by an early-process-initialization allocation, such as the heap). This is what the flag referenced above was designed for, but it was not used. Using this flag, on the other hand, now makes CSRSS fail, because it attempts to map the RAM into 0xA0000, which fails since you can map a section on top of reserved memory. To work around this Brobdingnagian annoyance, CSRSS simply releases the first MB of memory that SMSS has nicely reserved for it, and then proceeds with the mapping. This fixes the issue of getting 0xA0000 by luck and now guarantees it can be mapped.
svn path=/trunk/; revision=49133
2010-10-12 21:17:58 +00:00
|
|
|
|
2008-09-24 08:12:41 +00:00
|
|
|
/* Create the user process */
|
2005-05-22 16:10:10 +00:00
|
|
|
Status = RtlCreateUserProcess (& ImagePathString,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
ProcessParameters,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
FALSE,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
pProcessInfo);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
RtlDestroyProcessParameters (ProcessParameters);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
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 */
|
2008-09-24 08:12:41 +00:00
|
|
|
if (Flags & SM_CREATE_FLAG_WAIT)
|
2005-05-22 16:10:10 +00:00
|
|
|
{
|
|
|
|
Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
|
|
|
|
FALSE,
|
|
|
|
Timeout);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
|
|
|
|
__FUNCTION__, Status);
|
|
|
|
}
|
|
|
|
}
|
2008-09-24 08:12:41 +00:00
|
|
|
|
|
|
|
if (NULL == UserProcessInfo)
|
|
|
|
{
|
|
|
|
NtClose(pProcessInfo->ProcessHandle);
|
|
|
|
NtClose(pProcessInfo->ThreadHandle);
|
|
|
|
}
|
2005-05-22 16:10:10 +00:00
|
|
|
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;
|
|
|
|
}
|
2007-11-21 21:25:26 +00:00
|
|
|
DPRINT("SM: %s called from CID(%p|%p)\n",
|
2005-05-22 16:10:10 +00:00
|
|
|
__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;
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
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,
|
2005-06-02 13:17:37 +00:00
|
|
|
SmSystemEnvironment /* expand */);
|
2005-05-22 16:10:10 +00:00
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Is the subsystem definition non-empty? */
|
|
|
|
if (DataLength > sizeof Data[0])
|
|
|
|
{
|
|
|
|
WCHAR ImagePath [MAX_PATH + 1] = {0};
|
|
|
|
PWCHAR CommandLine = ImagePath;
|
2005-07-12 01:56:14 +00:00
|
|
|
RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
|
2005-05-22 16:10:10 +00:00
|
|
|
|
|
|
|
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,
|
2008-09-24 08:12:41 +00:00
|
|
|
SM_CREATE_FLAG_RESERVE_1MB,
|
|
|
|
NULL, /* timeout */
|
|
|
|
& ProcessInfo);
|
2005-05-22 16:10:10 +00:00
|
|
|
if (NT_SUCCESS(Request->SmHeader.Status))
|
|
|
|
{
|
|
|
|
Status = SmCreateClient (& ProcessInfo, Name);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2005-08-27 09:55:27 +00:00
|
|
|
DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
|
|
|
|
__FUNCTION__, Status);
|
2005-05-22 16:10:10 +00:00
|
|
|
//Status = SmDestroyClient TODO
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
|
|
|
|
__FUNCTION__, Status);
|
|
|
|
}
|
2008-07-31 21:33:17 +00:00
|
|
|
NtClose(ProcessInfo.ThreadHandle);
|
|
|
|
NtClose(ProcessInfo.ProcessHandle);
|
2005-05-22 16:10:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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 */
|