FreeRDP
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 
45 static HMODULE g_WtsApiModule = NULL;
46 
47 static const WtsApiFunctionTable* g_WtsApi = NULL;
48 
49 #if defined(_WIN32)
50 static HMODULE g_WtsApi32Module = NULL;
51 static 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 
61 static 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 
142 static BOOL CALLBACK InitializeWtsApiStubs(PINIT_ONCE once, PVOID param, PVOID* context);
143 static 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 
163 BOOL 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 
170 BOOL 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 
177 BOOL 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 
184 BOOL 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 
191 BOOL WINAPI WTSStopRemoteControlSession(ULONG LogonId)
192 {
193  WTSAPI_STUB_CALL_BOOL(StopRemoteControlSession, LogonId);
194 }
195 
196 BOOL WINAPI WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait)
197 {
198  WTSAPI_STUB_CALL_BOOL(ConnectSessionW, LogonId, TargetLogonId, pPassword, bWait);
199 }
200 
201 BOOL WINAPI WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait)
202 {
203  WTSAPI_STUB_CALL_BOOL(ConnectSessionA, LogonId, TargetLogonId, pPassword, bWait);
204 }
205 
206 BOOL 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 
212 BOOL 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 
218 HANDLE WINAPI WTSOpenServerW(LPWSTR pServerName)
219 {
220  WTSAPI_STUB_CALL_HANDLE(OpenServerW, pServerName);
221 }
222 
223 HANDLE WINAPI WTSOpenServerA(LPSTR pServerName)
224 {
225  WTSAPI_STUB_CALL_HANDLE(OpenServerA, pServerName);
226 }
227 
228 HANDLE WINAPI WTSOpenServerExW(LPWSTR pServerName)
229 {
230  WTSAPI_STUB_CALL_HANDLE(OpenServerExW, pServerName);
231 }
232 
233 HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName)
234 {
235  WTSAPI_STUB_CALL_HANDLE(OpenServerExA, pServerName);
236 }
237 
238 VOID WINAPI WTSCloseServer(HANDLE hServer)
239 {
240  WTSAPI_STUB_CALL_VOID(CloseServer, hServer);
241 }
242 
243 BOOL 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 
249 BOOL 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 
255 BOOL 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 
261 BOOL 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 
267 BOOL 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 
273 BOOL 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 
279 BOOL WINAPI WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
280 {
281  WTSAPI_STUB_CALL_BOOL(TerminateProcess, hServer, ProcessId, ExitCode);
282 }
283 
284 BOOL 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 
292 BOOL 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 
300 BOOL 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 
308 BOOL 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 
315 BOOL 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 
322 BOOL 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 
329 BOOL 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 
337 BOOL 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 
345 BOOL WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
346 {
347  WTSAPI_STUB_CALL_BOOL(DisconnectSession, hServer, SessionId, bWait);
348 }
349 
350 BOOL WINAPI WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
351 {
352  WTSAPI_STUB_CALL_BOOL(LogoffSession, hServer, SessionId, bWait);
353 }
354 
355 BOOL WINAPI WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
356 {
357  WTSAPI_STUB_CALL_BOOL(ShutdownSystem, hServer, ShutdownFlag);
358 }
359 
360 BOOL WINAPI WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
361 {
362  WTSAPI_STUB_CALL_BOOL(WaitSystemEvent, hServer, EventMask, pEventFlags);
363 }
364 
365 HANDLE WINAPI WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
366 {
367  WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpen, hServer, SessionId, pVirtualName);
368 }
369 
370 HANDLE WINAPI WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
371 {
372  WTSAPI_STUB_CALL_HANDLE(VirtualChannelOpenEx, SessionId, pVirtualName, flags);
373 }
374 
375 BOOL WINAPI WTSVirtualChannelClose(HANDLE hChannelHandle)
376 {
377  WTSAPI_STUB_CALL_BOOL(VirtualChannelClose, hChannelHandle);
378 }
379 
380 BOOL 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 
387 BOOL WINAPI WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
388  PULONG pBytesWritten)
389 {
390  WTSAPI_STUB_CALL_BOOL(VirtualChannelWrite, hChannelHandle, Buffer, Length, pBytesWritten);
391 }
392 
393 BOOL WINAPI WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
394 {
395  WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeInput, hChannelHandle);
396 }
397 
398 BOOL WINAPI WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
399 {
400  WTSAPI_STUB_CALL_BOOL(VirtualChannelPurgeOutput, hChannelHandle);
401 }
402 
403 BOOL 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 
410 VOID WINAPI WTSFreeMemory(PVOID pMemory)
411 {
412  WTSAPI_STUB_CALL_VOID(FreeMemory, pMemory);
413 }
414 
415 BOOL WINAPI WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
416 {
417  WTSAPI_STUB_CALL_BOOL(FreeMemoryExW, WTSTypeClass, pMemory, NumberOfEntries);
418 }
419 
420 BOOL WINAPI WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
421 {
422  WTSAPI_STUB_CALL_BOOL(FreeMemoryExA, WTSTypeClass, pMemory, NumberOfEntries);
423 }
424 
425 BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
426 {
427  WTSAPI_STUB_CALL_BOOL(RegisterSessionNotification, hWnd, dwFlags);
428 }
429 
430 BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd)
431 {
432  WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotification, hWnd);
433 }
434 
435 BOOL WINAPI WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
436 {
437  WTSAPI_STUB_CALL_BOOL(RegisterSessionNotificationEx, hServer, hWnd, dwFlags);
438 }
439 
440 BOOL WINAPI WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
441 {
442  WTSAPI_STUB_CALL_BOOL(UnRegisterSessionNotificationEx, hServer, hWnd);
443 }
444 
445 BOOL WINAPI WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
446 {
447  WTSAPI_STUB_CALL_BOOL(QueryUserToken, SessionId, phToken);
448 }
449 
450 BOOL 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 
456 BOOL 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 
462 BOOL 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 
468 BOOL 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 
474 BOOL 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 
481 BOOL 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 
488 BOOL 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 
495 BOOL 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 
502 BOOL 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 
510 BOOL 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 
518 BOOL 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 
527 BOOL 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 
536 BOOL CDECL WTSEnableChildSessions(BOOL bEnable)
537 {
538  WTSAPI_STUB_CALL_BOOL(EnableChildSessions, bEnable);
539 }
540 
541 BOOL CDECL WTSIsChildSessionsEnabled(PBOOL pbEnabled)
542 {
543  WTSAPI_STUB_CALL_BOOL(IsChildSessionsEnabled, pbEnabled);
544 }
545 
546 BOOL CDECL WTSGetChildSessionId(PULONG pSessionId)
547 {
548  WTSAPI_STUB_CALL_BOOL(GetChildSessionId, pSessionId);
549 }
550 
551 BOOL CDECL WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
552 {
553  WTSAPI_STUB_CALL_BOOL(LogonUser, hServer, username, password, domain);
554 }
555 
556 BOOL CDECL WTSLogoffUser(HANDLE hServer)
557 {
558  WTSAPI_STUB_CALL_BOOL(LogoffUser, hServer);
559 }
560 
561 #ifndef _WIN32
562 
567 DWORD 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 
579 const 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 
651 const 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 
681 BOOL WTSRegisterWtsApiFunctionTable(const WtsApiFunctionTable* table)
682 {
683  /* Use InitOnceExecuteOnce here as well - otherwise a table set with this
684  function is overriden 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 
698 static 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 
714 static 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 
739 static 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 
781 static 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 }