Coverage Report

Created: 2026-03-04 06:17

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