ReactOS 0.4.15-dev-8093-g3285f69
smutils.c File Reference
#include "precomp.h"
#include <windef.h>
#include <winreg.h>
#include <ndk/cmfuncs.h>
#include <sm/helper.h>
#include <debug.h>
Include dependency graph for smutils.c:

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 
#define _INC_WINDOWS
 
#define COM_NO_WINDOWS_H
 
#define NTOS_MODE_USER
 
#define NDEBUG
 

Functions

NTSTATUS NTAPI SmExecuteProgram (_In_ HANDLE SmApiPort, _In_ PUNICODE_STRING Program)
 This function is used to make the SM start an external process under an already-loaded environment subsystem server.
 
NTSTATUS NTAPI SmLookupSubsystem (_In_ PWSTR Name, _Out_ PWSTR Data, _Inout_ PULONG DataLength, _Out_opt_ PULONG DataType, _In_opt_ PVOID Environment)
 Reads from the registry key \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems the value specified by Name.
 
NTSTATUS NTAPI SmQueryInformation (_In_ HANDLE SmApiPort, _In_ SM_INFORMATION_CLASS SmInformationClass, _Inout_ PVOID Data, _In_ ULONG DataLength, _Inout_opt_ PULONG ReturnedDataLength)
 Retrieves information about subsystems registered with the SM.
 

Variables

BOOLEAN SmpDebug = FALSE
 

Macro Definition Documentation

◆ _INC_WINDOWS

#define _INC_WINDOWS

Definition at line 12 of file smutils.c.

◆ COM_NO_WINDOWS_H

#define COM_NO_WINDOWS_H

Definition at line 13 of file smutils.c.

◆ NDEBUG

#define NDEBUG

Definition at line 22 of file smutils.c.

◆ NTOS_MODE_USER

#define NTOS_MODE_USER

Definition at line 17 of file smutils.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 11 of file smutils.c.

Function Documentation

◆ SmExecuteProgram()

NTSTATUS NTAPI SmExecuteProgram ( _In_ HANDLE  SmApiPort,
_In_ PUNICODE_STRING  Program 
)

This function is used to make the SM start an external process under an already-loaded environment subsystem server.

Parameters
[in]SmApiPortPort handle returned by SmConnectToSm().
[in]ProgramFully qualified NT name of the executable to load.
Returns
Success status as handed by the SM reply; otherwise a failure status code.
Remarks
Adapted from SMSS' SmpExecuteInitialCommand() and SmpExecuteImage().

Definition at line 51 of file smutils.c.

55{
56 // ULONG MuSessionId;
57
60 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
61
62 PUNICODE_STRING FileName = Program; // FIXME!
63 PUNICODE_STRING Directory = NULL; // FIXME!
64 PUNICODE_STRING CommandLine = NULL; // FIXME!
65
66 PVOID SmpDefaultEnvironment = NtCurrentPeb()->ProcessParameters->Environment;
67 // UNICODE_STRING SmpDefaultLibPath;
68
69 DPRINT("SMLIB: %s(%p, '%wZ') called\n",
70 __FUNCTION__, SmApiPort, Program);
71
72 /* Parameters validation */
73 if (!SmApiPort)
75 if (!Program)
77
78 /* Create parameters for the target process, using the current environment */
79 Status = RtlCreateProcessParameters(&ProcessParameters,
81 /* SmpDefaultLibPath.Length ?
82 &SmpDefaultLibPath : */ NULL,
84 CommandLine,
86 NULL,
87 NULL,
88 NULL,
89 0);
90 if (!NT_SUCCESS(Status))
91 {
92 DPRINT1("SMLIB: RtlCreateProcessParameters failed for %wZ - Status == %lx\n",
94 return Status;
95 }
96
97 /* Set the size field as required */
98 ProcessInfo.Size = sizeof(ProcessInfo);
99
100 /* Otherwise inherit the flag that was passed to SMSS itself */
101 ProcessParameters->DebugFlags = SmpDebug;
102
103 /* And always force NX for anything that SMSS launches */
104 ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX;
105
106 /* Now create the process in suspended state */
109 ProcessParameters,
110 NULL,
111 NULL,
112 NULL,
113 FALSE,
114 NULL,
115 NULL,
116 &ProcessInfo);
117 RtlDestroyProcessParameters(ProcessParameters);
118 if (!NT_SUCCESS(Status))
119 {
120 /* If we couldn't create it, fail back to the caller */
121 DPRINT1("SMLIB: Failed load of %wZ - Status == %lx\n",
123 return Status;
124 }
125
126 // /* Now duplicate the handle to this process */
127 // Status = NtDuplicateObject(NtCurrentProcess(),
128 // ProcessInfo.ProcessHandle,
129 // NtCurrentProcess(),
130 // InitialCommandProcess,
131 // PROCESS_ALL_ACCESS,
132 // 0,
133 // 0);
134 // if (!NT_SUCCESS(Status))
135 // {
136 // /* Kill it utterly if duplication failed */
137 // DPRINT1("SMLIB: DupObject Failed. Status == %lx\n", Status);
138 // NtTerminateProcess(ProcessInfo.ProcessHandle, Status);
139 // NtResumeThread(ProcessInfo.ThreadHandle, NULL);
140 // NtClose(ProcessInfo.ThreadHandle);
141 // NtClose(ProcessInfo.ProcessHandle);
142 // return Status;
143 // }
144
145 /* Call SM and wait for a reply */
146 Status = SmExecPgm(SmApiPort, &ProcessInfo, TRUE);
147
148 NtClose(ProcessInfo.ThreadHandle);
149 NtClose(ProcessInfo.ProcessHandle);
150
151 // if (ProcessInformation)
152 // *ProcessInformation = ProcessInfo;
153
154 DPRINT("SMLIB: %s returned (Status=0x%08lx)\n", __FUNCTION__, Status);
155 return Status;
156}
#define NtCurrentPeb()
Definition: FLS.c:22
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define __FUNCTION__
Definition: types.h:116
Status
Definition: gdiplustypes.h:25
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS NTAPI RtlDestroyProcessParameters(_In_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
NTSYSAPI NTSTATUS NTAPI RtlCreateProcessParameters(_Out_ PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, _In_ PUNICODE_STRING ImagePathName, _In_opt_ PUNICODE_STRING DllPath, _In_opt_ PUNICODE_STRING CurrentDirectory, _In_opt_ PUNICODE_STRING CommandLine, _In_opt_ PWSTR Environment, _In_opt_ PUNICODE_STRING WindowTitle, _In_opt_ PUNICODE_STRING DesktopInfo, _In_opt_ PUNICODE_STRING ShellInfo, _In_opt_ PUNICODE_STRING RuntimeInfo)
NTSYSAPI NTSTATUS NTAPI RtlCreateUserProcess(_In_ PUNICODE_STRING ImageFileName, _In_ ULONG Attributes, _In_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters, _In_opt_ PSECURITY_DESCRIPTOR ProcessSecutityDescriptor, _In_opt_ PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, _In_opt_ HANDLE ParentProcess, _In_ BOOLEAN CurrentDirectory, _In_opt_ HANDLE DebugPort, _In_opt_ HANDLE ExceptionPort, _Out_ PRTL_USER_PROCESS_INFORMATION ProcessInfo)
#define RTL_USER_PROCESS_PARAMETERS_NX
Definition: rtltypes.h:55
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
PWCHAR SmpDefaultEnvironment
Definition: sminit.c:28
NTSTATUS NTAPI SmExecPgm(_In_ HANDLE SmApiPort, _In_ PRTL_USER_PROCESS_INFORMATION ProcessInformation, _In_ BOOLEAN DebugFlag)
Requests the SM to start a process under a new environment session.
Definition: smclient.c:265
HANDLE SmApiPort
Definition: smss.c:23
BOOLEAN SmpDebug
Definition: smutils.c:28
#define DPRINT
Definition: sndvol32.h:73
base for all directory entries
Definition: entries.h:138

◆ SmLookupSubsystem()

NTSTATUS NTAPI SmLookupSubsystem ( _In_ PWSTR  Name,
_Out_ PWSTR  Data,
_Inout_ PULONG  DataLength,
_Out_opt_ PULONG  DataType,
_In_opt_ PVOID  Environment 
)

Reads from the registry key \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems the value specified by Name.

Parameters
[in]NameName of the program to run, that is a value's name in the SM registry key "SubSystems".
[out]DataWhat the registry gave back for Name.
[in,out]DataLengthHow much Data the registry returns.
[out]DataTypeOptional pointer to a variable that receives the type of data stored in the specified value.
[in]EnvironmentOptional environment to be used to possibly expand Data before returning it back; if set to NULL, no expansion will be performed.
Returns
Success status if the specified subsystem existed and its information has been retrieved successfully; otherwise a failure status code.

Definition at line 188 of file smutils.c.

194{
196 UNICODE_STRING usKeyName;
198 HANDLE hKey = NULL;
199
200 UNICODE_STRING usValueName;
201 PWCHAR KeyValueInformation = NULL;
202 ULONG KeyValueInformationLength = 1024;
205
206 DPRINT("SMLIB: %s(Name='%S') called\n", __FUNCTION__, Name);
207
208 /*
209 * Prepare the key name to scan and
210 * related object attributes.
211 */
212 RtlInitUnicodeString(&usKeyName,
213 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");
214
216 &usKeyName,
218 NULL,
219 NULL);
220 /*
221 * Open the key. This MUST NOT fail, if the
222 * request is for a legitimate subsystem.
223 */
226 &Oa);
227 if (!NT_SUCCESS(Status))
228 {
229 DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
230 return Status;
231 }
232
233 KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(),
234 0,
235 KeyValueInformationLength);
236 if (!KeyValueInformation)
237 {
238 NtClose(hKey);
239 return STATUS_NO_MEMORY;
240 }
241
242 kvpi = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueInformation;
243 RtlInitUnicodeString(&usValueName, Name);
245 &usValueName,
247 KeyValueInformation,
248 KeyValueInformationLength,
249 &ResultLength);
250 if (!NT_SUCCESS(Status))
251 {
252 DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
253
254 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation);
255 NtClose(hKey);
256
257 return Status;
258 }
259
260 DPRINT("kvpi.TitleIndex = %lu\n", kvpi->TitleIndex);
261 DPRINT("kvpi.Type = %lu\n", kvpi->Type);
262 DPRINT("kvpi.DataLength = %lu\n", kvpi->DataLength);
263
264 if (Data && DataLength)
265 {
266 if (DataType)
267 *DataType = kvpi->Type;
268
269 if (Environment && (kvpi->Type == REG_EXPAND_SZ))
270 {
273 PWCHAR DestinationBuffer = NULL;
275
276 DPRINT("SMLIB: %s: value will be expanded\n", __FUNCTION__);
277
278 Length = 2 * KeyValueInformationLength;
279 DestinationBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
280 0,
281 Length);
282 if (!DestinationBuffer)
283 {
285 }
286 else
287 {
288 Source.Length = (USHORT)kvpi->DataLength;
289 Source.MaximumLength = Source.Length;
290 Source.Buffer = (PWCHAR)&kvpi->Data;
291
292 RtlInitEmptyUnicodeString(&Destination,
293 DestinationBuffer,
294 (USHORT)Length);
295
296 Length = 0;
298 &Source,
300 &Length);
301 if (NT_SUCCESS(Status))
302 {
305 }
306 RtlFreeHeap(RtlGetProcessHeap(), 0, DestinationBuffer);
307 }
308 }
309 else
310 {
311 DPRINT("SMLIB: %s: value won't be expanded\n", __FUNCTION__);
314 }
315 }
316 else
317 {
318 DPRINT1("SMLIB: %s: Data or DataLength is NULL!\n", __FUNCTION__);
320 }
321
322 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation);
323 NtClose(hKey);
324
325 return Status;
326}
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
FxAutoRegKey hKey
NTSYSAPI NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PCWSTR, const UNICODE_STRING *, UNICODE_STRING *, ULONG *)
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
DataType
Definition: simd.h:252
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776

◆ SmQueryInformation()

NTSTATUS NTAPI SmQueryInformation ( _In_ HANDLE  SmApiPort,
_In_ SM_INFORMATION_CLASS  SmInformationClass,
_Inout_ PVOID  Data,
_In_ ULONG  DataLength,
_Inout_opt_ PULONG  ReturnedDataLength 
)

Retrieves information about subsystems registered with the SM.

Parameters
[in]SmApiPortPort handle returned by SmConnectToSm().
[in]SmInformationClassAn SM information class ID:
  • SmBasicInformation: The number and list of registered subsystems. Data is returned in a SM_BASIC_INFORMATION structure.
  • SmSubSystemInformation: Information about a particular registered subsystem. Data is returned in a SM_SUBSYSTEM_INFORMATION structure.
[in,out]DataPointer to storage for the information to request. Either a SM_BASIC_INFORMATION or a SM_SUBSYSTEM_INFORMATION, depending on the information class.
[in]DataLengthLength in bytes of the Data buffer; it must be set and must match the SmInformationClass information size.
[in,out]ReturnedDataLengthOptional pointer to storage to receive the size of the returned data.
Returns
STATUS_SUCCESS when the information asked for has been retrieved. STATUS_INVALID_PARAMETER_2 if an invalid information class has been provided. STATUS_INFO_LENGTH_MISMATCH in case either DataLength was set to 0 or to a value that does not match what the SmInformationClass requires. Otherwise, a success status as handed by the SM reply, or a failure status code.
Remarks
This API is ReactOS-specific and not in NT.

Definition at line 369 of file smutils.c.

375{
376#if defined(__REACTOS__) && DBG
378 SM_API_MSG SmApiMsg = {0};
379 PSM_QUERYINFO_MSG QueryInfo = &SmApiMsg.u.QueryInfo;
380
381 /* Marshal data in the port message */
382 switch (SmInformationClass)
383 {
385 if (DataLength != sizeof(SM_BASIC_INFORMATION))
386 {
388 }
390 QueryInfo->DataLength = DataLength;
391 QueryInfo->BasicInformation.SubSystemCount = 0;
392 break;
393
396 {
398 }
400 QueryInfo->DataLength = DataLength;
402 ((PSM_SUBSYSTEM_INFORMATION)Data)->SubSystemId;
403 break;
404
405 default:
407 }
408
409 /* SM API to invoke */
411
412 /* NOTE: Repurpose the DataLength variable */
414
415 /* Fill out the Port Message Header */
416 // SmApiMsg.h.u2.s2.Type = LPC_NEW_MESSAGE;
417 SmApiMsg.h.u2.ZeroInit = 0;
418 /* DataLength = user_data_size + anything between
419 * header and data, including intermediate padding */
420 SmApiMsg.h.u1.s1.DataLength = (CSHORT)DataLength +
421 FIELD_OFFSET(SM_API_MSG, u) - sizeof(SmApiMsg.h);
422 /* TotalLength = sizeof(SmApiMsg) on <= NT5.2, otherwise:
423 * DataLength + header_size == user_data_size + FIELD_OFFSET(SM_API_MSG, u)
424 * without structure trailing padding */
425 SmApiMsg.h.u1.s1.TotalLength = SmApiMsg.h.u1.s1.DataLength + sizeof(SmApiMsg.h);
426
427 /* Send the LPC message and wait for a reply */
428 Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h);
429 if (!NT_SUCCESS(Status))
430 {
431 DPRINT1("SMLIB: %s: NtRequestWaitReplyPort failed, Status: 0x%08lx\n",
433 return Status;
434 }
435
436 /* Unmarshal data */
438 &QueryInfo->BasicInformation,
439 QueryInfo->DataLength);
440
441 /* Use caller provided storage to store data size */
442 if (ReturnedDataLength)
443 *ReturnedDataLength = QueryInfo->DataLength;
444
445 /* Return the real status */
446 return SmApiMsg.ReturnValue;
447#else
449#endif /* defined(__REACTOS__) && DBG */
450}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
NTSTATUS NTAPI NtRequestWaitReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE LpcRequest, IN OUT PPORT_MESSAGE LpcReply)
Definition: send.c:696
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
struct _SM_SUBSYSTEM_INFORMATION * PSM_SUBSYSTEM_INFORMATION
#define SM_API_QUERY_INFORMATION
Definition: smrosdbg.h:17
@ SmBasicInformation
Definition: smrosdbg.h:23
@ SmSubSystemInformation
Definition: smrosdbg.h:24
struct _SM_QUERYINFO_MSG SM_QUERYINFO_MSG
union _SM_API_MSG::@3529 u
NTSTATUS ReturnValue
Definition: smmsg.h:106
PORT_MESSAGE h
Definition: smmsg.h:104
SMSRV_API_NUMBER ApiNumber
Definition: smmsg.h:105
SM_INFORMATION_CLASS SmInformationClass
Definition: smrosdbg.h:49
SM_SUBSYSTEM_INFORMATION SubSystemInformation
Definition: smrosdbg.h:54
SM_BASIC_INFORMATION BasicInformation
Definition: smrosdbg.h:53
ULONG DataLength
Definition: smrosdbg.h:50
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
short CSHORT
Definition: umtypes.h:127

Variable Documentation

◆ SmpDebug

BOOLEAN SmpDebug = FALSE

Definition at line 28 of file smutils.c.

Referenced by SmExecuteProgram().