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