/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 | } |