diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index c2b00882c2d..96200db55dc 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -688,7 +688,7 @@ @ stdcall RtlComputeCrc32(long ptr long) @ stdcall RtlComputeImportTableHash(ptr ptr long) @ stdcall RtlComputePrivatizedDllName_U(ptr ptr ptr) -@ stub -version=0x600+ RtlConnectToSm +@ stdcall -stub -version=0x600+ RtlConnectToSm(ptr ptr long ptr) @ stdcall RtlConsoleMultiByteToUnicodeN(ptr long ptr ptr long ptr) @ stdcall RtlConvertExclusiveToShared(ptr) @ stub -version=0x600+ RtlConvertLCIDToString @@ -1133,7 +1133,7 @@ @ stdcall RtlSeekMemoryStream(ptr int64 long ptr) @ stdcall RtlSelfRelativeToAbsoluteSD2(ptr ptr) @ stdcall RtlSelfRelativeToAbsoluteSD(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) -@ stub -version=0x600+ RtlSendMsgToSm +@ stdcall -stub -version=0x600+ RtlSendMsgToSm(ptr ptr) @ stdcall RtlSetAllBits(ptr) @ stdcall RtlSetAttributesSecurityDescriptor(ptr long ptr) @ stdcall RtlSetBits(ptr long long) diff --git a/dll/ntdll/nt_0600/CMakeLists.txt b/dll/ntdll/nt_0600/CMakeLists.txt index 061502ac7f1..9cc2c32e192 100644 --- a/dll/ntdll/nt_0600/CMakeLists.txt +++ b/dll/ntdll/nt_0600/CMakeLists.txt @@ -16,7 +16,7 @@ list(APPEND SOURCE add_library(ntdll_vista MODULE ${SOURCE}) set_module_type(ntdll_vista win32dll ENTRYPOINT DllMain 12) -target_link_libraries(ntdll_vista rtl_vista) +target_link_libraries(ntdll_vista smlib rtl_vista) if(ARCH STREQUAL "arm") target_link_libraries(ntdll_vista chkstk) endif() diff --git a/dll/ntdll/nt_0600/ntdll_vista.spec b/dll/ntdll/nt_0600/ntdll_vista.spec index 1a3098dde3f..d36c6449d8e 100644 --- a/dll/ntdll/nt_0600/ntdll_vista.spec +++ b/dll/ntdll/nt_0600/ntdll_vista.spec @@ -12,3 +12,6 @@ @ stdcall RtlRunOnceBeginInitialize(ptr long ptr) @ stdcall RtlRunOnceComplete(ptr long ptr) @ stdcall RtlRunOnceExecuteOnce(ptr ptr ptr ptr) + +@ stdcall RtlConnectToSm(ptr ptr long ptr) SmConnectToSm +@ stdcall RtlSendMsgToSm(ptr ptr) SmSendMsgToSm diff --git a/dll/win32/CMakeLists.txt b/dll/win32/CMakeLists.txt index fad02b4cc03..50c4080a8ca 100644 --- a/dll/win32/CMakeLists.txt +++ b/dll/win32/CMakeLists.txt @@ -192,7 +192,6 @@ add_subdirectory(shfolder) add_subdirectory(shimgvw) add_subdirectory(shlwapi) add_subdirectory(slbcsp) -add_subdirectory(smdll) add_subdirectory(sndblst) add_subdirectory(snmpapi) add_subdirectory(softpub) diff --git a/dll/win32/smdll/CMakeLists.txt b/dll/win32/smdll/CMakeLists.txt deleted file mode 100644 index 9c38ba32b27..00000000000 --- a/dll/win32/smdll/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys) -spec2def(smdll.dll smdll.spec ADD_IMPORTLIB) - -list(APPEND SOURCE - dllmain.c - query.c - precomp.h) - -add_library(smdll MODULE - ${SOURCE} - smdll.rc - ${CMAKE_CURRENT_BINARY_DIR}/smdll.def) - -target_link_libraries(smdll smlib) -set_module_type(smdll nativedll ENTRYPOINT DllMainCRTStartup 12) -add_importlibs(smdll ntdll) -add_pch(smdll precomp.h SOURCE) -add_dependencies(smdll psdk) -add_cd_file(TARGET smdll DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/smdll/dllmain.c b/dll/win32/smdll/dllmain.c deleted file mode 100644 index 604f8944d40..00000000000 --- a/dll/win32/smdll/dllmain.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS - * FILE: lib/smdll/dllmain.c - * PURPOSE: SM Helper Library - */ - -#include "precomp.h" - -BOOL WINAPI DllMainCRTStartup(HANDLE hinstDll, DWORD fdwReason, LPVOID fImpLoad) -{ - return TRUE; -} - -/* EOF */ diff --git a/dll/win32/smdll/precomp.h b/dll/win32/smdll/precomp.h deleted file mode 100644 index 2caa290d549..00000000000 --- a/dll/win32/smdll/precomp.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SMDLL_PCH_ -#define _SMDLL_PCH_ - -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -#include - -#endif /* _SMDLL_PCH_ */ diff --git a/dll/win32/smdll/query.c b/dll/win32/smdll/query.c deleted file mode 100644 index d3b6e964398..00000000000 --- a/dll/win32/smdll/query.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/smdll/query.c - * PURPOSE: Call SM API SM_API_QUERY_INFORMATION (not in NT) - */ - -#include "precomp.h" - -#define NTOS_MODE_USER -#include -#include -#include - -#define NDEBUG -#include - - -/********************************************************************** - * NAME EXPORTED - * SmQueryInformation/5 - * - * DESCRIPTION - * Ask the SM to collect some data from its internal data - * structures and send it back. - * - * ARGUMENTS - * hSmApiPort: handle returned by SmConnectApiPort; - * SmInformationClass: an SM information class ID: - * SM_BASIC_INFORMATION: the number of registered subsystems - * Data: pointer to storage for the information to request; - * DataLength: length in bytes of the Data buffer; it must be - * set and must match the SmInformationClass info size; - * ReturnedDataLength: optional pointer to storage to receive - * the size of the returned data. - * - * RETURN VALUE - * STATUS_SUCCESS: OK you get what you asked for; - * STATUS_INFO_LENGTH_MISMATCH: you set DataLength to 0 or to a - * value that does not match whet the SmInformationClass - * requires; - * STATUS_INVALID_PARAMETER_2: bad information class; - * A port error. - * - */ -NTSTATUS WINAPI -SmQueryInformation (IN HANDLE hSmApiPort, - IN SM_INFORMATION_CLASS SmInformationClass, - IN OUT PVOID Data, - IN ULONG DataLength, - IN OUT PULONG ReturnedDataLength OPTIONAL) -{ - NTSTATUS Status = STATUS_SUCCESS; - SM_PORT_MESSAGE SmReqMsg; - - - if(0 == DataLength) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - /* Marshal data in the port message */ - switch (SmInformationClass) - { - case SmBasicInformation: - if(DataLength != sizeof (SM_BASIC_INFORMATION)) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - SmReqMsg.Request.QryInfo.SmInformationClass = SmBasicInformation; - SmReqMsg.Request.QryInfo.DataLength = DataLength; - SmReqMsg.Request.QryInfo.BasicInformation.SubSystemCount = 0; - break; - case SmSubSystemInformation: - if(DataLength != sizeof (SM_SUBSYSTEM_INFORMATION)) - { - return STATUS_INFO_LENGTH_MISMATCH; - } - SmReqMsg.Request.QryInfo.SmInformationClass = SmSubSystemInformation; - SmReqMsg.Request.QryInfo.DataLength = DataLength; - SmReqMsg.Request.QryInfo.SubSystemInformation.SubSystemId = - ((PSM_SUBSYSTEM_INFORMATION)Data)->SubSystemId; - break; - default: - return STATUS_INVALID_PARAMETER_2; - } - /* SM API to invoke */ - SmReqMsg.SmHeader.ApiIndex = SM_API_QUERY_INFORMATION; - - /* Prepare the port request message */ - SmReqMsg.Header.u2.s2.Type = LPC_NEW_MESSAGE; - SmReqMsg.Header.u1.s1.DataLength = SM_PORT_DATA_SIZE(SmReqMsg.Request); - SmReqMsg.Header.u1.s1.TotalLength = SM_PORT_MESSAGE_SIZE; - Status = NtRequestWaitReplyPort (hSmApiPort, (PPORT_MESSAGE) & SmReqMsg, (PPORT_MESSAGE) & SmReqMsg); - if (NT_SUCCESS(Status)) - { - /* Unmarshal data */ - RtlCopyMemory (Data, & SmReqMsg.Reply.QryInfo.BasicInformation, SmReqMsg.Reply.QryInfo.DataLength); - /* Use caller provided storage to store data size */ - if(NULL != ReturnedDataLength) - { - *ReturnedDataLength = SmReqMsg.Reply.QryInfo.DataLength; - } - return SmReqMsg.SmHeader.Status; - } - DPRINT("SMLIB: %s failed (Status=0x%08lx)\n", __FUNCTION__, Status); - return Status; -} -/* EOF */ diff --git a/dll/win32/smdll/readme.txt b/dll/win32/smdll/readme.txt deleted file mode 100644 index a85f2f10152..00000000000 --- a/dll/win32/smdll/readme.txt +++ /dev/null @@ -1,42 +0,0 @@ - -This is SMDLL: a helper library to talk to the ReactOS session manager (SM). - -It should be linked in the following components: - -a) the SM itself, because it registers for managing native processes - IMAGE_SUBSYSTEM_NATIVE; - -b) environment subsystem servers, because each one should register in - the SM its own subsystem (willing to manage those processes); - -c) terminal emulators for optional subsystems, like posixw32 and os2w32, - to ask the SM to start the optional subsystem server they need connect to; - -d) system and development utilities to debug/query the SM. - -2004-02-15 ea - - -How a subsystem uses these APIs -=============================== - -Thread #0 Thread #1 -- create your own directory (\EXAMPLE) -- create an event E0 -- create your call back API port (\EXAMPLE\SbApiPort) - and serving thread T1 - - wait connection requests on call - back port (\EXAMPLE\SbApiPort) -- SmConnectApiPort( - \EXAMPLE\SbApiPort, - hSbApiPort, - SUBSYSTEM_ID, - & hSmApiPort) -- wait for E0 - - as SM calls back, signal event E0 -- create your API port (\EXAMPLE\ApiPort) and - initialize the subsystem -- call SmCompleteSession (hSmApiPort, - hSbApiPort, - hApiPort) -- manage processes etc. diff --git a/dll/win32/smdll/smdll.rc b/dll/win32/smdll/smdll.rc deleted file mode 100644 index c2277b97fe4..00000000000 --- a/dll/win32/smdll/smdll.rc +++ /dev/null @@ -1,4 +0,0 @@ -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS SM Helper" -#define REACTOS_STR_INTERNAL_NAME "smdll.dll" -#define REACTOS_STR_ORIGINAL_FILENAME "smdll.dll" -#include diff --git a/dll/win32/smdll/smdll.spec b/dll/win32/smdll/smdll.spec deleted file mode 100644 index a917bf979a7..00000000000 --- a/dll/win32/smdll/smdll.spec +++ /dev/null @@ -1,5 +0,0 @@ -@ stdcall SmCompleteSession(ptr ptr ptr) -@ stdcall SmConnectApiPort(ptr ptr long ptr) -@ stdcall SmExecuteProgram(ptr ptr) -@ stdcall SmQueryInformation(ptr long ptr long ptr) -@ stdcall SmLookupSubsystem(ptr ptr ptr ptr ptr) diff --git a/sdk/cmake/baseaddress.cmake b/sdk/cmake/baseaddress.cmake index c8a2c9a81ca..dbaad8bb9ba 100644 --- a/sdk/cmake/baseaddress.cmake +++ b/sdk/cmake/baseaddress.cmake @@ -45,7 +45,6 @@ set(baseaddress_dsound 0x7a040000) set(baseaddress_glu32 0x79f20000) set(baseaddress_opengl32 0x79dc0000) set(baseaddress_riched20 0x79cf0000) -set(baseaddress_smdll 0x79cd0000) set(baseaddress_userenv 0x79c70000) set(baseaddress_uxtheme 0x79c00000) set(baseaddress_cryptui 0x79b40000) diff --git a/sdk/cmake/baseaddress_dwarf.cmake b/sdk/cmake/baseaddress_dwarf.cmake index 8eb2eb74fbb..00b8d491251 100644 --- a/sdk/cmake/baseaddress_dwarf.cmake +++ b/sdk/cmake/baseaddress_dwarf.cmake @@ -45,7 +45,6 @@ set(baseaddress_dsound 0x79080000) set(baseaddress_glu32 0x78ee0000) set(baseaddress_opengl32 0x78d50000) set(baseaddress_riched20 0x78c10000) -set(baseaddress_smdll 0x78be0000) set(baseaddress_userenv 0x78b50000) set(baseaddress_uxtheme 0x78ac0000) set(baseaddress_cryptui 0x789f0000) diff --git a/sdk/cmake/baseaddress_msvc.cmake b/sdk/cmake/baseaddress_msvc.cmake index c56267561d9..a4dee3b4993 100644 --- a/sdk/cmake/baseaddress_msvc.cmake +++ b/sdk/cmake/baseaddress_msvc.cmake @@ -45,7 +45,6 @@ set(baseaddress_dsound 0x7ad60000) set(baseaddress_glu32 0x7ace0000) set(baseaddress_opengl32 0x7ac00000) set(baseaddress_riched20 0x7ab70000) -set(baseaddress_smdll 0x7ab50000) set(baseaddress_userenv 0x7ab10000) set(baseaddress_uxtheme 0x7aac0000) set(baseaddress_cryptui 0x7aa20000) diff --git a/sdk/cmake/baseaddress_msvc_x64.cmake b/sdk/cmake/baseaddress_msvc_x64.cmake index d49365cb457..a9a251aef1d 100644 --- a/sdk/cmake/baseaddress_msvc_x64.cmake +++ b/sdk/cmake/baseaddress_msvc_x64.cmake @@ -44,7 +44,6 @@ set(baseaddress_dsound 0x7FF8F500000) set(baseaddress_glu32 0x7FF8E500000) set(baseaddress_opengl32 0x7FF8D500000) set(baseaddress_riched20 0x7FF8C500000) -set(baseaddress_smdll 0x7FF8B500000) set(baseaddress_userenv 0x7FF8A500000) set(baseaddress_uxtheme 0x7FF89500000) set(baseaddress_cryptui 0x7FF88500000) diff --git a/sdk/include/reactos/subsys/sm/api.h b/sdk/include/reactos/subsys/sm/api.h deleted file mode 100644 index cf3b1778d60..00000000000 --- a/sdk/include/reactos/subsys/sm/api.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __SM_API_H -#define __SM_API_H - -#include - -/*** DATA TYPES ******************************************************/ - -#define SM_SB_NAME_MAX_LENGTH 120 - -#include - -/* SmConnectApiPort (SS->SM) */ -typedef struct _SM_CONNECT_DATA -{ - USHORT SubSystemId; - WORD Unused; - WCHAR SbName [SM_SB_NAME_MAX_LENGTH]; - -} SM_CONNECT_DATA, *PSM_CONNECT_DATA; - -/* SmpConnectSbApiPort (SM->SS) */ -typedef struct _SB_CONNECT_DATA -{ - ULONG SmApiMax; -} SB_CONNECT_DATA, *PSB_CONNECT_DATA; - - -/*** SM API ***/ - -/*** 1 ****************************************************************/ - -#define SM_API_COMPLETE_SESSION 1 /* complete a session initialization */ - -typedef struct _SM_PORT_MESSAGE_COMPSES -{ - HANDLE hApiPort; - HANDLE hSbApiPort; - -} SM_PORT_MESSAGE_COMPSES, *PSM_PORT_MESSAGE_COMPSES; - -/*** 2 ****************************************************************/ - -#define SM_API_2 2 - -/* obsolete */ - -/*** 3 ****************************************************************/ - -#define SM_API_3 3 - -/* unknown */ - -/*** 4 ****************************************************************/ - -#define SM_API_EXECUTE_PROGRAMME 4 /* start a subsystem (server) */ - -#define SM_EXEXPGM_MAX_LENGTH 32 /* max count of wide string */ - -typedef struct _SM_PORT_MESSAGE_EXECPGM -{ - ULONG NameLength; - WCHAR Name [SM_EXEXPGM_MAX_LENGTH]; - -} SM_PORT_MESSAGE_EXECPGM, *PSM_PORT_MESSAGE_EXECPGM; - -/*** 5 ****************************************************************/ - -#define SM_API_QUERY_INFORMATION 5 /* ask SM to send back some data */ - /* Note: this is not in NT */ -#define SM_QRYINFO_MAX_SS_COUNT 8 -#define SM_QRYINFO_MAX_ROOT_NODE 30 - -typedef enum { - SmBasicInformation = 0, - SmSubSystemInformation = 1, -} SM_INFORMATION_CLASS; - -typedef struct _SM_BASIC_INFORMATION -{ - USHORT SubSystemCount; - WORD Unused; - struct { - WORD Id; - WORD Flags; - DWORD ProcessId; - } SubSystem [SM_QRYINFO_MAX_SS_COUNT]; -} SM_BASIC_INFORMATION, *PSM_BASIC_INFORMATION; - -typedef struct _SM_SUBSYSTEM_INFORMATION -{ - WORD SubSystemId; - WORD Flags; - DWORD ProcessId; - WCHAR NameSpaceRootNode [SM_QRYINFO_MAX_ROOT_NODE]; -} SM_SUBSYSTEM_INFORMATION, *PSM_SUBSYSTEM_INFORMATION; - -typedef struct _SM_PORT_MESSAGE_QRYINFO -{ - SM_INFORMATION_CLASS SmInformationClass; - ULONG DataLength; - union { - SM_BASIC_INFORMATION BasicInformation; - SM_SUBSYSTEM_INFORMATION SubSystemInformation; - }; -} SM_PORT_MESSAGE_QRYINFO, * PSM_PORT_MESSAGE_QRYINFO; - -/*** | ****************************************************************/ - -typedef struct _SM_PORT_MESSAGE -{ - /*** LPC common header ***/ - PORT_MESSAGE Header; - union - { - struct - { - /*** SM common header ***/ - struct - { - DWORD ApiIndex; - NTSTATUS Status; - } SmHeader; - /*** SM per API arguments ***/ - union - { - union - { - SM_PORT_MESSAGE_COMPSES CompSes; - SM_PORT_MESSAGE_EXECPGM ExecPgm; - SM_PORT_MESSAGE_QRYINFO QryInfo; - } Request; - union - { - SM_PORT_MESSAGE_COMPSES CompSes; - SM_PORT_MESSAGE_EXECPGM ExecPgm; - SM_PORT_MESSAGE_QRYINFO QryInfo; - } Reply; - }; - }; - SM_CONNECT_DATA ConnectData; - }; -} SM_PORT_MESSAGE, * PSM_PORT_MESSAGE; - -#include - -/*** MACRO ***********************************************************/ - -#define SM_CONNECT_DATA_SIZE(m) ((m).Header.u1.s1.DataLength-sizeof(USHORT)-sizeof(WORD)) -#define SM_PORT_DATA_SIZE(c) (sizeof(DWORD)+sizeof(NTSTATUS)+sizeof(c)) -#define SM_PORT_MESSAGE_SIZE (sizeof(SM_PORT_MESSAGE)) - - -#endif /* !def __SM_API_H */ diff --git a/sdk/include/reactos/subsys/sm/helper.h b/sdk/include/reactos/subsys/sm/helper.h index 82491e7f95f..4d2263e3b97 100644 --- a/sdk/include/reactos/subsys/sm/helper.h +++ b/sdk/include/reactos/subsys/sm/helper.h @@ -1,37 +1,39 @@ -#if !defined(INCLUDE_SM_HELPER_H) -#define INCLUDE_SM_HELPER_H +/* + * PROJECT: ReactOS SM Helper Library + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Utility functions built around the client SM API + * COPYRIGHT: Copyright 2005 Emanuele Aliberti + * Copyright 2022 Hermès Bélusca-Maïto + */ -#if !defined(__SM_API_H) -#include -#endif +#ifndef _SM_HELPER_H_ +#define _SM_HELPER_H_ -/* smlib/connect.c */ -NTSTATUS WINAPI -SmConnectApiPort(IN PUNICODE_STRING pSbApiPortName OPTIONAL, - IN HANDLE hSbApiPort OPTIONAL, - IN WORD wSubsystem OPTIONAL, /* pe.h */ - IN OUT PHANDLE phSmApiPort); -/* smlib/compses.c */ -NTSTATUS WINAPI -SmCompleteSession(IN HANDLE hSmApiPort, - IN HANDLE hSbApiPort, - IN HANDLE hApiPort); -/* smlib/execpgm.c */ -NTSTATUS WINAPI -SmExecuteProgram(IN HANDLE hSmApiPort, - IN PUNICODE_STRING Pgm); -/* smdll/query.c */ -NTSTATUS WINAPI -SmQueryInformation(IN HANDLE SmApiPort, - IN SM_INFORMATION_CLASS SmInformationClass, - IN OUT PVOID Data, - IN ULONG DataLength, - IN OUT PULONG ReturnedDataLength OPTIONAL); -/* smlib/lookupss.c */ -NTSTATUS WINAPI -SmLookupSubsystem(IN PWSTR Name, - IN OUT PWSTR Data, - IN OUT PULONG DataLength, - IN OUT PULONG DataType, - IN PVOID Environment OPTIONAL); -#endif /* ndef INCLUDE_SM_HELPER_H */ +#include "smrosdbg.h" + +NTSTATUS +NTAPI +SmExecuteProgram( + _In_ HANDLE SmApiPort, + _In_ PUNICODE_STRING Pgm /*, + _Out_opt_ PRTL_USER_PROCESS_INFORMATION ProcessInformation*/); + +NTSTATUS +NTAPI +SmLookupSubsystem( + _In_ PWSTR Name, + _Out_ PWSTR Data, + _Inout_ PULONG DataLength, + _Out_opt_ PULONG DataType, + _In_opt_ PVOID Environment); + +NTSTATUS +NTAPI +SmQueryInformation( + _In_ HANDLE SmApiPort, + _In_ SM_INFORMATION_CLASS SmInformationClass, + _Inout_ PVOID Data, + _In_ ULONG DataLength, + _Inout_opt_ PULONG ReturnedDataLength); + +#endif // _SM_HELPER_H_ diff --git a/sdk/include/reactos/subsys/sm/ns.h b/sdk/include/reactos/subsys/sm/ns.h index 2cd37850656..74b30ce9a31 100644 --- a/sdk/include/reactos/subsys/sm/ns.h +++ b/sdk/include/reactos/subsys/sm/ns.h @@ -1,11 +1,11 @@ -#if !defined(INCLUDE_SM_NS_H) -#define INCLUDE_SM_NS_H +#ifndef _SM_NS_H_ +#define _SM_NS_H_ -#define SM_REGISTRY_ROOT_NAME L"\\Session Manager" -#define SM_REGISTRY_SUBSYSTEMS_NAME L"SubSystems" +#define SM_REGISTRY_ROOT_NAME L"\\Session Manager" +#define SM_REGISTRY_SUBSYSTEMS_NAME L"SubSystems" #define SM_API_PORT_NAME L"\\SmApiPort" #define SM_DBGSS_PORT_NAME L"\\DbgSsApiPort" #define SM_DBGUI_PORT_NAME L"\\DbgUiApiPort" -#endif /* ndef INCLUDE_SM_NS_H */ +#endif //_SM_NS_H_ diff --git a/sdk/include/reactos/subsys/sm/smmsg.h b/sdk/include/reactos/subsys/sm/smmsg.h index a5af962fed6..e8f15b5a1a1 100644 --- a/sdk/include/reactos/subsys/sm/smmsg.h +++ b/sdk/include/reactos/subsys/sm/smmsg.h @@ -1,17 +1,19 @@ /* - * PROJECT: ReactOS Windows-Compatible Session Manager - * LICENSE: BSD 2-Clause License - * FILE: include/reactos/subsys/sm/smmsg.h - * PURPOSE: SMSS (SB and SM) Message Format - * PROGRAMMERS: Alex Ionescu + * PROJECT: ReactOS NT-Compatible Session Manager + * LICENSE: BSD 2-Clause License (https://spdx.org/licenses/BSD-2-Clause) + * PURPOSE: SMSS Client (SB and SM) Message Format + * COPYRIGHT: Copyright 2012-2013 Alex Ionescu + * Copyright 2021 Hervé Poussineau + * Copyright 2022 Hermès Bélusca-Maïto */ -#pragma once + #ifndef _SM_MSG_ #define _SM_MSG_ +#pragma once + // // There are the APIs that a Client (such as CSRSS) can send to the SMSS Server. -// // These are called "SM" APIs. // // The exact names are not known, but we are basing them on the SmpApiName array @@ -21,7 +23,6 @@ // The enumeration finishes with an enumeratee holding the maximum API number. // Its name is based on BasepMaxApiNumber, UserpMaxApiNumber... // -// typedef enum _SMSRV_API_NUMBER { SmpCreateForeignSessionApi, @@ -62,6 +63,8 @@ typedef struct _SM_EXEC_PGM_MSG } SM_EXEC_PGM_MSG, *PSM_EXEC_PGM_MSG; #ifndef _WIN64 C_ASSERT(sizeof(SM_EXEC_PGM_MSG) == 0x48); +#else +C_ASSERT(sizeof(SM_EXEC_PGM_MSG) == 0x70); #endif typedef struct _SM_LOAD_DEFERED_SUBSYSTEM_MSG @@ -78,14 +81,23 @@ typedef struct _SM_START_CSR_MSG HANDLE WindowsSubSysProcessId; HANDLE SmpInitialCommandProcessId; } SM_START_CSR_MSG, *PSM_START_CSR_MSG; +#ifndef _WIN64 +C_ASSERT(sizeof(SM_START_CSR_MSG) == 0x110); +#else +C_ASSERT(sizeof(SM_START_CSR_MSG) == 0x118); +#endif typedef struct _SM_STOP_CSR_MSG { ULONG MuSessionId; } SM_STOP_CSR_MSG, *PSM_STOP_CSR_MSG; +#if defined(__REACTOS__) && DBG +#include "smrosdbg.h" +#endif + // -// This is the actual packet structure sent over LCP to the \SmApiPort +// This is the actual packet structure sent over LPC to the \SmApiPort // typedef struct _SM_API_MSG { @@ -101,6 +113,10 @@ typedef struct _SM_API_MSG SM_LOAD_DEFERED_SUBSYSTEM_MSG LoadDefered; SM_START_CSR_MSG StartCsr; SM_STOP_CSR_MSG StopCsr; + +#if defined(__REACTOS__) && DBG + SM_QUERYINFO_MSG QueryInfo; +#endif } u; } SM_API_MSG, *PSM_API_MSG; @@ -109,11 +125,12 @@ typedef struct _SM_API_MSG // #ifndef _WIN64 C_ASSERT(sizeof(SM_API_MSG) == 0x130); +#else +C_ASSERT(sizeof(SM_API_MSG) == 0x148); #endif // // There are the APIs that the SMSS Server can send to a client (such as CSRSS). -// // These are called "SB" APIs. // // The exact names are unknown but we are basing them on the CsrServerSbApiName @@ -124,7 +141,6 @@ C_ASSERT(sizeof(SM_API_MSG) == 0x130); // The enumeration finishes with an enumeratee holding the maximum API number. // Its name is based on BasepMaxApiNumber, UserpMaxApiNumber... // -// typedef enum _SB_API_NUMBER { SbpCreateSession, @@ -143,10 +159,15 @@ typedef struct _SB_CREATE_SESSION_MSG { ULONG SessionId; RTL_USER_PROCESS_INFORMATION ProcessInfo; - ULONG Unknown; + PVOID Unknown; ULONG MuSessionId; CLIENT_ID ClientId; } SB_CREATE_SESSION_MSG, *PSB_CREATE_SESSION_MSG; +#ifndef _WIN64 +C_ASSERT(sizeof(SB_CREATE_SESSION_MSG) == 0x58); +#else +C_ASSERT(sizeof(SB_CREATE_SESSION_MSG) == 0x90); +#endif typedef struct _SB_TERMINATE_SESSION_MSG { @@ -184,6 +205,11 @@ typedef struct _SB_CREATE_PROCESS_MSG } Out; }; } SB_CREATE_PROCESS_MSG, *PSB_CREATE_PROCESS_MSG; +#ifndef _WIN64 +C_ASSERT(sizeof(SB_CREATE_PROCESS_MSG) == 0x18); +#else +C_ASSERT(sizeof(SB_CREATE_PROCESS_MSG) == 0x28); +#endif // // When the server connects to a client, this structure is exchanged @@ -195,7 +221,7 @@ typedef struct _SB_CONNECTION_INFO } SB_CONNECTION_INFO, *PSB_CONNECTION_INFO; // -// This is the actual packet structure sent over LCP to the \SbApiPort +// This is the actual packet structure sent over LPC to the \SbApiPort // typedef struct _SB_API_MSG { @@ -222,8 +248,9 @@ typedef struct _SB_API_MSG // This is the size that Server 2003 SP1 SMSS expects, so make sure we conform. // #ifndef _WIN64 -C_ASSERT(sizeof(SB_CONNECTION_INFO) == 0xF4); C_ASSERT(sizeof(SB_API_MSG) == 0x110); +#else +C_ASSERT(sizeof(SB_API_MSG) == 0x120); #endif // @@ -232,52 +259,55 @@ C_ASSERT(sizeof(SB_API_MSG) == 0x110); typedef BOOLEAN (NTAPI *PSB_API_ROUTINE)( - IN PSB_API_MSG SbApiMsg + _In_ PSB_API_MSG SbApiMsg ); // -// The actual server functions that a client linking with smlib can call +// The actual server functions that a client linking with SMLIB can call. // +/* NTDLL!RtlConnectToSm */ NTSTATUS NTAPI SmConnectToSm( - IN PUNICODE_STRING SbApiPortName, - IN HANDLE SbApiPort, - IN ULONG ImageType, - OUT PHANDLE SmApiPort -); + _In_opt_ PUNICODE_STRING SbApiPortName, + _In_opt_ HANDLE SbApiPort, + _In_opt_ ULONG ImageType, + _Out_ PHANDLE SmApiPort); +/* NTDLL!RtlSendMsgToSm */ NTSTATUS NTAPI -SmExecPgm( - IN HANDLE SmApiPort, - IN PRTL_USER_PROCESS_INFORMATION ProcessInformation, - IN BOOLEAN DebugFlag -); +SmSendMsgToSm( + _In_ HANDLE SmApiPort, + _Inout_ PSM_API_MSG SmApiMsg); NTSTATUS NTAPI SmSessionComplete( - IN HANDLE SmApiPort, - IN ULONG SessionId, - IN NTSTATUS SessionStatus -); + _In_ HANDLE SmApiPort, + _In_ ULONG SessionId, + _In_ NTSTATUS SessionStatus); + +NTSTATUS +NTAPI +SmExecPgm( + _In_ HANDLE SmApiPort, + _In_ PRTL_USER_PROCESS_INFORMATION ProcessInformation, + _In_ BOOLEAN DebugFlag); NTSTATUS NTAPI SmStartCsr( - IN HANDLE SmApiPort, - OUT PULONG pMuSessionId, - IN PUNICODE_STRING CommandLine, - OUT PHANDLE pWindowsSubSysProcessId, - OUT PHANDLE pInitialCommandProcessId -); + _In_ HANDLE SmApiPort, + _Out_ PULONG pMuSessionId, + _In_opt_ PUNICODE_STRING CommandLine, + _Out_ PHANDLE pWindowsSubSysProcessId, + _Out_ PHANDLE pInitialCommandProcessId); NTSTATUS NTAPI SmStopCsr( - IN HANDLE SmApiPort, - IN ULONG SessionId -); + _In_ HANDLE SmApiPort, + _In_ ULONG MuSessionId); -#endif +#endif // _SM_MSG_ diff --git a/sdk/include/reactos/subsys/sm/smrosdbg.h b/sdk/include/reactos/subsys/sm/smrosdbg.h new file mode 100644 index 00000000000..8a20f9afa1d --- /dev/null +++ b/sdk/include/reactos/subsys/sm/smrosdbg.h @@ -0,0 +1,58 @@ +/* + * PROJECT: ReactOS SM Helper Library + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: ReactOS-specific SM Debug Utility Function: + * Querying subsystem information. + * COPYRIGHT: Copyright 2005 Emanuele Aliberti + * Copyright 2022 Hermès Bélusca-Maïto + */ + +#ifndef _SMROSDBG_H_ +#define _SMROSDBG_H_ + +#pragma once + +/* Note: this is not in NT */ +/* Ask SM to send back some data */ +#define SM_API_QUERY_INFORMATION SmpMaxApiNumber + +#define SM_QRYINFO_MAX_SS_COUNT 8 +#define SM_QRYINFO_MAX_ROOT_NODE 30 + +typedef enum { + SmBasicInformation = 0, + SmSubSystemInformation +} SM_INFORMATION_CLASS; + +typedef struct _SM_BASIC_INFORMATION +{ + USHORT SubSystemCount; + USHORT Unused; + struct + { + USHORT Id; + USHORT Flags; + ULONG ProcessId; + } SubSystem[SM_QRYINFO_MAX_SS_COUNT]; +} SM_BASIC_INFORMATION, *PSM_BASIC_INFORMATION; + +typedef struct _SM_SUBSYSTEM_INFORMATION +{ + USHORT SubSystemId; + USHORT Flags; + ULONG ProcessId; + WCHAR NameSpaceRootNode[SM_QRYINFO_MAX_ROOT_NODE]; +} SM_SUBSYSTEM_INFORMATION, *PSM_SUBSYSTEM_INFORMATION; + +typedef struct _SM_QUERYINFO_MSG +{ + SM_INFORMATION_CLASS SmInformationClass; + ULONG DataLength; + union + { + SM_BASIC_INFORMATION BasicInformation; + SM_SUBSYSTEM_INFORMATION SubSystemInformation; + }; +} SM_QUERYINFO_MSG, *PSM_QUERYINFO_MSG; + +#endif // _SMROSDBG_H_ diff --git a/sdk/lib/smlib/CMakeLists.txt b/sdk/lib/smlib/CMakeLists.txt index 41429ad3e02..00d223c7755 100644 --- a/sdk/lib/smlib/CMakeLists.txt +++ b/sdk/lib/smlib/CMakeLists.txt @@ -2,10 +2,6 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys) list(APPEND SOURCE - compses.c - connect.c - execpgm.c - lookupss.c smclient.c precomp.h) diff --git a/sdk/lib/smlib/compses.c b/sdk/lib/smlib/compses.c deleted file mode 100644 index 04f18019991..00000000000 --- a/sdk/lib/smlib/compses.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/smlib/compses.c - * PURPOSE: Call SM API SM_API_COMPLETE_SESSION - */ - -#include "precomp.h" - -#define NDEBUG -#include - -/********************************************************************** - * NAME EXPORTED - * SmCompleteSession/3 - * - * DESCRIPTION - * This function is called by an environment subsystem server to - * tell the SM it finished initialization phase and is ready to - * manage processes it registered for (SmConnectApiPort). - * - * ARGUMENTS - * hSmApiPort: port handle returned by SmConnectApiPort; - * hSbApiPort: call back API port of the subsystem (handle); - * hApiPort : API port of the subsystem (handle). - * - * RETURN VALUE - * Success status as handed by the SM reply; otherwise a failure - * status code. - */ -NTSTATUS WINAPI -SmCompleteSession (IN HANDLE hSmApiPort, - IN HANDLE hSbApiPort, - IN HANDLE hApiPort) -{ - NTSTATUS Status; - SM_PORT_MESSAGE SmReqMsg; - - DPRINT("SMLIB: %s called\n", __FUNCTION__); - - /* Marshal Ses in the LPC message */ - SmReqMsg.Request.CompSes.hApiPort = hApiPort; - SmReqMsg.Request.CompSes.hSbApiPort = hSbApiPort; - - /* SM API to invoke */ - SmReqMsg.SmHeader.ApiIndex = SM_API_COMPLETE_SESSION; - - /* Port message */ - SmReqMsg.Header.u2.s2.Type = LPC_NEW_MESSAGE; - SmReqMsg.Header.u1.s1.DataLength = SM_PORT_DATA_SIZE(SmReqMsg.Request); - SmReqMsg.Header.u1.s1.TotalLength = SM_PORT_MESSAGE_SIZE; - Status = NtRequestWaitReplyPort (hSmApiPort, (PPORT_MESSAGE) & SmReqMsg, (PPORT_MESSAGE) & SmReqMsg); - if (NT_SUCCESS(Status)) - { - return SmReqMsg.SmHeader.Status; - } - DPRINT("SMLIB: %s failed (Status=0x%08lx)\n", __FUNCTION__, Status); - return Status; -} - -/* EOF */ diff --git a/sdk/lib/smlib/connect.c b/sdk/lib/smlib/connect.c deleted file mode 100644 index aa95d9ab4d8..00000000000 --- a/sdk/lib/smlib/connect.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: reactos/lib/smlib/connect.c - * PURPOSE: Connect to the API LPC port exposed by the SM - */ - -#include "precomp.h" - -#define NDEBUG -#include - -/********************************************************************** - * NAME EXPORTED - * SmConnectApiPort/4 - * - * DESCRIPTION - * Connect to SM API port and register a session "begin" port (Sb) - * or to issue API requests to SmApiPort. - * - * ARGUMENTS - * pSbApiPortName: name of the Sb port the calling subsystem - * server already created in the system name space; - * hSbApiPort: LPC port handle (checked, but not used: the - * subsystem is required to have already created - * the callback port before it connects to the SM); - * wSubsystem: a valid IMAGE_SUBSYSTEM_xxx value; - * phSmApiPort: a pointer to a HANDLE, which will be - * filled with a valid client-side LPC comm port. - * - * There should be only two ways to call this API: - * a) subsystems willing to register with SM will use it - * with full parameters (the function checks them); - * b) regular SM clients, will set to 0 the 1st, the 2nd, - * and the 3rd parameter. - * - * RETURN VALUE - * If all three optional values are omitted, an LPC status. - * STATUS_INVALID_PARAMETER_MIX if PortName is defined and - * both hSbApiPort and wSubsystem are 0. - */ -NTSTATUS WINAPI -SmConnectApiPort (IN PUNICODE_STRING pSbApiPortName OPTIONAL, - IN HANDLE hSbApiPort OPTIONAL, - IN WORD wSubSystemId OPTIONAL, - IN OUT PHANDLE phSmApiPort) -{ - UNICODE_STRING SmApiPortName; - SECURITY_QUALITY_OF_SERVICE SecurityQos; - NTSTATUS Status = STATUS_SUCCESS; - SM_CONNECT_DATA ConnectData = {0,0,{0}}; - ULONG ConnectDataLength = 0; - - DPRINT("SMLIB: %s called\n", __FUNCTION__); - - if (pSbApiPortName) - { - if (pSbApiPortName->Length > (sizeof pSbApiPortName->Buffer[0] * SM_SB_NAME_MAX_LENGTH)) - { - return STATUS_INVALID_PARAMETER_1; - } - if (NULL == hSbApiPort || IMAGE_SUBSYSTEM_UNKNOWN == wSubSystemId) - { - return STATUS_INVALID_PARAMETER_MIX; - } - RtlZeroMemory (& ConnectData, sizeof ConnectData); - ConnectData.Unused = 0; - ConnectData.SubSystemId = wSubSystemId; - if (pSbApiPortName->Length > 0) - { - RtlCopyMemory (& ConnectData.SbName, - pSbApiPortName->Buffer, - pSbApiPortName->Length); - } - } - ConnectDataLength = sizeof ConnectData; - - SecurityQos.Length = sizeof (SecurityQos); - SecurityQos.ImpersonationLevel = SecurityIdentification; - SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; - SecurityQos.EffectiveOnly = TRUE; - - RtlInitUnicodeString (& SmApiPortName, SM_API_PORT_NAME); - - Status = NtConnectPort ( - phSmApiPort, - & SmApiPortName, - & SecurityQos, - NULL, - NULL, - NULL, - & ConnectData, - & ConnectDataLength - ); - if (NT_SUCCESS(Status)) - { - return STATUS_SUCCESS; - } - DPRINT("SMLIB: %s failed (Status=0x%08lx)\n", __FUNCTION__, Status); - return Status; -} - -/* EOF */ diff --git a/sdk/lib/smlib/execpgm.c b/sdk/lib/smlib/execpgm.c deleted file mode 100644 index e75b743de4c..00000000000 --- a/sdk/lib/smlib/execpgm.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/smlib/execpgm.c - * PURPOSE: Call SM API SM_API_EXECPGM - */ - -#include "precomp.h" - -#define NDEBUG -#include - -/********************************************************************** - * NAME EXPORTED - * SmExecuteProgram/2 - * - * DESCRIPTION - * This function is used to make the SM start an environment - * subsystem server process. - * - * ARGUMENTS - * hSmApiPort: port handle returned by SmConnectApiPort; - * Pgm : name of the subsystem (to be used by the SM to - * lookup the image name from the registry). - * Valid names are: DEBUG, WINDOWS, POSIX, OS2, - * and VMS. - * - * RETURN VALUE - * Success status as handed by the SM reply; otherwise a failure - * status code. - */ -NTSTATUS WINAPI -SmExecuteProgram (IN HANDLE hSmApiPort, - IN PUNICODE_STRING Pgm) -{ - NTSTATUS Status; - SM_PORT_MESSAGE SmReqMsg; - - - DPRINT("SMLIB: %s(%p,'%S') called\n", - __FUNCTION__, hSmApiPort, Pgm->Buffer); - - /* Check Pgm's length */ - if (Pgm->Length > (sizeof (Pgm->Buffer[0]) * SM_EXEXPGM_MAX_LENGTH)) - { - return STATUS_INVALID_PARAMETER; - } - /* Marshal Pgm in the LPC message */ - RtlZeroMemory (& SmReqMsg, sizeof SmReqMsg); - SmReqMsg.Request.ExecPgm.NameLength = Pgm->Length; - RtlCopyMemory (SmReqMsg.Request.ExecPgm.Name, - Pgm->Buffer, - Pgm->Length); - - /* SM API to invoke */ - SmReqMsg.SmHeader.ApiIndex = SM_API_EXECUTE_PROGRAMME; - - /* LPC message */ - SmReqMsg.Header.u2.s2.Type = LPC_NEW_MESSAGE; - SmReqMsg.Header.u1.s1.DataLength = SM_PORT_DATA_SIZE(SmReqMsg.Request); - SmReqMsg.Header.u1.s1.TotalLength = SM_PORT_MESSAGE_SIZE; - - DPRINT("SMLIB: %s:\n" - " u2.s2.Type = %d\n" - " u1.s1.DataLength = %d\n" - " u1.s1.TotalLength = %d\n" - " sizeof(PORT_MESSAGE)==%u\n", - __FUNCTION__, - SmReqMsg.Header.u2.s2.Type, - SmReqMsg.Header.u1.s1.DataLength, - SmReqMsg.Header.u1.s1.TotalLength, - sizeof(PORT_MESSAGE)); - - /* Call SM and wait for a reply */ - Status = NtRequestWaitReplyPort (hSmApiPort, (PPORT_MESSAGE) & SmReqMsg, (PPORT_MESSAGE) & SmReqMsg); - if (NT_SUCCESS(Status)) - { - return SmReqMsg.SmHeader.Status; - } - DPRINT("SMLIB: %s failed (Status=0x%08lx)\n", __FUNCTION__, Status); - return Status; -} - -/* EOF */ diff --git a/sdk/lib/smlib/lookupss.c b/sdk/lib/smlib/lookupss.c deleted file mode 100644 index e47a47ac0ee..00000000000 --- a/sdk/lib/smlib/lookupss.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/smlib/lookupss.c - */ - -#include "precomp.h" - -#define NDEBUG -#include - -/********************************************************************** - * NAME EXPORTED - * SmLookupSubsystem/6 - * - * DESCRIPTION - * Read from the registry key - * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems - * the value which name is Name. - * - * ARGUMENTS - * Name: name of the program to run, that is a value's name in - * the SM registry key SubSystems; - * Data: what the registry gave back for Name; - * DataLength: how much Data the registry returns; - * DataType: what is Data? - * Environment: set it if you want this function to use it - * to possibly expand Data before giving it back; if set - * to NULL, no expansion will be performed. - */ -NTSTATUS WINAPI -SmLookupSubsystem (IN PWSTR Name, - IN OUT PWSTR Data, - IN OUT PULONG DataLength, - IN OUT PULONG DataType, - IN PVOID Environment OPTIONAL) -{ - NTSTATUS Status = STATUS_SUCCESS; - UNICODE_STRING usKeyName = { 0, 0, NULL }; - OBJECT_ATTRIBUTES Oa = {0}; - HANDLE hKey = (HANDLE) 0; - - DPRINT("SM: %s(Name='%S') called\n", __FUNCTION__, Name); - /* - * Prepare the key name to scan and - * related object attributes. - */ - RtlInitUnicodeString (& usKeyName, - L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems"); - - InitializeObjectAttributes (& Oa, - & usKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - /* - * Open the key. This MUST NOT fail, if the - * request is for a legitimate subsystem. - */ - Status = NtOpenKey (& hKey, - MAXIMUM_ALLOWED, - & Oa); - if(NT_SUCCESS(Status)) - { - UNICODE_STRING usValueName = { 0, 0, NULL }; - PWCHAR KeyValueInformation = NULL; - ULONG KeyValueInformationLength = 1024; - ULONG ResultLength = 0L; - PKEY_VALUE_PARTIAL_INFORMATION kvpi = NULL; - - KeyValueInformation = RtlAllocateHeap (RtlGetProcessHeap(), - 0, - KeyValueInformationLength); - if (NULL == KeyValueInformation) - { - return STATUS_NO_MEMORY; - } - kvpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; - RtlInitUnicodeString (& usValueName, Name); - Status = NtQueryValueKey (hKey, - & usValueName, - KeyValuePartialInformation, - KeyValueInformation, - KeyValueInformationLength, - & ResultLength); - if(NT_SUCCESS(Status)) - { - DPRINT("nkvpi.TitleIndex = %lu\n", kvpi->TitleIndex); - DPRINT("kvpi.Type = %lu\n", kvpi->Type); - DPRINT("kvpi.DataLength = %lu\n", kvpi->DataLength); - - if((NULL != Data) && (NULL != DataLength) && (NULL != DataType)) - { - *DataType = kvpi->Type; - if((NULL != Environment) && (REG_EXPAND_SZ == *DataType)) - { - UNICODE_STRING Source; - PWCHAR DestinationBuffer = NULL; - UNICODE_STRING Destination; - ULONG Length = 0; - - DPRINT("SM: %s: value will be expanded\n", __FUNCTION__); - - DestinationBuffer = RtlAllocateHeap (RtlGetProcessHeap(), - 0, - (2 * KeyValueInformationLength)); - if (NULL == DestinationBuffer) - { - Status = STATUS_NO_MEMORY; - } - else - { - Source.Length = (USHORT)kvpi->DataLength; - Source.MaximumLength = (USHORT)kvpi->DataLength; - Source.Buffer = (PWCHAR) & kvpi->Data; - - Destination.Length = 0; - Destination.MaximumLength = (USHORT)(2 * KeyValueInformationLength); - Destination.Buffer = DestinationBuffer; - - Status = RtlExpandEnvironmentStrings_U (Environment, - & Source, - & Destination, - & Length); - if(NT_SUCCESS(Status)) - { - *DataLength = min(*DataLength, Destination.Length); - RtlCopyMemory (Data, Destination.Buffer, *DataLength); - } - RtlFreeHeap (RtlGetProcessHeap(), 0, DestinationBuffer); - } - }else{ - DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__); - *DataLength = min(*DataLength, kvpi->DataLength); - RtlCopyMemory (Data, & kvpi->Data, *DataLength); - } - *DataType = kvpi->Type; - }else{ - DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__); - Status = STATUS_INVALID_PARAMETER; - } - }else{ - DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status); - } - RtlFreeHeap (RtlGetProcessHeap(), 0, KeyValueInformation); - NtClose (hKey); - }else{ - DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status); - } - return Status; -} - -/* EOF */ diff --git a/sdk/lib/smlib/precomp.h b/sdk/lib/smlib/precomp.h index 97f3b2bf7a2..19e69e374bd 100644 --- a/sdk/lib/smlib/precomp.h +++ b/sdk/lib/smlib/precomp.h @@ -1,24 +1,20 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS System Libraries - * FILE: lib/smlib/precomp.h - * PURPOSE: SMLIB Library Header - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * PROJECT: ReactOS NT-Compatible Session Manager + * LICENSE: BSD 2-Clause License (https://spdx.org/licenses/BSD-2-Clause) + * PURPOSE: SMSS Client Library (SMLIB) Header + * COPYRIGHT: Copyright 2012-2013 Alex Ionescu */ #ifndef _SMLIB_PCH_ #define _SMLIB_PCH_ -#define WIN32_NO_STATUS -#include -#include #define NTOS_MODE_USER -#include #include #include #include #include -#include +#include +#include #endif /* _SMLIB_PCH_ */ diff --git a/sdk/lib/smlib/readme.txt b/sdk/lib/smlib/readme.txt new file mode 100644 index 00000000000..14fa624b32a --- /dev/null +++ b/sdk/lib/smlib/readme.txt @@ -0,0 +1,67 @@ + +SMLIB: Client Library to talk to the ReactOS NT-Compatible Session Manager (SM). + +It should be linked in the following components: + +a) the SM itself, because it registers for managing native processes + IMAGE_SUBSYSTEM_NATIVE; + +b) environment subsystem servers, because each one should register in + the SM its own subsystem (willing to manage those processes); + +c) application launchers (e.g. terminal emulators) for optional subsystems, + to ask the SM to start the optional subsystem server they need to connect; + +d) system and development utilities to debug/query the SM. + +2004-02-15 ea +2022-11-03 hbelusca + + +How a subsystem uses these APIs +=============================== + +Thread #0 Thread #1 + +- Creates its own directory (\EXAMPLE) +- Initializes the main parts of the subsystem. +- Creates its main API port (\EXAMPLE\ApiPort), + and servicing thread for it. Programs running + under this subsystem will communicate with + this API port. + +- Creates its SM callback API port (\EXAMPLE\SbApiPort) + and servicing thread T1. + + - Waits connection requests on the + callback port (\EXAMPLE\SbApiPort) + +- Registers to the SM by calling + SmConnectToSm( + "\EXAMPLE\SbApiPort", + hSbApiPort, + SUBSYSTEM_ID, + &hSmApiPort); + - As the SM calls back, validates + and accepts connection. + +- The subsystem is now ready to + manage processes, etc. + +----- + +Thread #N Thread #1 + + - The SM calls back the subsystem + SbCreateSession() API, so that it + can initialize a new environment + session (with associated SessionId). + +- When no more processes to manage exist, + terminate the subsystem session by calling + SmSessionComplete( + hSmApiPort, + SessionId, + ExitStatus); + - The SM calls back the subsystem + SbTerminateSession() API. diff --git a/sdk/lib/smlib/smclient.c b/sdk/lib/smlib/smclient.c index d56c8e57d0a..58768f197bb 100644 --- a/sdk/lib/smlib/smclient.c +++ b/sdk/lib/smlib/smclient.c @@ -1,79 +1,69 @@ /* - * PROJECT: ReactOS Windows-Compatible Session Manager - * LICENSE: BSD 2-Clause License - * FILE: lib/smlib/smclient.c - * PURPOSE: SMSS Client Library Stubs for calling SM APIs from a client - * PROGRAMMERS: Alex Ionescu + * PROJECT: ReactOS NT-Compatible Session Manager + * LICENSE: BSD 2-Clause License (https://spdx.org/licenses/BSD-2-Clause) + * PURPOSE: SMSS Client Library (SMLIB) Client Stubs + * COPYRIGHT: Copyright 2012-2013 Alex Ionescu + * Copyright 2021 Hervé Poussineau + * Copyright 2022 Hermès Bélusca-Maïto */ /* INCLUDES *******************************************************************/ #include "precomp.h" -#include // To go in precomp.h after #define NDEBUG #include /* FUNCTIONS ******************************************************************/ +/** + * @brief + * Connects to the SM API port for registering a session callback port (Sb) + * associated to a subsystem, or for issuing API requests to the SM API port. + * + * There are only two ways to call this API: + * a) subsystems willing to register with SM will use it + * with full parameters (the function checks them); + * b) regular SM clients, will set to 0 the 1st, the 2nd, + * and the 3rd parameters. + * + * @param[in] SbApiPortName + * Name of the Sb port the calling subsystem server already + * created in the system namespace. + * + * @param[in] SbApiPort + * LPC port handle (checked, but not used: the subsystem is + * required to have already created the callback port before + * it connects to the SM). + * + * @param[in] ImageType + * A valid IMAGE_SUBSYSTEM_xxx value. PE images having this + * subsystem value will be handled by the current subsystem. + * + * @param[out] SmApiPort + * Pointer to a HANDLE, which will be filled with a valid + * client-side LPC communication port. + * + * @return + * If all three optional values are omitted, an LPC status. + * STATUS_INVALID_PARAMETER_MIX if PortName is defined and + * both SbApiPort and ImageType are 0. + * + * @remark + * Exported on Vista+ by NTDLL and called RtlConnectToSm(). + **/ NTSTATUS NTAPI -SmExecPgm(IN HANDLE SmApiPort, - IN PRTL_USER_PROCESS_INFORMATION ProcessInformation, - IN BOOLEAN DebugFlag) +SmConnectToSm( + _In_opt_ PUNICODE_STRING SbApiPortName, + _In_opt_ HANDLE SbApiPort, + _In_opt_ ULONG ImageType, + _Out_ PHANDLE SmApiPort) { NTSTATUS Status; - SM_API_MSG SmApiMsg; - -#if 0 //def _WIN64 // You can take care of this Timo - /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */ - if (SmpIsWow64Process()) - { - return SmpWow64ExecPgm(SmApiPort, ProcessInformation, DebugFlag); - } -#endif - - /* Initialize the generic LPC header */ - SmApiMsg.h.u2.ZeroInit = 0; - SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8; - SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); - - /* Initialize this specific API's parameters */ - SmApiMsg.ApiNumber = SmpExecPgmApi; - RtlCopyMemory(&SmApiMsg.u.ExecPgm.ProcessInformation, - ProcessInformation, - sizeof(SmApiMsg.u.ExecPgm.ProcessInformation)); - SmApiMsg.u.ExecPgm.DebugFlag = DebugFlag; - - /* Send the message to SMSS */ - Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SmExecPgm: NtRequestWaitReply Failed %lx\n", Status); - } - else - { - /* Upon success, we use the API's return value */ - Status = SmApiMsg.ReturnValue; - } - - /* Close the handles that the parent passed in and return status */ - NtClose(ProcessInformation->ProcessHandle); - NtClose(ProcessInformation->ThreadHandle); - return Status; -} - -NTSTATUS -NTAPI -SmConnectToSm(IN PUNICODE_STRING SbApiPortName, - IN HANDLE SbApiPort, - IN ULONG ImageType, - OUT PHANDLE SmApiPort) -{ - NTSTATUS Status; - SB_CONNECTION_INFO ConnectInfo; - UNICODE_STRING PortName; SECURITY_QUALITY_OF_SERVICE SecurityQos; + UNICODE_STRING PortName; + SB_CONNECTION_INFO ConnectInfo = {0}; ULONG ConnectInfoLength = sizeof(ConnectInfo); /* Setup the QoS structure */ @@ -82,20 +72,24 @@ SmConnectToSm(IN PUNICODE_STRING SbApiPortName, SecurityQos.EffectiveOnly = TRUE; /* Set the SM API port name */ - RtlInitUnicodeString(&PortName, L"\\SmApiPort"); + RtlInitUnicodeString(&PortName, L"\\SmApiPort"); // SM_API_PORT_NAME /* Check if this is a client connecting to SMSS, or SMSS to itself */ if (SbApiPortName) { /* A client SB port as well as an image type must be present */ - if (!(SbApiPort) || !(ImageType)) return STATUS_INVALID_PARAMETER_MIX; + if (!SbApiPort || (ImageType == IMAGE_SUBSYSTEM_UNKNOWN)) + return STATUS_INVALID_PARAMETER_MIX; + + /* Validate SbApiPortName's length */ + if (SbApiPortName->Length >= sizeof(ConnectInfo.SbApiPortName)) + return STATUS_INVALID_PARAMETER; /* Copy the client port name, and NULL-terminate it */ RtlCopyMemory(ConnectInfo.SbApiPortName, SbApiPortName->Buffer, SbApiPortName->Length); - ConnectInfo.SbApiPortName[SbApiPortName->Length / - sizeof(WCHAR)] = UNICODE_NULL; + ConnectInfo.SbApiPortName[SbApiPortName->Length / sizeof(WCHAR)] = UNICODE_NULL; /* Save the subsystem type */ ConnectInfo.SubsystemType = ImageType; @@ -120,131 +114,302 @@ SmConnectToSm(IN PUNICODE_STRING SbApiPortName, { DPRINT1("SmConnectToSm: Connect to Sm failed %lx\n", Status); } +#if (NTDDI_VERSION < NTDDI_VISTA) else { /* Treat a warning or informational status as success */ Status = STATUS_SUCCESS; } +#endif /* Return if the connection was successful or not */ return Status; } +/** + * @brief + * Sends a message to the SM via the SM API port. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in,out] SmApiMsg + * Message to send to the SM. The API-specific data must be initialized, + * and the SmApiMsg->ApiNumber must be specified accordingly. + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + * + * @remark + * Exported on Vista+ by NTDLL and called RtlSendMsgToSm(). + **/ NTSTATUS NTAPI -SmSessionComplete(IN HANDLE SmApiPort, - IN ULONG SessionId, - IN NTSTATUS SessionStatus) +SmSendMsgToSm( + _In_ HANDLE SmApiPort, + _Inout_ PSM_API_MSG SmApiMsg) { + static ULONG RtlpSmMessageInfo[SmpMaxApiNumber] = + { + 0 /*sizeof(SM_CREATE_FOREIGN_SESSION_MSG)*/, + sizeof(SM_SESSION_COMPLETE_MSG), + 0 /*sizeof(SM_TERMINATE_FOREIGN_SESSION_MSG)*/, + sizeof(SM_EXEC_PGM_MSG), + sizeof(SM_LOAD_DEFERED_SUBSYSTEM_MSG), + sizeof(SM_START_CSR_MSG), + sizeof(SM_STOP_CSR_MSG), + }; + NTSTATUS Status; - SM_API_MSG ApiMessage; - PSM_SESSION_COMPLETE_MSG SessionComplete = &ApiMessage.u.SessionComplete; + ULONG DataLength; + + if (SmApiMsg->ApiNumber >= SmpMaxApiNumber) + return STATUS_NOT_IMPLEMENTED; + + /* Obtain the necessary data length for this API */ + DataLength = RtlpSmMessageInfo[SmApiMsg->ApiNumber]; + + /* Fill out the Port Message Header */ + // RtlZeroMemory(&SmApiMsg->h, sizeof(SmApiMsg->h)); + SmApiMsg->h.u2.ZeroInit = 0; + /* DataLength = user_data_size + anything between + * header and data, including intermediate padding */ + SmApiMsg->h.u1.s1.DataLength = (CSHORT)DataLength + + FIELD_OFFSET(SM_API_MSG, u) - sizeof(SmApiMsg->h); + /* TotalLength = sizeof(*SmApiMsg) on <= NT5.2, otherwise: + * DataLength + header_size == user_data_size + FIELD_OFFSET(SM_API_MSG, u) + * without structure trailing padding */ + SmApiMsg->h.u1.s1.TotalLength = SmApiMsg->h.u1.s1.DataLength + sizeof(SmApiMsg->h); + + /* Send the LPC message and wait for a reply */ + Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg->h, &SmApiMsg->h); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SmSendMsgToSm: NtRequestWaitReplyPort failed, Status: 0x%08lx\n", Status); + } + else + { + /* Return the real status */ + Status = SmApiMsg->ReturnValue; + } + + return Status; +} + +/** + * @brief + * This function is called by an environment subsystem server + * to tell the SM it has terminated the session it managed. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in] SessionId + * The session ID of the session being terminated. + * + * @param[in] SessionStatus + * An NT status code for the termination. + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + **/ +NTSTATUS +NTAPI +SmSessionComplete( + _In_ HANDLE SmApiPort, + _In_ ULONG SessionId, + _In_ NTSTATUS SessionStatus) +{ + SM_API_MSG SmApiMsg = {0}; + PSM_SESSION_COMPLETE_MSG SessionComplete = &SmApiMsg.u.SessionComplete; + +#if 0 //def _WIN64 + /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */ + if (SmpIsWow64Process()) + { + return SmpWow64SessionComplete(SmApiPort, SessionId, SessionStatus); + } +#endif /* Set the message data */ SessionComplete->SessionId = SessionId; SessionComplete->SessionStatus = SessionStatus; - /* Set the API Message Port Message header */ - ApiMessage.ApiNumber = SmpSessionCompleteApi; - ApiMessage.h.u1.s1.DataLength = sizeof(SM_SESSION_COMPLETE_MSG) + 8; - ApiMessage.h.u1.s1.TotalLength = sizeof(SM_API_MSG); - ApiMessage.h.u2.ZeroInit = 0; + /* Send the message and wait for a reply */ + SmApiMsg.ApiNumber = SmpSessionCompleteApi; + return SmSendMsgToSm(SmApiPort, &SmApiMsg); +} - /* Sent the message and wait for a reply */ - Status = NtRequestWaitReplyPort(SmApiPort, - &ApiMessage.h, - &ApiMessage.h); - if (NT_SUCCESS(Status)) - { - /* Return the real status */ - Status = ApiMessage.ReturnValue; - } - else - { - DPRINT1("SmCompleteSession: NtRequestWaitReply failed\n"); - } +/** + * @brief + * Requests the SM to start a process under a new environment session. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in] ProcessInformation + * A process description as returned by RtlCreateUserProcess(). + * + * @param[in] DebugFlag + * If set, indicates that the caller wants to debug this process + * and act as its debug user interface. + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + **/ +NTSTATUS +NTAPI +SmExecPgm( + _In_ HANDLE SmApiPort, + _In_ PRTL_USER_PROCESS_INFORMATION ProcessInformation, + _In_ BOOLEAN DebugFlag) +{ + NTSTATUS Status; + SM_API_MSG SmApiMsg = {0}; + PSM_EXEC_PGM_MSG ExecPgm = &SmApiMsg.u.ExecPgm; - /* Return status */ +#if 0 //def _WIN64 + /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */ + if (SmpIsWow64Process()) + { + return SmpWow64ExecPgm(SmApiPort, ProcessInformation, DebugFlag); + } +#endif + + /* Set the message data */ + RtlCopyMemory(&ExecPgm->ProcessInformation, + ProcessInformation, + sizeof(ExecPgm->ProcessInformation)); + ExecPgm->DebugFlag = DebugFlag; + + /* Send the message and wait for a reply */ + SmApiMsg.ApiNumber = SmpExecPgmApi; + Status = SmSendMsgToSm(SmApiPort, &SmApiMsg); + + /* Close the handles that the parent passed in and return status */ + NtClose(ProcessInformation->ProcessHandle); + NtClose(ProcessInformation->ThreadHandle); return Status; } +/** + * @brief + * Requests the SM to create a new Terminal Services session + * and start an initial command. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[out] pMuSessionId + * Pointer to a variable that receives the session ID of the new + * Terminal Services session that has been created. + * + * @param[in] CommandLine + * Full path to the image to be used as the initial command. + * + * @param[out] pWindowsSubSysProcessId + * Pointer to a variable that receives the process ID of the environment + * subsystem that has been started in the new session. + * + * @param[out] pInitialCommandProcessId + * Pointer to a variable that receives the process ID of the initial command. + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + **/ NTSTATUS NTAPI -SmStartCsr(IN HANDLE SmApiPort, - OUT PULONG pMuSessionId, - IN PUNICODE_STRING CommandLine, - OUT PHANDLE pWindowsSubSysProcessId, - OUT PHANDLE pInitialCommandProcessId) +SmStartCsr( + _In_ HANDLE SmApiPort, + _Out_ PULONG pMuSessionId, + _In_opt_ PUNICODE_STRING CommandLine, + _Out_ PHANDLE pWindowsSubSysProcessId, + _Out_ PHANDLE pInitialCommandProcessId) { NTSTATUS Status; - SM_API_MSG SmApiMsg; + SM_API_MSG SmApiMsg = {0}; + PSM_START_CSR_MSG StartCsr = &SmApiMsg.u.StartCsr; - /* Initialize the generic LPC header */ - RtlZeroMemory(&SmApiMsg, sizeof(SmApiMsg)); - SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8; - SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); +#if 0 //def _WIN64 + /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */ + if (SmpIsWow64Process()) + { + return SmpWow64StartCsr(SmApiPort, + pMuSessionId, + CommandLine, + pWindowsSubSysProcessId, + pInitialCommandProcessId); + } +#endif - /* Initialize this specific API's parameters */ - SmApiMsg.ApiNumber = SmpStartCsrApi; + /* Set the message data */ if (CommandLine) { - if (CommandLine->Length > ARRAYSIZE(SmApiMsg.u.StartCsr.Buffer)) - { - DPRINT1("SmStartCsr: Command line too long\n"); + /* Validate CommandLine's length */ + if (CommandLine->Length > sizeof(StartCsr->Buffer)) return STATUS_INVALID_PARAMETER; - } - RtlCopyMemory(SmApiMsg.u.StartCsr.Buffer, CommandLine->Buffer, CommandLine->Length); - SmApiMsg.u.StartCsr.Length = CommandLine->Length; - } - /* Send the message to SMSS */ - Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SmStartCsr: NtRequestWaitReply Failed %lx\n", Status); + /* Buffer stores a counted non-NULL-terminated UNICODE string */ + StartCsr->Length = CommandLine->Length; + RtlCopyMemory(StartCsr->Buffer, + CommandLine->Buffer, + CommandLine->Length); } else { - /* Upon success, we use the API's return value */ - Status = SmApiMsg.ReturnValue; + StartCsr->Length = 0; } + /* Send the message and wait for a reply */ + SmApiMsg.ApiNumber = SmpStartCsrApi; + Status = SmSendMsgToSm(SmApiPort, &SmApiMsg); + /* Give back informations to caller */ - *pMuSessionId = SmApiMsg.u.StartCsr.MuSessionId; - *pWindowsSubSysProcessId = SmApiMsg.u.StartCsr.WindowsSubSysProcessId; - *pInitialCommandProcessId = SmApiMsg.u.StartCsr.SmpInitialCommandProcessId; + *pMuSessionId = StartCsr->MuSessionId; + *pWindowsSubSysProcessId = StartCsr->WindowsSubSysProcessId; + *pInitialCommandProcessId = StartCsr->SmpInitialCommandProcessId; return Status; } +/** + * @brief + * Requests the SM to terminate a Terminal Services session. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in] MuSessionId + * The Terminal Services session ID, returned by SmStartCsr(). + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + **/ NTSTATUS NTAPI -SmStopCsr(IN HANDLE SmApiPort, - IN ULONG SessionId) +SmStopCsr( + _In_ HANDLE SmApiPort, + _In_ ULONG MuSessionId) { - NTSTATUS Status; - SM_API_MSG SmApiMsg; + SM_API_MSG SmApiMsg = {0}; - /* Initialize the generic LPC header */ - RtlZeroMemory(&SmApiMsg, sizeof(SmApiMsg)); - SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8; - SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); +#if 0 //def _WIN64 + /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */ + if (SmpIsWow64Process()) + { + return SmpWow64StopCsr(SmApiPort, MuSessionId); + } +#endif - /* Initialize this specific API's parameters */ + /* Set the message data */ + SmApiMsg.u.StopCsr.MuSessionId = MuSessionId; + + /* Send the message and wait for a reply */ SmApiMsg.ApiNumber = SmpStopCsrApi; - SmApiMsg.u.StopCsr.MuSessionId = SessionId; - - /* Send the message to SMSS */ - Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SmStopCsr: NtRequestWaitReply Failed %lx\n", Status); - } - else - { - /* Upon success, we use the API's return value */ - Status = SmApiMsg.ReturnValue; - } - - return Status; + return SmSendMsgToSm(SmApiPort, &SmApiMsg); } diff --git a/sdk/lib/smlib/smdll.spec b/sdk/lib/smlib/smdll.spec new file mode 100644 index 00000000000..7372353e3c7 --- /dev/null +++ b/sdk/lib/smlib/smdll.spec @@ -0,0 +1,16 @@ +@ stdcall SmConnectToSm(ptr ptr long ptr) +@ stub SmCreateForeignSession +@ stdcall SmSessionComplete(ptr long long) +@ stub SmTerminateForeignSession +@ stdcall SmExecPgm(ptr ptr long) +@ stdcall SmLoadDeferedSubsystem(ptr ptr) +@ stdcall SmStartCsr(ptr ptr ptr ptr ptr) +@ stdcall SmStopCsr(ptr long) + +@ stdcall -version=0x600+ RtlConnectToSm(ptr ptr long ptr) SmConnectToSm +@ stdcall -version=0x600+ RtlSendMsgToSm(ptr ptr) SmSendMsgToSm + +## Utilities +@ stdcall SmExecuteProgram(ptr ptr) +@ stdcall SmLookupSubsystem(ptr ptr ptr ptr ptr) +@ stdcall SmQueryInformation(ptr long ptr long ptr) diff --git a/sdk/lib/smlib/smutils.c b/sdk/lib/smlib/smutils.c new file mode 100644 index 00000000000..5dc2503133b --- /dev/null +++ b/sdk/lib/smlib/smutils.c @@ -0,0 +1,452 @@ +/* + * PROJECT: ReactOS SM Helper Library + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Utility functions built around the client SM API + * COPYRIGHT: Copyright 2005 Emanuele Aliberti + * Copyright 2022 Hermès Bélusca-Maïto + */ + +#include "precomp.h" + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include + +#define NTOS_MODE_USER +#include + +#include + +#define NDEBUG +#include + +#if DBG +BOOLEAN SmpDebug = TRUE; +#else +BOOLEAN SmpDebug = FALSE; +#endif + +/** + * @brief + * This function is used to make the SM start an external process + * under an already-loaded environment subsystem server. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in] Program + * Fully qualified NT name of the executable to load. + * + * @return + * Success status as handed by the SM reply; otherwise a failure + * status code. + * + * @remark + * Adapted from SMSS' SmpExecuteInitialCommand() and SmpExecuteImage(). + **/ +NTSTATUS +NTAPI +SmExecuteProgram( + _In_ HANDLE SmApiPort, + _In_ PUNICODE_STRING Program /*, + _Out_opt_ PRTL_USER_PROCESS_INFORMATION ProcessInformation*/) +{ + // ULONG MuSessionId; + + NTSTATUS Status; + RTL_USER_PROCESS_INFORMATION ProcessInfo; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + + PUNICODE_STRING FileName = Program; // FIXME! + PUNICODE_STRING Directory = NULL; // FIXME! + PUNICODE_STRING CommandLine = NULL; // FIXME! + + PVOID SmpDefaultEnvironment = NtCurrentPeb()->ProcessParameters->Environment; + // UNICODE_STRING SmpDefaultLibPath; + + DPRINT("SMLIB: %s(%p, '%wZ') called\n", + __FUNCTION__, SmApiPort, Program); + + /* Parameters validation */ + if (!SmApiPort) + return STATUS_INVALID_PARAMETER_1; + if (!Program) + return STATUS_INVALID_PARAMETER_2; + + /* Create parameters for the target process, using the current environment */ + Status = RtlCreateProcessParameters(&ProcessParameters, + FileName, + /* SmpDefaultLibPath.Length ? + &SmpDefaultLibPath : */ NULL, + Directory, + CommandLine, + SmpDefaultEnvironment, + NULL, + NULL, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SMLIB: RtlCreateProcessParameters failed for %wZ - Status == %lx\n", + FileName, Status); + return Status; + } + + /* Set the size field as required */ + ProcessInfo.Size = sizeof(ProcessInfo); + + /* Otherwise inherit the flag that was passed to SMSS itself */ + ProcessParameters->DebugFlags = SmpDebug; + + /* And always force NX for anything that SMSS launches */ + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX; + + /* Now create the process in suspended state */ + Status = RtlCreateUserProcess(FileName, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + RtlDestroyProcessParameters(ProcessParameters); + if (!NT_SUCCESS(Status)) + { + /* If we couldn't create it, fail back to the caller */ + DPRINT1("SMLIB: Failed load of %wZ - Status == %lx\n", + FileName, Status); + return Status; + } + + // /* Now duplicate the handle to this process */ + // Status = NtDuplicateObject(NtCurrentProcess(), + // ProcessInfo.ProcessHandle, + // NtCurrentProcess(), + // InitialCommandProcess, + // PROCESS_ALL_ACCESS, + // 0, + // 0); + // if (!NT_SUCCESS(Status)) + // { + // /* Kill it utterly if duplication failed */ + // DPRINT1("SMLIB: DupObject Failed. Status == %lx\n", Status); + // NtTerminateProcess(ProcessInfo.ProcessHandle, Status); + // NtResumeThread(ProcessInfo.ThreadHandle, NULL); + // NtClose(ProcessInfo.ThreadHandle); + // NtClose(ProcessInfo.ProcessHandle); + // return Status; + // } + + /* Call SM and wait for a reply */ + Status = SmExecPgm(SmApiPort, &ProcessInfo, TRUE); + + NtClose(ProcessInfo.ThreadHandle); + NtClose(ProcessInfo.ProcessHandle); + + // if (ProcessInformation) + // *ProcessInformation = ProcessInfo; + + DPRINT("SMLIB: %s returned (Status=0x%08lx)\n", __FUNCTION__, Status); + return Status; +} + +/** + * @brief + * Reads from the registry key + * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems + * the value specified by Name. + * + * @param[in] Name + * Name of the program to run, that is a value's name in + * the SM registry key "SubSystems". + * + * @param[out] Data + * What the registry gave back for Name. + * + * @param[in,out] DataLength + * How much Data the registry returns. + * + * @param[out] DataType + * Optional pointer to a variable that receives the type of data + * stored in the specified value. + * + * @param[in] Environment + * Optional environment to be used to possibly expand Data before + * returning it back; if set to NULL, no expansion will be performed. + * + * @return + * Success status if the specified subsystem existed and its information + * has been retrieved successfully; otherwise a failure status code. + **/ +NTSTATUS +NTAPI +SmLookupSubsystem( + _In_ PWSTR Name, + _Out_ PWSTR Data, + _Inout_ PULONG DataLength, + _Out_opt_ PULONG DataType, + _In_opt_ PVOID Environment) +{ + NTSTATUS Status; + UNICODE_STRING usKeyName; + OBJECT_ATTRIBUTES Oa; + HANDLE hKey = NULL; + + UNICODE_STRING usValueName; + PWCHAR KeyValueInformation = NULL; + ULONG KeyValueInformationLength = 1024; + ULONG ResultLength = 0; + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + + DPRINT("SMLIB: %s(Name='%S') called\n", __FUNCTION__, Name); + + /* + * Prepare the key name to scan and + * related object attributes. + */ + RtlInitUnicodeString(&usKeyName, + L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems"); + + InitializeObjectAttributes(&Oa, + &usKeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + /* + * Open the key. This MUST NOT fail, if the + * request is for a legitimate subsystem. + */ + Status = NtOpenKey(&hKey, + MAXIMUM_ALLOWED, + &Oa); + if (!NT_SUCCESS(Status)) + { + DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status); + return Status; + } + + KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + KeyValueInformationLength); + if (!KeyValueInformation) + { + NtClose(hKey); + return STATUS_NO_MEMORY; + } + + kvpi = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueInformation; + RtlInitUnicodeString(&usValueName, Name); + Status = NtQueryValueKey(hKey, + &usValueName, + KeyValuePartialInformation, + KeyValueInformation, + KeyValueInformationLength, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status); + + RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); + NtClose(hKey); + + return Status; + } + + DPRINT("kvpi.TitleIndex = %lu\n", kvpi->TitleIndex); + DPRINT("kvpi.Type = %lu\n", kvpi->Type); + DPRINT("kvpi.DataLength = %lu\n", kvpi->DataLength); + + if (Data && DataLength) + { + if (DataType) + *DataType = kvpi->Type; + + if (Environment && (kvpi->Type == REG_EXPAND_SZ)) + { + UNICODE_STRING Source; + UNICODE_STRING Destination; + PWCHAR DestinationBuffer = NULL; + ULONG Length; + + DPRINT("SMLIB: %s: value will be expanded\n", __FUNCTION__); + + Length = 2 * KeyValueInformationLength; + DestinationBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + Length); + if (!DestinationBuffer) + { + Status = STATUS_NO_MEMORY; + } + else + { + Source.Length = (USHORT)kvpi->DataLength; + Source.MaximumLength = Source.Length; + Source.Buffer = (PWCHAR)&kvpi->Data; + + RtlInitEmptyUnicodeString(&Destination, + DestinationBuffer, + (USHORT)Length); + + Length = 0; + Status = RtlExpandEnvironmentStrings_U(Environment, + &Source, + &Destination, + &Length); + if (NT_SUCCESS(Status)) + { + *DataLength = min(*DataLength, Destination.Length); + RtlCopyMemory(Data, Destination.Buffer, *DataLength); + } + RtlFreeHeap(RtlGetProcessHeap(), 0, DestinationBuffer); + } + } + else + { + DPRINT("SMLIB: %s: value won't be expanded\n", __FUNCTION__); + *DataLength = min(*DataLength, kvpi->DataLength); + RtlCopyMemory(Data, &kvpi->Data, *DataLength); + } + } + else + { + DPRINT1("SMLIB: %s: Data or DataLength is NULL!\n", __FUNCTION__); + Status = STATUS_INVALID_PARAMETER; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); + NtClose(hKey); + + return Status; +} + +/** + * @brief + * Retrieves information about subsystems registered with the SM. + * + * @param[in] SmApiPort + * Port handle returned by SmConnectToSm(). + * + * @param[in] SmInformationClass + * An 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. + * + * @param[in,out] Data + * Pointer to storage for the information to request. Either a + * SM_BASIC_INFORMATION or a SM_SUBSYSTEM_INFORMATION, depending + * on the information class. + * + * @param[in] DataLength + * Length in bytes of the Data buffer; it must be set and must + * match the SmInformationClass information size. + * + * @param[in,out] ReturnedDataLength + * Optional pointer to storage to receive the size of the returned data. + * + * @return + * 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. + * + * @remark + * This API is ReactOS-specific and not in NT. + */ +NTSTATUS +NTAPI +SmQueryInformation( + _In_ HANDLE SmApiPort, + _In_ SM_INFORMATION_CLASS SmInformationClass, + _Inout_ PVOID Data, + _In_ ULONG DataLength, + _Inout_opt_ PULONG ReturnedDataLength) +{ +#if defined(__REACTOS__) && DBG + NTSTATUS Status; + SM_API_MSG SmApiMsg = {0}; + PSM_QUERYINFO_MSG QueryInfo = &SmApiMsg.u.QueryInfo; + + /* Marshal data in the port message */ + switch (SmInformationClass) + { + case SmBasicInformation: + if (DataLength != sizeof(SM_BASIC_INFORMATION)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + QueryInfo->SmInformationClass = SmBasicInformation; + QueryInfo->DataLength = DataLength; + QueryInfo->BasicInformation.SubSystemCount = 0; + break; + + case SmSubSystemInformation: + if (DataLength != sizeof(SM_SUBSYSTEM_INFORMATION)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + QueryInfo->SmInformationClass = SmSubSystemInformation; + QueryInfo->DataLength = DataLength; + QueryInfo->SubSystemInformation.SubSystemId = + ((PSM_SUBSYSTEM_INFORMATION)Data)->SubSystemId; + break; + + default: + return STATUS_INVALID_PARAMETER_2; + } + + /* SM API to invoke */ + SmApiMsg.ApiNumber = SM_API_QUERY_INFORMATION; + + /* NOTE: Repurpose the DataLength variable */ + DataLength = sizeof(SM_QUERYINFO_MSG); + + /* Fill out the Port Message Header */ + // SmApiMsg.h.u2.s2.Type = LPC_NEW_MESSAGE; + SmApiMsg.h.u2.ZeroInit = 0; + /* DataLength = user_data_size + anything between + * header and data, including intermediate padding */ + SmApiMsg.h.u1.s1.DataLength = (CSHORT)DataLength + + FIELD_OFFSET(SM_API_MSG, u) - sizeof(SmApiMsg.h); + /* TotalLength = sizeof(SmApiMsg) on <= NT5.2, otherwise: + * DataLength + header_size == user_data_size + FIELD_OFFSET(SM_API_MSG, u) + * without structure trailing padding */ + SmApiMsg.h.u1.s1.TotalLength = SmApiMsg.h.u1.s1.DataLength + sizeof(SmApiMsg.h); + + /* Send the LPC message and wait for a reply */ + Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SMLIB: %s: NtRequestWaitReplyPort failed, Status: 0x%08lx\n", + __FUNCTION__, Status); + return Status; + } + + /* Unmarshal data */ + RtlCopyMemory(Data, + &QueryInfo->BasicInformation, + QueryInfo->DataLength); + + /* Use caller provided storage to store data size */ + if (ReturnedDataLength) + *ReturnedDataLength = QueryInfo->DataLength; + + /* Return the real status */ + return SmApiMsg.ReturnValue; +#else + return STATUS_NOT_IMPLEMENTED; +#endif /* defined(__REACTOS__) && DBG */ +} + +/* EOF */ diff --git a/sdk/lib/smlib/smutils.cmake b/sdk/lib/smlib/smutils.cmake new file mode 100644 index 00000000000..579eecb0650 --- /dev/null +++ b/sdk/lib/smlib/smutils.cmake @@ -0,0 +1,11 @@ + +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys) + +list(APPEND SOURCE + smutils.c + precomp.h) + +add_library(smutils ${SOURCE}) +target_link_libraries(smutils smlib) +add_pch(smutils precomp.h SOURCE) +add_dependencies(smutils psdk) diff --git a/sdk/tools/gen_baseaddress.py b/sdk/tools/gen_baseaddress.py index 0b0cc2e4739..51e89d0870d 100644 --- a/sdk/tools/gen_baseaddress.py +++ b/sdk/tools/gen_baseaddress.py @@ -77,7 +77,6 @@ PRIORITIES = ( 'glu32.dll', 'opengl32.dll', 'riched20.dll', - 'smdll.dll', 'userenv.dll', 'uxtheme.dll', 'cryptui.dll', diff --git a/sdk/tools/rgenstat/module_list.txt b/sdk/tools/rgenstat/module_list.txt index 269ab99ab9d..993c3618632 100644 --- a/sdk/tools/rgenstat/module_list.txt +++ b/sdk/tools/rgenstat/module_list.txt @@ -108,7 +108,6 @@ shdocvw dll\win32\shdocvw shell32 dll\win32\shell32 shfolder dll\win32\shfolder shlwapi dll\win32\shlwapi -smdll dll\win32\smdll snmpapi dll\win32\snmpapi syssetup dll\win32\syssetup twain_32 dll\win32\twain_32