FreeRDP
Loading...
Searching...
No Matches
wtsapi.c
1
22#include <winpr/config.h>
23
24#include <winpr/crt.h>
25#include <winpr/ini.h>
26#include <winpr/path.h>
27#include <winpr/synch.h>
28#include <winpr/library.h>
29#include <winpr/environment.h>
30
31#include <winpr/wtsapi.h>
32
33#ifdef _WIN32
34#include "wtsapi_win32.h"
35#endif
36
37#include "../log.h"
38#define TAG WINPR_TAG("wtsapi")
39
45static HMODULE g_WtsApiModule = nullptr;
46
47static const WtsApiFunctionTable* g_WtsApi = nullptr;
48
49#if defined(_WIN32)
50static HMODULE g_WtsApi32Module = nullptr;
51static WtsApiFunctionTable WtsApi32_WtsApiFunctionTable = WINPR_C_ARRAY_INIT;
52
53#ifdef __MINGW32__
54#define WTSAPI32_LOAD_PROC(NAME, TYPE) \
55 WtsApi32_WtsApiFunctionTable.p##NAME = GetProcAddressAs(g_WtsApi32Module, "WTS" #NAME, TYPE);
56#else
57#define WTSAPI32_LOAD_PROC(NAME, TYPE) \
58 WtsApi32_WtsApiFunctionTable.p##NAME = GetProcAddressAs(g_WtsApi32Module, "WTS" #NAME, ##TYPE);
59#endif
60
61static BOOL WtsApi32_InitializeWtsApi(void)
62{
63 g_WtsApi32Module = LoadLibraryA("wtsapi32.dll");
64
65 if (!g_WtsApi32Module)
66 return FALSE;
67
68 WTSAPI32_LOAD_PROC(StopRemoteControlSession, WTS_STOP_REMOTE_CONTROL_SESSION_FN);
69 WTSAPI32_LOAD_PROC(StartRemoteControlSessionW, WTS_START_REMOTE_CONTROL_SESSION_FN_W);
70 WTSAPI32_LOAD_PROC(StartRemoteControlSessionA, WTS_START_REMOTE_CONTROL_SESSION_FN_A);
71 WTSAPI32_LOAD_PROC(ConnectSessionW, WTS_CONNECT_SESSION_FN_W);
72 WTSAPI32_LOAD_PROC(ConnectSessionA, WTS_CONNECT_SESSION_FN_A);
73 WTSAPI32_LOAD_PROC(EnumerateServersW, WTS_ENUMERATE_SERVERS_FN_W);
74 WTSAPI32_LOAD_PROC(EnumerateServersA, WTS_ENUMERATE_SERVERS_FN_A);
75 WTSAPI32_LOAD_PROC(OpenServerW, WTS_OPEN_SERVER_FN_W);
76 WTSAPI32_LOAD_PROC(OpenServerA, WTS_OPEN_SERVER_FN_A);
77 WTSAPI32_LOAD_PROC(OpenServerExW, WTS_OPEN_SERVER_EX_FN_W);
78 WTSAPI32_LOAD_PROC(OpenServerExA, WTS_OPEN_SERVER_EX_FN_A);
79 WTSAPI32_LOAD_PROC(CloseServer, WTS_CLOSE_SERVER_FN);
80 WTSAPI32_LOAD_PROC(EnumerateSessionsW, WTS_ENUMERATE_SESSIONS_FN_W);
81 WTSAPI32_LOAD_PROC(EnumerateSessionsA, WTS_ENUMERATE_SESSIONS_FN_A);
82 WTSAPI32_LOAD_PROC(EnumerateSessionsExW, WTS_ENUMERATE_SESSIONS_EX_FN_W);
83 WTSAPI32_LOAD_PROC(EnumerateSessionsExA, WTS_ENUMERATE_SESSIONS_EX_FN_A);
84 WTSAPI32_LOAD_PROC(EnumerateProcessesW, WTS_ENUMERATE_PROCESSES_FN_W);
85 WTSAPI32_LOAD_PROC(EnumerateProcessesA, WTS_ENUMERATE_PROCESSES_FN_A);
86 WTSAPI32_LOAD_PROC(TerminateProcess, WTS_TERMINATE_PROCESS_FN);
87 WTSAPI32_LOAD_PROC(QuerySessionInformationW, WTS_QUERY_SESSION_INFORMATION_FN_W);
88 WTSAPI32_LOAD_PROC(QuerySessionInformationA, WTS_QUERY_SESSION_INFORMATION_FN_A);
89 WTSAPI32_LOAD_PROC(QueryUserConfigW, WTS_QUERY_USER_CONFIG_FN_W);
90 WTSAPI32_LOAD_PROC(QueryUserConfigA, WTS_QUERY_USER_CONFIG_FN_A);
91 WTSAPI32_LOAD_PROC(SetUserConfigW, WTS_SET_USER_CONFIG_FN_W);
92 WTSAPI32_LOAD_PROC(SetUserConfigA, WTS_SET_USER_CONFIG_FN_A);
93 WTSAPI32_LOAD_PROC(SendMessageW, WTS_SEND_MESSAGE_FN_W);
94 WTSAPI32_LOAD_PROC(SendMessageA, WTS_SEND_MESSAGE_FN_A);
95 WTSAPI32_LOAD_PROC(DisconnectSession, WTS_DISCONNECT_SESSION_FN);
96 WTSAPI32_LOAD_PROC(LogoffSession, WTS_LOGOFF_SESSION_FN);
97 WTSAPI32_LOAD_PROC(ShutdownSystem, WTS_SHUTDOWN_SYSTEM_FN);
98 WTSAPI32_LOAD_PROC(WaitSystemEvent, WTS_WAIT_SYSTEM_EVENT_FN);
99 WTSAPI32_LOAD_PROC(VirtualChannelOpen, WTS_VIRTUAL_CHANNEL_OPEN_FN);
100 WTSAPI32_LOAD_PROC(VirtualChannelOpenEx, WTS_VIRTUAL_CHANNEL_OPEN_EX_FN);
101 WTSAPI32_LOAD_PROC(VirtualChannelClose, WTS_VIRTUAL_CHANNEL_CLOSE_FN);
102 WTSAPI32_LOAD_PROC(VirtualChannelRead, WTS_VIRTUAL_CHANNEL_READ_FN);
103 WTSAPI32_LOAD_PROC(VirtualChannelWrite, WTS_VIRTUAL_CHANNEL_WRITE_FN);
104 WTSAPI32_LOAD_PROC(VirtualChannelPurgeInput, WTS_VIRTUAL_CHANNEL_PURGE_INPUT_FN);
105 WTSAPI32_LOAD_PROC(VirtualChannelPurgeOutput, WTS_VIRTUAL_CHANNEL_PURGE_OUTPUT_FN);
106 WTSAPI32_LOAD_PROC(VirtualChannelQuery, WTS_VIRTUAL_CHANNEL_QUERY_FN);
107 WTSAPI32_LOAD_PROC(FreeMemory, WTS_FREE_MEMORY_FN);
108 WTSAPI32_LOAD_PROC(RegisterSessionNotification, WTS_REGISTER_SESSION_NOTIFICATION_FN);
109 WTSAPI32_LOAD_PROC(UnRegisterSessionNotification, WTS_UNREGISTER_SESSION_NOTIFICATION_FN);
110 WTSAPI32_LOAD_PROC(RegisterSessionNotificationEx, WTS_REGISTER_SESSION_NOTIFICATION_EX_FN);
111 WTSAPI32_LOAD_PROC(UnRegisterSessionNotificationEx, WTS_UNREGISTER_SESSION_NOTIFICATION_EX_FN);
112 WTSAPI32_LOAD_PROC(QueryUserToken, WTS_QUERY_USER_TOKEN_FN);
113 WTSAPI32_LOAD_PROC(FreeMemoryExW, WTS_FREE_MEMORY_EX_FN_W);
114 WTSAPI32_LOAD_PROC(FreeMemoryExA, WTS_FREE_MEMORY_EX_FN_A);
115 WTSAPI32_LOAD_PROC(EnumerateProcessesExW, WTS_ENUMERATE_PROCESSES_EX_FN_W);
116 WTSAPI32_LOAD_PROC(EnumerateProcessesExA, WTS_ENUMERATE_PROCESSES_EX_FN_A);
117 WTSAPI32_LOAD_PROC(EnumerateListenersW, WTS_ENUMERATE_LISTENERS_FN_W);
118 WTSAPI32_LOAD_PROC(EnumerateListenersA, WTS_ENUMERATE_LISTENERS_FN_A);
119 WTSAPI32_LOAD_PROC(QueryListenerConfigW, WTS_QUERY_LISTENER_CONFIG_FN_W);
120 WTSAPI32_LOAD_PROC(QueryListenerConfigA, WTS_QUERY_LISTENER_CONFIG_FN_A);
121 WTSAPI32_LOAD_PROC(CreateListenerW, WTS_CREATE_LISTENER_FN_W);
122 WTSAPI32_LOAD_PROC(CreateListenerA, WTS_CREATE_LISTENER_FN_A);
123 WTSAPI32_LOAD_PROC(SetListenerSecurityW, WTS_SET_LISTENER_SECURITY_FN_W);
124 WTSAPI32_LOAD_PROC(SetListenerSecurityA, WTS_SET_LISTENER_SECURITY_FN_A);
125 WTSAPI32_LOAD_PROC(GetListenerSecurityW, WTS_GET_LISTENER_SECURITY_FN_W);
126 WTSAPI32_LOAD_PROC(GetListenerSecurityA, WTS_GET_LISTENER_SECURITY_FN_A);
127 WTSAPI32_LOAD_PROC(EnableChildSessions, WTS_ENABLE_CHILD_SESSIONS_FN);
128 WTSAPI32_LOAD_PROC(IsChildSessionsEnabled, WTS_IS_CHILD_SESSIONS_ENABLED_FN);
129 WTSAPI32_LOAD_PROC(GetChildSessionId, WTS_GET_CHILD_SESSION_ID_FN);
130 WTSAPI32_LOAD_PROC(GetActiveConsoleSessionId, WTS_GET_ACTIVE_CONSOLE_SESSION_ID_FN);
131
132 Win32_InitializeWinSta(&WtsApi32_WtsApiFunctionTable);
133
134 g_WtsApi = &WtsApi32_WtsApiFunctionTable;
135
136 return TRUE;
137}
138#endif
139
140/* WtsApi Functions */
141
142static BOOL CALLBACK InitializeWtsApiStubs(PINIT_ONCE once, PVOID param, PVOID* context);
143static INIT_ONCE wtsapiInitOnce = INIT_ONCE_STATIC_INIT;
144
145#define WTSAPI_STUB_CALL_VOID(_name, ...) \
146 if (!InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, nullptr, nullptr)) \
147 return; \
148 if (!g_WtsApi || !g_WtsApi->p##_name) \
149 return; \
150 g_WtsApi->p##_name(__VA_ARGS__)
151
152#define WTSAPI_STUB_CALL_BOOL(_name, ...) \
153 if (!InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, nullptr, nullptr)) \
154 return FALSE; \
155 if (!g_WtsApi || !g_WtsApi->p##_name) \
156 return FALSE; \
157 return g_WtsApi->p##_name(__VA_ARGS__)
158
159#define WTSAPI_STUB_CALL_HANDLE(_name, ...) \
160 if (!InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, nullptr, nullptr)) \
161 return nullptr; \
162 if (!g_WtsApi || !g_WtsApi->p##_name) \
163 return nullptr; \
164 return g_WtsApi->p##_name(__VA_ARGS__)
165
166BOOL WINAPI WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId,
167 BYTE HotkeyVk, USHORT HotkeyModifiers)
168{
169 WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionW, pTargetServerName, TargetLogonId, HotkeyVk,
170 HotkeyModifiers);
171}
172
173BOOL WINAPI WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
174 BYTE HotkeyVk, USHORT HotkeyModifiers)
175{
176 WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionA, pTargetServerName, TargetLogonId, HotkeyVk,
177 HotkeyModifiers);
178}
179
180BOOL WINAPI WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName, ULONG TargetLogonId,
181 BYTE HotkeyVk, USHORT HotkeyModifiers, DWORD flags)
182{
183 WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionExW, pTargetServerName, TargetLogonId, HotkeyVk,
184 HotkeyModifiers, flags);
185}
186
187BOOL WINAPI WTSStartRemoteControlSessionExA(LPSTR pTargetServerName, ULONG TargetLogonId,
188 BYTE HotkeyVk, USHORT HotkeyModifiers, DWORD flags)
189{
190 WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionExA, pTargetServerName, TargetLogonId, HotkeyVk,
191 HotkeyModifiers, flags);
192}
193
194BOOL WINAPI WTSStopRemoteControlSession(ULONG LogonId)
195{
196 WTSAPI_STUB_CALL_BOOL(StopRemoteControlSession, LogonId);
197}
198
199BOOL WINAPI WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait)
200{
201 WTSAPI_STUB_CALL_BOOL(ConnectSessionW, LogonId, TargetLogonId, pPassword, bWait);
202}
203
204BOOL WINAPI WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait)
205{
206 WTSAPI_STUB_CALL_BOOL(ConnectSessionA, LogonId, TargetLogonId, pPassword, bWait);
207}
208
209BOOL WINAPI WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version,
210 PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount)
211{
212 WTSAPI_STUB_CALL_BOOL(EnumerateServersW, pDomainName, Reserved, Version, ppServerInfo, pCount);
213}
214
215BOOL WINAPI WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
216 PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount)
217{
218 WTSAPI_STUB_CALL_BOOL(EnumerateServersA, pDomainName, Reserved, Version, ppServerInfo, pCount);
219}
220
221HANDLE WINAPI WTSOpenServerW(LPWSTR pServerName)
222{
223 WTSAPI_STUB_CALL_HANDLE(OpenServerW, pServerName);
224}
225
226HANDLE WINAPI WTSOpenServerA(LPSTR pServerName)
227{
228 WTSAPI_STUB_CALL_HANDLE(OpenServerA, pServerName);
229}
230
231HANDLE WINAPI WTSOpenServerExW(LPWSTR pServerName)
232{
233 WTSAPI_STUB_CALL_HANDLE(OpenServerExW, pServerName);
234}
235
236HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName)
237{
238 WTSAPI_STUB_CALL_HANDLE(OpenServerExA, pServerName);
239}
240
241VOID WINAPI WTSCloseServer(HANDLE hServer)
242{
243 WTSAPI_STUB_CALL_VOID(CloseServer, hServer);
244}
245
246BOOL WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
247 PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount)
248{
249 WTSAPI_STUB_CALL_BOOL(EnumerateSessionsW, hServer, Reserved, Version, ppSessionInfo, pCount);
250}
251
252BOOL WINAPI WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
253 PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount)
254{
255 WTSAPI_STUB_CALL_BOOL(EnumerateSessionsA, hServer, Reserved, Version, ppSessionInfo, pCount);
256}
257
258BOOL WINAPI WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter,
259 PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount)
260{
261 WTSAPI_STUB_CALL_BOOL(EnumerateSessionsExW, hServer, pLevel, Filter, ppSessionInfo, pCount);
262}
263
264BOOL WINAPI WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter,
265 PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount)
266{
267 WTSAPI_STUB_CALL_BOOL(EnumerateSessionsExA, hServer, pLevel, Filter, ppSessionInfo, pCount);
268}
269
270BOOL WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
271 PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
272{
273 WTSAPI_STUB_CALL_BOOL(EnumerateProcessesW, hServer, Reserved, Version, ppProcessInfo, pCount);
274}
275
276BOOL WINAPI WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
277 PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
278{
279 WTSAPI_STUB_CALL_BOOL(EnumerateProcessesA, hServer, Reserved, Version, ppProcessInfo, pCount);
280}
281
282BOOL WINAPI WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
283{
284 WTSAPI_STUB_CALL_BOOL(TerminateProcess, hServer, ProcessId, ExitCode);
285}
286
287BOOL WINAPI WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
288 WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer,
289 DWORD* pBytesReturned)
290{
291 WTSAPI_STUB_CALL_BOOL(QuerySessionInformationW, hServer, SessionId, WTSInfoClass, ppBuffer,
292 pBytesReturned);
293}
294
295BOOL WINAPI WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
296 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
297 DWORD* pBytesReturned)
298{
299 WTSAPI_STUB_CALL_BOOL(QuerySessionInformationA, hServer, SessionId, WTSInfoClass, ppBuffer,
300 pBytesReturned);
301}
302
303BOOL WINAPI WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
304 WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer,
305 DWORD* pBytesReturned)
306{
307 WTSAPI_STUB_CALL_BOOL(QueryUserConfigW, pServerName, pUserName, WTSConfigClass, ppBuffer,
308 pBytesReturned);
309}
310
311BOOL WINAPI WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass,
312 LPSTR* ppBuffer, DWORD* pBytesReturned)
313{
314 WTSAPI_STUB_CALL_BOOL(QueryUserConfigA, pServerName, pUserName, WTSConfigClass, ppBuffer,
315 pBytesReturned);
316}
317
318BOOL WINAPI WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass,
319 LPWSTR pBuffer, DWORD DataLength)
320{
321 WTSAPI_STUB_CALL_BOOL(SetUserConfigW, pServerName, pUserName, WTSConfigClass, pBuffer,
322 DataLength);
323}
324
325BOOL WINAPI WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass,
326 LPSTR pBuffer, DWORD DataLength)
327{
328 WTSAPI_STUB_CALL_BOOL(SetUserConfigA, pServerName, pUserName, WTSConfigClass, pBuffer,
329 DataLength);
330}
331
332BOOL WINAPI WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength,
333 LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout,
334 DWORD* pResponse, BOOL bWait)
335{
336 WTSAPI_STUB_CALL_BOOL(SendMessageW, hServer, SessionId, pTitle, TitleLength, pMessage,
337 MessageLength, Style, Timeout, pResponse, bWait);
338}
339
340BOOL WINAPI WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength,
341 LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout,
342 DWORD* pResponse, BOOL bWait)
343{
344 WTSAPI_STUB_CALL_BOOL(SendMessageA, hServer, SessionId, pTitle, TitleLength, pMessage,
345 MessageLength, Style, Timeout, pResponse, bWait);
346}
347
348BOOL WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
349{
350 WTSAPI_STUB_CALL_BOOL(DisconnectSession, hServer, SessionId, bWait);
351}
352
353BOOL WINAPI WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
354{
355 WTSAPI_STUB_CALL_BOOL(LogoffSession, hServer, SessionId, bWait);
356}
357
358BOOL WINAPI WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
359{
360 WTSAPI_STUB_CALL_BOOL(ShutdownSystem, hServer, ShutdownFlag);
361}
362
363BOOL WINAPI WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
364{
365 WTSAPI_STUB_CALL_BOOL(WaitSystemEvent, hServer, EventMask, pEventFlags);
366}
367
368HANDLE WINAPI WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
369{
370 WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpen, hServer, SessionId, pVirtualName);
371}
372
373HANDLE WINAPI WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
374{
375 WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpenEx, SessionId, pVirtualName, flags);
376}
377
378BOOL WINAPI WTSVirtualChannelClose(HANDLE hChannelHandle)
379{
380 WTSAPI_STUB_CALL_BOOL(VirtualChannelClose, hChannelHandle);
381}
382
383BOOL WINAPI WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer,
384 ULONG BufferSize, PULONG pBytesRead)
385{
386 WTSAPI_STUB_CALL_BOOL(VirtualChannelRead, hChannelHandle, TimeOut, Buffer, BufferSize,
387 pBytesRead);
388}
389
390BOOL WINAPI WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
391 PULONG pBytesWritten)
392{
393 WTSAPI_STUB_CALL_BOOL(VirtualChannelWrite, hChannelHandle, Buffer, Length, pBytesWritten);
394}
395
396BOOL WINAPI WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
397{
398 WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeInput, hChannelHandle);
399}
400
401BOOL WINAPI WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
402{
403 WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeOutput, hChannelHandle);
404}
405
406BOOL WINAPI WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
407 PVOID* ppBuffer, DWORD* pBytesReturned)
408{
409 WTSAPI_STUB_CALL_BOOL(VirtualChannelQuery, hChannelHandle, WtsVirtualClass, ppBuffer,
410 pBytesReturned);
411}
412
413VOID WINAPI WTSFreeMemory(PVOID pMemory)
414{
415 WTSAPI_STUB_CALL_VOID(FreeMemory, pMemory);
416}
417
418BOOL WINAPI WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
419{
420 WTSAPI_STUB_CALL_BOOL(FreeMemoryExW, WTSTypeClass, pMemory, NumberOfEntries);
421}
422
423BOOL WINAPI WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
424{
425 WTSAPI_STUB_CALL_BOOL(FreeMemoryExA, WTSTypeClass, pMemory, NumberOfEntries);
426}
427
428BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
429{
430 WTSAPI_STUB_CALL_BOOL(RegisterSessionNotification, hWnd, dwFlags);
431}
432
433BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd)
434{
435 WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotification, hWnd);
436}
437
438BOOL WINAPI WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
439{
440 WTSAPI_STUB_CALL_BOOL(RegisterSessionNotificationEx, hServer, hWnd, dwFlags);
441}
442
443BOOL WINAPI WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
444{
445 WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotificationEx, hServer, hWnd);
446}
447
448BOOL WINAPI WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
449{
450 WTSAPI_STUB_CALL_BOOL(QueryUserToken, SessionId, phToken);
451}
452
453BOOL WINAPI WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
454 LPWSTR* ppProcessInfo, DWORD* pCount)
455{
456 WTSAPI_STUB_CALL_BOOL(EnumerateProcessesExW, hServer, pLevel, SessionId, ppProcessInfo, pCount);
457}
458
459BOOL WINAPI WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
460 LPSTR* ppProcessInfo, DWORD* pCount)
461{
462 WTSAPI_STUB_CALL_BOOL(EnumerateProcessesExA, hServer, pLevel, SessionId, ppProcessInfo, pCount);
463}
464
465BOOL WINAPI WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
466 PWTSLISTENERNAMEW pListeners, DWORD* pCount)
467{
468 WTSAPI_STUB_CALL_BOOL(EnumerateListenersW, hServer, pReserved, Reserved, pListeners, pCount);
469}
470
471BOOL WINAPI WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
472 PWTSLISTENERNAMEA pListeners, DWORD* pCount)
473{
474 WTSAPI_STUB_CALL_BOOL(EnumerateListenersA, hServer, pReserved, Reserved, pListeners, pCount);
475}
476
477BOOL WINAPI WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
478 LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer)
479{
480 WTSAPI_STUB_CALL_BOOL(QueryListenerConfigW, hServer, pReserved, Reserved, pListenerName,
481 pBuffer);
482}
483
484BOOL WINAPI WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
485 LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer)
486{
487 WTSAPI_STUB_CALL_BOOL(QueryListenerConfigA, hServer, pReserved, Reserved, pListenerName,
488 pBuffer);
489}
490
491BOOL WINAPI WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
492 LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag)
493{
494 WTSAPI_STUB_CALL_BOOL(CreateListenerW, hServer, pReserved, Reserved, pListenerName, pBuffer,
495 flag);
496}
497
498BOOL WINAPI WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName,
499 PWTSLISTENERCONFIGA pBuffer, DWORD flag)
500{
501 WTSAPI_STUB_CALL_BOOL(CreateListenerA, hServer, pReserved, Reserved, pListenerName, pBuffer,
502 flag);
503}
504
505BOOL WINAPI WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
506 LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
507 PSECURITY_DESCRIPTOR pSecurityDescriptor)
508{
509 WTSAPI_STUB_CALL_BOOL(SetListenerSecurityW, hServer, pReserved, Reserved, pListenerName,
510 SecurityInformation, pSecurityDescriptor);
511}
512
513BOOL WINAPI WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
514 LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
515 PSECURITY_DESCRIPTOR pSecurityDescriptor)
516{
517 WTSAPI_STUB_CALL_BOOL(SetListenerSecurityA, hServer, pReserved, Reserved, pListenerName,
518 SecurityInformation, pSecurityDescriptor);
519}
520
521BOOL WINAPI WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
522 LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
523 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
524 LPDWORD lpnLengthNeeded)
525{
526 WTSAPI_STUB_CALL_BOOL(GetListenerSecurityW, hServer, pReserved, Reserved, pListenerName,
527 SecurityInformation, pSecurityDescriptor, nLength, lpnLengthNeeded);
528}
529
530BOOL WINAPI WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
531 LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
532 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
533 LPDWORD lpnLengthNeeded)
534{
535 WTSAPI_STUB_CALL_BOOL(GetListenerSecurityA, hServer, pReserved, Reserved, pListenerName,
536 SecurityInformation, pSecurityDescriptor, nLength, lpnLengthNeeded);
537}
538
539BOOL CDECL WTSEnableChildSessions(BOOL bEnable)
540{
541 WTSAPI_STUB_CALL_BOOL(EnableChildSessions, bEnable);
542}
543
544BOOL CDECL WTSIsChildSessionsEnabled(PBOOL pbEnabled)
545{
546 WTSAPI_STUB_CALL_BOOL(IsChildSessionsEnabled, pbEnabled);
547}
548
549BOOL CDECL WTSGetChildSessionId(PULONG pSessionId)
550{
551 WTSAPI_STUB_CALL_BOOL(GetChildSessionId, pSessionId);
552}
553
554BOOL CDECL WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
555{
556 WTSAPI_STUB_CALL_BOOL(LogonUser, hServer, username, password, domain);
557}
558
559BOOL CDECL WTSLogoffUser(HANDLE hServer)
560{
561 WTSAPI_STUB_CALL_BOOL(LogoffUser, hServer);
562}
563
564#ifndef _WIN32
565
570DWORD WINAPI WTSGetActiveConsoleSessionId(void)
571{
572 if (!InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, nullptr, nullptr))
573 return UINT32_MAX;
574
575 if (!g_WtsApi || !g_WtsApi->pGetActiveConsoleSessionId)
576 return UINT32_MAX;
577
578 return g_WtsApi->pGetActiveConsoleSessionId();
579}
580
581#endif
582
583const CHAR* WTSErrorToString(UINT error)
584{
585 switch (error)
586 {
587 case CHANNEL_RC_OK:
588 return "CHANNEL_RC_OK";
589
590 case CHANNEL_RC_ALREADY_INITIALIZED:
591 return "CHANNEL_RC_ALREADY_INITIALIZED";
592
593 case CHANNEL_RC_NOT_INITIALIZED:
594 return "CHANNEL_RC_NOT_INITIALIZED";
595
596 case CHANNEL_RC_ALREADY_CONNECTED:
597 return "CHANNEL_RC_ALREADY_CONNECTED";
598
599 case CHANNEL_RC_NOT_CONNECTED:
600 return "CHANNEL_RC_NOT_CONNECTED";
601
602 case CHANNEL_RC_TOO_MANY_CHANNELS:
603 return "CHANNEL_RC_TOO_MANY_CHANNELS";
604
605 case CHANNEL_RC_BAD_CHANNEL:
606 return "CHANNEL_RC_BAD_CHANNEL";
607
608 case CHANNEL_RC_BAD_CHANNEL_HANDLE:
609 return "CHANNEL_RC_BAD_CHANNEL_HANDLE";
610
611 case CHANNEL_RC_NO_BUFFER:
612 return "CHANNEL_RC_NO_BUFFER";
613
614 case CHANNEL_RC_BAD_INIT_HANDLE:
615 return "CHANNEL_RC_BAD_INIT_HANDLE";
616
617 case CHANNEL_RC_NOT_OPEN:
618 return "CHANNEL_RC_NOT_OPEN";
619
620 case CHANNEL_RC_BAD_PROC:
621 return "CHANNEL_RC_BAD_PROC";
622
623 case CHANNEL_RC_NO_MEMORY:
624 return "CHANNEL_RC_NO_MEMORY";
625
626 case CHANNEL_RC_UNKNOWN_CHANNEL_NAME:
627 return "CHANNEL_RC_UNKNOWN_CHANNEL_NAME";
628
629 case CHANNEL_RC_ALREADY_OPEN:
630 return "CHANNEL_RC_ALREADY_OPEN";
631
632 case CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY:
633 return "CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY";
634
635 case CHANNEL_RC_NULL_DATA:
636 return "CHANNEL_RC_NULL_DATA";
637
638 case CHANNEL_RC_ZERO_LENGTH:
639 return "CHANNEL_RC_ZERO_LENGTH";
640
641 case CHANNEL_RC_INVALID_INSTANCE:
642 return "CHANNEL_RC_INVALID_INSTANCE";
643
644 case CHANNEL_RC_UNSUPPORTED_VERSION:
645 return "CHANNEL_RC_UNSUPPORTED_VERSION";
646
647 case CHANNEL_RC_INITIALIZATION_ERROR:
648 return "CHANNEL_RC_INITIALIZATION_ERROR";
649
650 default:
651 return "UNKNOWN";
652 }
653}
654
655const CHAR* WTSSessionStateToString(WTS_CONNECTSTATE_CLASS state)
656{
657 switch (state)
658 {
659 case WTSActive:
660 return "WTSActive";
661 case WTSConnected:
662 return "WTSConnected";
663 case WTSConnectQuery:
664 return "WTSConnectQuery";
665 case WTSShadow:
666 return "WTSShadow";
667 case WTSDisconnected:
668 return "WTSDisconnected";
669 case WTSIdle:
670 return "WTSIdle";
671 case WTSListen:
672 return "WTSListen";
673 case WTSReset:
674 return "WTSReset";
675 case WTSDown:
676 return "WTSDown";
677 case WTSInit:
678 return "WTSInit";
679 default:
680 break;
681 }
682 return "INVALID_STATE";
683}
684
685BOOL WTSRegisterWtsApiFunctionTable(const WtsApiFunctionTable* table)
686{
687 /* Use InitOnceExecuteOnce here as well - otherwise a table set with this
688 function is overridden on the first use of a WTS* API call (due to
689 wtsapiInitOnce not being set). */
690 union
691 {
692 const void* cpv;
693 void* pv;
694 } cnv;
695 cnv.cpv = table;
696 if (!InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, cnv.pv, nullptr))
697 return FALSE;
698 return g_WtsApi != nullptr;
699}
700
701static BOOL LoadAndInitialize(char* library)
702{
703 g_WtsApiModule = LoadLibraryX(library);
704
705 if (!g_WtsApiModule)
706 return FALSE;
707
708 INIT_WTSAPI_FN pInitWtsApi = GetProcAddressAs(g_WtsApiModule, "InitWtsApi", INIT_WTSAPI_FN);
709
710 if (!pInitWtsApi)
711 return FALSE;
712
713 g_WtsApi = pInitWtsApi();
714 return TRUE;
715}
716
717static void InitializeWtsApiStubs_Env(void)
718{
719 DWORD nSize = 0;
720 char* env = nullptr;
721 LPCSTR wts = "WTSAPI_LIBRARY";
722
723 if (g_WtsApi)
724 return;
725
726 nSize = GetEnvironmentVariableA(wts, nullptr, 0);
727
728 if (!nSize)
729 return;
730
731 env = (LPSTR)malloc(nSize);
732 if (env)
733 {
734 if (GetEnvironmentVariableA(wts, env, nSize) == nSize - 1)
735 LoadAndInitialize(env);
736 free(env);
737 }
738}
739
740#define FREERDS_LIBRARY_NAME "libfreerds-fdsapi.so"
741
742static void InitializeWtsApiStubs_FreeRDS(void)
743{
744 wIniFile* ini = nullptr;
745 const char* prefix = nullptr;
746 const char* libdir = nullptr;
747
748 if (g_WtsApi)
749 return;
750
751 ini = IniFile_New();
752
753 if (IniFile_ReadFile(ini, "/var/run/freerds.instance") < 0)
754 {
755 IniFile_Free(ini);
756 WLog_ERR(TAG, "failed to parse freerds.instance");
757 LoadAndInitialize(FREERDS_LIBRARY_NAME);
758 return;
759 }
760
761 prefix = IniFile_GetKeyValueString(ini, "FreeRDS", "prefix");
762 libdir = IniFile_GetKeyValueString(ini, "FreeRDS", "libdir");
763 WLog_INFO(TAG, "FreeRDS (prefix / libdir): %s / %s", prefix, libdir);
764
765 if (prefix && libdir)
766 {
767 char* prefix_libdir = nullptr;
768 char* wtsapi_library = nullptr;
769 prefix_libdir = GetCombinedPath(prefix, libdir);
770 wtsapi_library = GetCombinedPath(prefix_libdir, FREERDS_LIBRARY_NAME);
771
772 if (wtsapi_library)
773 {
774 LoadAndInitialize(wtsapi_library);
775 }
776
777 free(prefix_libdir);
778 free(wtsapi_library);
779 }
780
781 IniFile_Free(ini);
782}
783
784static BOOL CALLBACK InitializeWtsApiStubs(PINIT_ONCE once, PVOID param, PVOID* context)
785{
786 WINPR_UNUSED(once);
787 WINPR_UNUSED(context);
788 if (param)
789 {
790 g_WtsApi = (const WtsApiFunctionTable*)param;
791 return TRUE;
792 }
793
794 InitializeWtsApiStubs_Env();
795
796#ifdef _WIN32
797 WtsApi32_InitializeWtsApi();
798#endif
799
800 if (!g_WtsApi)
801 InitializeWtsApiStubs_FreeRDS();
802
803 return TRUE;
804}