2005-05-22 16:10:10 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
* smapiexec.c - SM_API_EXECUTE_PROGRAM
|
|
|
|
*
|
|
|
|
* Reactos Session Manager
|
|
|
|
*
|
|
|
|
* --------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* This software is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this software; see the file COPYING.LIB. If not, write
|
|
|
|
* to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
|
2007-10-19 23:21:45 +00:00
|
|
|
* MA 02139, USA.
|
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;
|
|
|
|
* WaitForIt: TRUE for boot time processes and FALSE for
|
|
|
|
* subsystems bootstrapping;
|
|
|
|
* Timeout: optional: used if WaitForIt==TRUE;
|
|
|
|
* ProcessHandle: optional: a duplicated handle for
|
|
|
|
the child process (storage provided by the caller).
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* NTSTATUS:
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
SmCreateUserProcess (LPWSTR ImagePath,
|
|
|
|
LPWSTR CommandLine,
|
|
|
|
BOOLEAN WaitForIt,
|
|
|
|
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
|
|
|
{
|
|
|
|
UNICODE_STRING ImagePathString = {0};
|
|
|
|
UNICODE_STRING CommandLineString = {0};
|
2006-04-26 04:49:11 +00:00
|
|
|
UNICODE_STRING SystemDirectory = {0};
|
2005-05-22 16:10:10 +00:00
|
|
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
|
2005-07-12 01:56:14 +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;
|
|
|
|
}
|
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 */
|
|
|
|
if (WaitForIt)
|
|
|
|
{
|
|
|
|
Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
|
|
|
|
FALSE,
|
|
|
|
Timeout);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
|
|
|
|
__FUNCTION__, Status);
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-05-22 16:10:10 +00:00
|
|
|
}
|
2005-05-30 20:11:44 +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,
|
|
|
|
FALSE, /* wait */
|
|
|
|
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))
|
|
|
|
{
|
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 */
|