ReactOS 0.4.15-dev-7953-g1f49173
smutils.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS SM Helper Library
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Utility functions built around the client SM API
5 * COPYRIGHT: Copyright 2005 Emanuele Aliberti <ea@reactos.com>
6 * Copyright 2022 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7 */
8
9#include "precomp.h"
10
11#define WIN32_NO_STATUS
12#define _INC_WINDOWS
13#define COM_NO_WINDOWS_H
14#include <windef.h>
15#include <winreg.h>
16
17#define NTOS_MODE_USER
18#include <ndk/cmfuncs.h>
19
20#include <sm/helper.h>
21
22#define NDEBUG
23#include <debug.h>
24
25#if DBG
27#else
29#endif
30
53 _In_ PUNICODE_STRING Program /*,
54 _Out_opt_ PRTL_USER_PROCESS_INFORMATION ProcessInformation*/)
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}
157
187NTAPI
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}
327
368NTAPI
371 _In_ SM_INFORMATION_CLASS SmInformationClass,
374 _Inout_opt_ PULONG ReturnedDataLength)
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}
451
452/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
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
#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
FxAutoRegKey hKey
Status
Definition: gdiplustypes.h:25
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
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
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
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
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)
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
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
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)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
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
NTSTATUS NTAPI NtRequestWaitReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE LpcRequest, IN OUT PPORT_MESSAGE LpcReply)
Definition: send.c:696
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
DataType
Definition: simd.h:252
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
struct _SM_SUBSYSTEM_INFORMATION * PSM_SUBSYSTEM_INFORMATION
#define SM_API_QUERY_INFORMATION
Definition: smrosdbg.h:17
SM_INFORMATION_CLASS
Definition: smrosdbg.h:22
@ SmBasicInformation
Definition: smrosdbg.h:23
@ SmSubSystemInformation
Definition: smrosdbg.h:24
struct _SM_QUERYINFO_MSG SM_QUERYINFO_MSG
HANDLE SmApiPort
Definition: smss.c:23
BOOLEAN SmpDebug
Definition: smutils.c:28
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 su...
Definition: smutils.c:51
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.
Definition: smutils.c:369
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...
Definition: smutils.c:188
#define DPRINT
Definition: sndvol32.h:71
base for all directory entries
Definition: entries.h:138
union _SM_API_MSG::@3525 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
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#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
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
short CSHORT
Definition: umtypes.h:127
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776