/src/FreeRDP/libfreerdp/core/settings.c
Line | Count | Source |
1 | | /** |
2 | | * FreeRDP: A Remote Desktop Protocol Implementation |
3 | | * RDP Settings |
4 | | * |
5 | | * Copyright 2009-2011 Jay Sorg |
6 | | * Copyright 2023 Armin Novak <anovak@thincast.com> |
7 | | * Copyright 2023 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 <freerdp/config.h> |
23 | | |
24 | | #include "settings.h" |
25 | | |
26 | | #include <freerdp/crypto/certificate.h> |
27 | | |
28 | | #include <ctype.h> |
29 | | |
30 | | #include <winpr/crt.h> |
31 | | #include <winpr/file.h> |
32 | | #include <winpr/path.h> |
33 | | #include <winpr/sysinfo.h> |
34 | | #if !defined(WITHOUT_FREERDP_3x_DEPRECATED) |
35 | | #include <winpr/registry.h> |
36 | | #endif |
37 | | #include <winpr/wtsapi.h> |
38 | | #include <winpr/input.h> |
39 | | |
40 | | #include <freerdp/version.h> |
41 | | #include <freerdp/settings.h> |
42 | | #include <freerdp/utils/string.h> |
43 | | #include <freerdp/utils/helpers.h> |
44 | | #include <freerdp/build-config.h> |
45 | | |
46 | | #include "../core/utils.h" |
47 | | #include "../crypto/certificate.h" |
48 | | #include "../crypto/privatekey.h" |
49 | | #include "capabilities.h" |
50 | | |
51 | 0 | #define TAG FREERDP_TAG("settings") |
52 | | |
53 | | #ifdef _MSC_VER |
54 | | #pragma warning(push) |
55 | | #pragma warning(disable : 4244) |
56 | | #endif |
57 | | |
58 | | static const char client_dll[] = "C:\\Windows\\System32\\mstscax.dll"; |
59 | | |
60 | 21.4k | #define SERVER_KEY "Software\\%s\\Server" |
61 | 307k | #define CLIENT_KEY "Software\\%s\\Client" |
62 | 76.9k | #define BITMAP_CACHE_KEY CLIENT_KEY "\\BitmapCacheV2" |
63 | 76.9k | #define GLYPH_CACHE_KEY CLIENT_KEY "\\GlyphCache" |
64 | 76.9k | #define POINTER_CACHE_KEY CLIENT_KEY "\\PointerCache" |
65 | | |
66 | | struct bounds_t |
67 | | { |
68 | | INT32 x; |
69 | | INT32 y; |
70 | | INT32 width; |
71 | | INT32 height; |
72 | | }; |
73 | | |
74 | | static const char* bounds2str(const struct bounds_t* bounds, char* buffer, size_t len) |
75 | 0 | { |
76 | 0 | WINPR_ASSERT(bounds); |
77 | 0 | (void)_snprintf(buffer, len, "{%dx%d-%dx%d}", bounds->x, bounds->y, bounds->x + bounds->width, |
78 | 0 | bounds->y + bounds->height); |
79 | 0 | return buffer; |
80 | 0 | } |
81 | | |
82 | | static struct bounds_t union_rect(const struct bounds_t* a, const struct bounds_t* b) |
83 | 0 | { |
84 | 0 | WINPR_ASSERT(a); |
85 | 0 | WINPR_ASSERT(b); |
86 | |
|
87 | 0 | struct bounds_t u = *a; |
88 | 0 | if (b->x < u.x) |
89 | 0 | u.x = b->x; |
90 | 0 | if (b->y < u.y) |
91 | 0 | u.y = b->y; |
92 | |
|
93 | 0 | const INT32 rightA = a->x + a->width; |
94 | 0 | const INT32 rightB = b->x + b->width; |
95 | 0 | const INT32 right = MAX(rightA, rightB); |
96 | 0 | u.width = right - u.x; |
97 | |
|
98 | 0 | const INT32 bottomA = a->y + a->height; |
99 | 0 | const INT32 bottomB = b->y + b->height; |
100 | 0 | const INT32 bottom = MAX(bottomA, bottomB); |
101 | 0 | u.height = bottom - u.y; |
102 | |
|
103 | 0 | return u; |
104 | 0 | } |
105 | | |
106 | | static BOOL intersect_rects(const struct bounds_t* r1, const struct bounds_t* r2) |
107 | 0 | { |
108 | 0 | WINPR_ASSERT(r1); |
109 | 0 | WINPR_ASSERT(r2); |
110 | |
|
111 | 0 | const INT32 left = MAX(r1->x, r2->x); |
112 | 0 | const INT32 top = MAX(r1->y, r2->y); |
113 | 0 | const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width); |
114 | 0 | const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height); |
115 | |
|
116 | 0 | return (left < right) && (top < bottom); |
117 | 0 | } |
118 | | |
119 | | static BOOL align_rects(const struct bounds_t* r1, const struct bounds_t* r2) |
120 | 0 | { |
121 | 0 | WINPR_ASSERT(r1); |
122 | 0 | WINPR_ASSERT(r2); |
123 | |
|
124 | 0 | const INT32 left = MAX(r1->x, r2->x); |
125 | 0 | const INT32 top = MAX(r1->y, r2->y); |
126 | 0 | const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width); |
127 | 0 | const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height); |
128 | |
|
129 | 0 | return (left == right) || (top == bottom); |
130 | 0 | } |
131 | | |
132 | | #if !defined(WITHOUT_FREERDP_3x_DEPRECATED) |
133 | | static BOOL settings_reg_query_dword_val(HKEY hKey, const TCHAR* sub, DWORD* value) |
134 | 0 | { |
135 | 0 | DWORD dwType = 0; |
136 | 0 | DWORD dwSize = 0; |
137 | |
|
138 | 0 | dwSize = sizeof(DWORD); |
139 | 0 | if (RegQueryValueEx(hKey, sub, nullptr, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS) |
140 | 0 | return FALSE; |
141 | 0 | if (dwType != REG_DWORD) |
142 | 0 | return FALSE; |
143 | | |
144 | 0 | return TRUE; |
145 | 0 | } |
146 | | |
147 | | static BOOL settings_reg_query_word_val(HKEY hKey, const TCHAR* sub, UINT16* value) |
148 | 0 | { |
149 | 0 | DWORD dwValue = 0; |
150 | |
|
151 | 0 | if (!settings_reg_query_dword_val(hKey, sub, &dwValue)) |
152 | 0 | return FALSE; |
153 | | |
154 | 0 | if (dwValue > UINT16_MAX) |
155 | 0 | return FALSE; |
156 | | |
157 | 0 | *value = (UINT16)dwValue; |
158 | 0 | return TRUE; |
159 | 0 | } |
160 | | |
161 | | static BOOL settings_reg_query_bool_val(HKEY hKey, const TCHAR* sub, BOOL* value) |
162 | 0 | { |
163 | 0 | DWORD dwValue = 0; |
164 | |
|
165 | 0 | if (!settings_reg_query_dword_val(hKey, sub, &dwValue)) |
166 | 0 | return FALSE; |
167 | 0 | *value = dwValue != 0; |
168 | 0 | return TRUE; |
169 | 0 | } |
170 | | |
171 | | static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32 id, |
172 | | HKEY hKey, const TCHAR* sub) |
173 | 0 | { |
174 | 0 | DWORD dwValue = 0; |
175 | |
|
176 | 0 | if (!settings_reg_query_dword_val(hKey, sub, &dwValue)) |
177 | 0 | return FALSE; |
178 | | |
179 | 0 | return freerdp_settings_set_uint32(settings, id, dwValue); |
180 | 0 | } |
181 | | |
182 | | static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool id, HKEY hKey, |
183 | | const TCHAR* sub) |
184 | 0 | { |
185 | 0 | DWORD dwValue = 0; |
186 | |
|
187 | 0 | if (!settings_reg_query_dword_val(hKey, sub, &dwValue)) |
188 | 0 | return FALSE; |
189 | | |
190 | 0 | return freerdp_settings_set_bool(settings, id, (dwValue != 0)); |
191 | 0 | } |
192 | | #endif |
193 | | |
194 | | static void settings_load_config(rdpSettings* settings, const char* config) |
195 | 76.9k | { |
196 | 76.9k | WINPR_JSON* json = freerdp_GetJSONConfigFile(TRUE, config); |
197 | 76.9k | if (!json) |
198 | 76.9k | return; |
199 | | |
200 | 0 | if (!freerdp_settings_apply_from_json(settings, json)) |
201 | 0 | { |
202 | 0 | WLog_DBG(TAG, "%s could not be applied. File does not exist or is not valid", config); |
203 | 0 | } |
204 | 0 | WINPR_JSON_Delete(json); |
205 | 0 | } |
206 | | |
207 | | static void settings_client_load_hkey_local_machine(rdpSettings* settings) |
208 | 76.9k | { |
209 | 76.9k | const char config[] = "settings-defaults-client.json"; |
210 | 76.9k | #if !defined(WITHOUT_FREERDP_3x_DEPRECATED) |
211 | 76.9k | { |
212 | 76.9k | char* key = freerdp_getApplicatonDetailsRegKey(CLIENT_KEY); |
213 | 76.9k | if (key) |
214 | 76.9k | { |
215 | 76.9k | HKEY hKey = nullptr; |
216 | 76.9k | const LONG status = |
217 | 76.9k | RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); |
218 | 76.9k | free(key); |
219 | | |
220 | 76.9k | if (status == ERROR_SUCCESS) |
221 | 0 | { |
222 | 0 | WLog_WARN(TAG, "HKLM.reg is deprecated since 3.33.0. ATTENTION Use %s instead", |
223 | 0 | config); |
224 | |
|
225 | 0 | settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T("DesktopWidth")); |
226 | 0 | settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey, |
227 | 0 | _T("DesktopHeight")); |
228 | 0 | settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T("Fullscreen")); |
229 | 0 | settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T("ColorDepth")); |
230 | 0 | settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T("KeyboardType")); |
231 | 0 | settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey, |
232 | 0 | _T("KeyboardSubType")); |
233 | 0 | settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey, |
234 | 0 | _T("KeyboardFunctionKeys")); |
235 | 0 | settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey, |
236 | 0 | _T("KeyboardLayout")); |
237 | 0 | settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity")); |
238 | 0 | settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity")); |
239 | 0 | settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity")); |
240 | 0 | settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity")); |
241 | 0 | settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey, |
242 | 0 | _T("MstscCookieMode")); |
243 | 0 | settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey, |
244 | 0 | _T("CookieMaxLength")); |
245 | 0 | settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey, |
246 | 0 | _T("BitmapCache")); |
247 | 0 | settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey, |
248 | 0 | _T("OffscreenBitmapCache")); |
249 | 0 | settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey, |
250 | 0 | _T("OffscreenBitmapCacheSize")); |
251 | 0 | settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey, |
252 | 0 | _T("OffscreenBitmapCacheEntries")); |
253 | 0 | RegCloseKey(hKey); |
254 | 0 | } |
255 | 76.9k | } |
256 | 76.9k | } |
257 | 76.9k | { |
258 | 76.9k | char* key = freerdp_getApplicatonDetailsRegKey(BITMAP_CACHE_KEY); |
259 | 76.9k | if (key) |
260 | 76.9k | { |
261 | 76.9k | HKEY hKey = nullptr; |
262 | 76.9k | const LONG status = |
263 | 76.9k | RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); |
264 | 76.9k | free(key); |
265 | | |
266 | 76.9k | if (status == ERROR_SUCCESS) |
267 | 0 | { |
268 | 0 | settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey, |
269 | 0 | _T("NumCells")); |
270 | 0 | for (unsigned x = 0; x < 5; x++) |
271 | 0 | { |
272 | 0 | DWORD val = 0; |
273 | 0 | TCHAR numentries[64] = WINPR_C_ARRAY_INIT; |
274 | 0 | TCHAR persist[64] = WINPR_C_ARRAY_INIT; |
275 | 0 | BITMAP_CACHE_V2_CELL_INFO cache = WINPR_C_ARRAY_INIT; |
276 | 0 | (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cell%uNumEntries"), x); |
277 | 0 | (void)_sntprintf(persist, ARRAYSIZE(persist), _T("Cell%uPersistent"), x); |
278 | 0 | if (!settings_reg_query_dword_val(hKey, numentries, &val) || |
279 | 0 | !settings_reg_query_bool_val(hKey, persist, &cache.persistent)) |
280 | 0 | continue; |
281 | | |
282 | 0 | if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, |
283 | 0 | x, &cache)) |
284 | 0 | WLog_WARN(TAG, "Failed to load registry keys to settings!"); |
285 | 0 | cache.numEntries = val; |
286 | 0 | } |
287 | |
|
288 | 0 | settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey, |
289 | 0 | _T("AllowCacheWaitingList")); |
290 | 0 | RegCloseKey(hKey); |
291 | 0 | } |
292 | 76.9k | } |
293 | 76.9k | } |
294 | 76.9k | { |
295 | 76.9k | char* key = freerdp_getApplicatonDetailsRegKey(GLYPH_CACHE_KEY); |
296 | 76.9k | if (key) |
297 | 76.9k | { |
298 | 76.9k | HKEY hKey = nullptr; |
299 | 76.9k | const LONG status = |
300 | 76.9k | RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); |
301 | 76.9k | free(key); |
302 | | |
303 | 76.9k | if (status == ERROR_SUCCESS) |
304 | 0 | { |
305 | 0 | unsigned x = 0; |
306 | 0 | UINT32 GlyphSupportLevel = 0; |
307 | 0 | settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey, |
308 | 0 | _T("SupportLevel")); |
309 | 0 | for (; x < 10; x++) |
310 | 0 | { |
311 | 0 | GLYPH_CACHE_DEFINITION cache = WINPR_C_ARRAY_INIT; |
312 | 0 | TCHAR numentries[64] = WINPR_C_ARRAY_INIT; |
313 | 0 | TCHAR maxsize[64] = WINPR_C_ARRAY_INIT; |
314 | 0 | (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cache%uNumEntries"), x); |
315 | 0 | (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T("Cache%uMaxCellSize"), x); |
316 | |
|
317 | 0 | settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries); |
318 | 0 | settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize); |
319 | 0 | if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, |
320 | 0 | &cache)) |
321 | 0 | WLog_WARN(TAG, "Failed to store GlyphCache %u", x); |
322 | 0 | } |
323 | 0 | { |
324 | 0 | GLYPH_CACHE_DEFINITION cache = WINPR_C_ARRAY_INIT; |
325 | 0 | settings_reg_query_word_val(hKey, _T("FragCacheNumEntries"), |
326 | 0 | &cache.cacheEntries); |
327 | 0 | settings_reg_query_word_val(hKey, _T("FragCacheMaxCellSize"), |
328 | 0 | &cache.cacheMaximumCellSize); |
329 | 0 | if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache)) |
330 | 0 | WLog_WARN(TAG, "Failed to store FragCache"); |
331 | 0 | } |
332 | |
|
333 | 0 | RegCloseKey(hKey); |
334 | |
|
335 | 0 | if (!freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, |
336 | 0 | GlyphSupportLevel)) |
337 | 0 | WLog_WARN(TAG, "Failed to load registry keys to settings!"); |
338 | 0 | } |
339 | 76.9k | } |
340 | 76.9k | } |
341 | 76.9k | { |
342 | 76.9k | char* key = freerdp_getApplicatonDetailsRegKey(POINTER_CACHE_KEY); |
343 | 76.9k | if (key) |
344 | 76.9k | { |
345 | 76.9k | HKEY hKey = nullptr; |
346 | 76.9k | const LONG status = |
347 | 76.9k | RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); |
348 | 76.9k | free(key); |
349 | | |
350 | 76.9k | if (status == ERROR_SUCCESS) |
351 | 0 | { |
352 | 0 | settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey, |
353 | 0 | _T("LargePointer")); |
354 | 0 | settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey, |
355 | 0 | _T("PointerCacheSize")); |
356 | 0 | settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey, |
357 | 0 | _T("ColorPointerCacheSize")); |
358 | 0 | RegCloseKey(hKey); |
359 | 0 | } |
360 | 76.9k | } |
361 | 76.9k | } |
362 | 76.9k | #endif |
363 | 76.9k | settings_load_config(settings, config); |
364 | 76.9k | } |
365 | | |
366 | | static void settings_server_load_hkey_local_machine(rdpSettings* settings) |
367 | 21.4k | { |
368 | 21.4k | const char config[] = "settings-defaults-server.json"; |
369 | | |
370 | 21.4k | #if !defined(WITHOUT_FREERDP_3x_DEPRECATED) |
371 | 21.4k | { |
372 | 21.4k | HKEY hKey = nullptr; |
373 | | |
374 | 21.4k | char* key = freerdp_getApplicatonDetailsRegKey(SERVER_KEY); |
375 | 21.4k | if (!key) |
376 | 0 | return; |
377 | | |
378 | 21.4k | const LONG status = |
379 | 21.4k | RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); |
380 | 21.4k | free(key); |
381 | | |
382 | 21.4k | if (status != ERROR_SUCCESS) |
383 | 21.4k | return; |
384 | | |
385 | 0 | WLog_WARN(TAG, "HKLM.reg is deprecated since 3.33.0. ATTENTION Use %s instead", config); |
386 | |
|
387 | 0 | settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity")); |
388 | 0 | settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity")); |
389 | 0 | settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity")); |
390 | 0 | settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T("TlsSecLevel")); |
391 | 0 | settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity")); |
392 | |
|
393 | 0 | RegCloseKey(hKey); |
394 | 0 | } |
395 | 0 | #endif |
396 | | |
397 | 0 | settings_load_config(settings, config); |
398 | 0 | } |
399 | | |
400 | | WINPR_ATTR_NODISCARD |
401 | | static BOOL settings_load_hkey_local_machine(rdpSettings* settings) |
402 | 98.4k | { |
403 | 98.4k | const BOOL server = freerdp_settings_get_bool(settings, FreeRDP_ServerMode); |
404 | 98.4k | if (server) |
405 | 21.4k | settings_server_load_hkey_local_machine(settings); |
406 | 76.9k | else |
407 | 76.9k | settings_client_load_hkey_local_machine(settings); |
408 | | |
409 | 98.4k | const BOOL fail = server != freerdp_settings_get_bool(settings, FreeRDP_ServerMode); |
410 | 98.4k | if (fail) |
411 | 0 | { |
412 | 0 | WLog_ERR(TAG, |
413 | 0 | "default configuration changed FreeRDP_ServerMode! This is not allowed, aborting"); |
414 | 0 | } |
415 | 98.4k | return !fail; |
416 | 98.4k | } |
417 | | |
418 | | static BOOL settings_init_computer_name(rdpSettings* settings) |
419 | 98.4k | { |
420 | 98.4k | CHAR computerName[MAX_COMPUTERNAME_LENGTH + 1] = WINPR_C_ARRAY_INIT; |
421 | 98.4k | DWORD nSize = ARRAYSIZE(computerName); |
422 | | |
423 | 98.4k | if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize)) |
424 | 0 | return FALSE; |
425 | | |
426 | 98.4k | if (!freerdp_settings_set_string(settings, FreeRDP_ComputerName, computerName)) |
427 | 0 | return FALSE; |
428 | 98.4k | return freerdp_settings_set_string(settings, FreeRDP_ClientHostname, computerName); |
429 | 98.4k | } |
430 | | |
431 | | void freerdp_settings_print_warnings(const rdpSettings* settings) |
432 | 0 | { |
433 | 0 | const UINT32 level = freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel); |
434 | 0 | if (level != GLYPH_SUPPORT_NONE) |
435 | 0 | { |
436 | 0 | char buffer[32] = WINPR_C_ARRAY_INIT; |
437 | 0 | WLog_WARN(TAG, "[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!", |
438 | 0 | freerdp_settings_glyph_level_string(level, buffer, sizeof(buffer))); |
439 | 0 | } |
440 | 0 | } |
441 | | |
442 | | static BOOL monitor_operlaps(const rdpSettings* settings, UINT32 orig, UINT32 start, UINT32 count, |
443 | | const rdpMonitor* compare) |
444 | 0 | { |
445 | 0 | const struct bounds_t rect1 = { |
446 | 0 | .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height |
447 | 0 | }; |
448 | 0 | for (UINT32 x = start; x < count; x++) |
449 | 0 | { |
450 | 0 | const rdpMonitor* monitor = |
451 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); |
452 | 0 | const struct bounds_t rect2 = { |
453 | 0 | .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height |
454 | 0 | }; |
455 | |
|
456 | 0 | if (intersect_rects(&rect1, &rect2)) |
457 | 0 | { |
458 | 0 | char buffer1[32] = WINPR_C_ARRAY_INIT; |
459 | 0 | char buffer2[32] = WINPR_C_ARRAY_INIT; |
460 | |
|
461 | 0 | WLog_ERR(TAG, "Monitor %" PRIu32 " and %" PRIu32 " are overlapping:", orig, x); |
462 | 0 | WLog_ERR(TAG, "%s overlapps with %s", bounds2str(&rect1, buffer1, sizeof(buffer1)), |
463 | 0 | bounds2str(&rect2, buffer2, sizeof(buffer2))); |
464 | 0 | WLog_ERR( |
465 | 0 | TAG, |
466 | 0 | "Mulitimonitor mode requested, but local layout has gaps or overlapping areas!"); |
467 | 0 | WLog_ERR(TAG, |
468 | 0 | "Please reconfigure your local monitor setup so that there are no gaps or " |
469 | 0 | "overlapping areas!"); |
470 | 0 | return TRUE; |
471 | 0 | } |
472 | 0 | } |
473 | 0 | return FALSE; |
474 | 0 | } |
475 | | |
476 | | static BOOL monitor_has_gaps(const rdpSettings* settings, UINT32 start, UINT32 count, |
477 | | const rdpMonitor* compare, UINT32** graph) |
478 | 0 | { |
479 | 0 | const struct bounds_t rect1 = { |
480 | 0 | .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height |
481 | 0 | }; |
482 | |
|
483 | 0 | BOOL hasNeighbor = FALSE; |
484 | 0 | for (UINT32 i = 0; i < count; i++) |
485 | 0 | { |
486 | 0 | if (i == start) |
487 | 0 | continue; |
488 | | |
489 | 0 | const rdpMonitor* monitor = |
490 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, i); |
491 | |
|
492 | 0 | const struct bounds_t rect2 = { |
493 | 0 | .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height |
494 | 0 | }; |
495 | 0 | if (align_rects(&rect1, &rect2)) |
496 | 0 | { |
497 | 0 | hasNeighbor = TRUE; |
498 | 0 | graph[start][i] = 1; |
499 | 0 | graph[i][start] = 1; |
500 | 0 | } |
501 | 0 | } |
502 | |
|
503 | 0 | if (!hasNeighbor) |
504 | 0 | { |
505 | 0 | WLog_ERR(TAG, |
506 | 0 | "Monitor configuration has gaps! Monitor %" PRIu32 " does not have any neighbor", |
507 | 0 | start); |
508 | 0 | } |
509 | |
|
510 | 0 | return !hasNeighbor; |
511 | 0 | } |
512 | | |
513 | | static void alloc_free(UINT32** ptr) |
514 | 0 | { |
515 | 0 | free((void*)ptr); |
516 | 0 | } |
517 | | |
518 | | WINPR_ATTR_MALLOC(alloc_free, 1) |
519 | | WINPR_ATTR_NODISCARD |
520 | | static UINT32** alloc_array(size_t count) |
521 | 0 | { |
522 | | // NOLINTNEXTLINE(clang-analyzer-unix.MallocSizeof) |
523 | 0 | BYTE* array = calloc(count * sizeof(uintptr_t), count * sizeof(UINT32)); |
524 | 0 | UINT32** dst = WINPR_PACKED_ALIGN_CAST(UINT32**, array); |
525 | 0 | UINT32* val = WINPR_PACKED_ALIGN_CAST(UINT32*, (array + count * sizeof(uintptr_t))); |
526 | 0 | for (size_t x = 0; x < count; x++) |
527 | 0 | dst[x] = &val[x]; |
528 | |
|
529 | 0 | return dst; |
530 | 0 | } |
531 | | |
532 | | /* Monitors in the array need to: |
533 | | * |
534 | | * 1. be connected to another monitor (edges touch but don't overlap or have gaps) |
535 | | * 2. all monitors need to be connected so there are no separate groups. |
536 | | * |
537 | | * So, what we do here is we use dijkstra algorithm to find a path from any start node |
538 | | * (lazy as we are we always use the first in the array) to each other node. |
539 | | */ |
540 | | static BOOL find_path_exists_with_dijkstra(UINT32** graph, size_t count, UINT32 start) |
541 | 0 | { |
542 | 0 | if (count < 1) |
543 | 0 | return FALSE; |
544 | | |
545 | 0 | WINPR_ASSERT(start < count); |
546 | |
|
547 | 0 | UINT32** cost = alloc_array(count); |
548 | 0 | WINPR_ASSERT(cost); |
549 | |
|
550 | 0 | UINT32* distance = calloc(count, sizeof(UINT32)); |
551 | 0 | WINPR_ASSERT(distance); |
552 | |
|
553 | 0 | UINT32* visited = calloc(count, sizeof(UINT32)); |
554 | 0 | WINPR_ASSERT(visited); |
555 | |
|
556 | 0 | UINT32* parent = calloc(count, sizeof(UINT32)); |
557 | 0 | WINPR_ASSERT(parent); |
558 | |
|
559 | 0 | for (size_t x = 0; x < count; x++) |
560 | 0 | { |
561 | 0 | for (size_t y = 0; y < count; y++) |
562 | 0 | { |
563 | 0 | if (graph[x][y] == 0) |
564 | 0 | cost[x][y] = UINT32_MAX; |
565 | 0 | else |
566 | 0 | cost[x][y] = graph[x][y]; |
567 | 0 | } |
568 | 0 | } |
569 | |
|
570 | 0 | for (UINT32 x = 0; x < count; x++) |
571 | 0 | { |
572 | 0 | distance[x] = cost[start][x]; |
573 | 0 | parent[x] = start; |
574 | 0 | visited[x] = 0; |
575 | 0 | } |
576 | |
|
577 | 0 | distance[start] = 0; |
578 | 0 | visited[start] = 1; |
579 | |
|
580 | 0 | size_t pos = 1; |
581 | 0 | UINT32 nextnode = UINT32_MAX; |
582 | 0 | while (pos < count - 1) |
583 | 0 | { |
584 | 0 | UINT32 mindistance = UINT32_MAX; |
585 | |
|
586 | 0 | for (UINT32 x = 0; x < count; x++) |
587 | 0 | { |
588 | 0 | if ((distance[x] < mindistance) && !visited[x]) |
589 | 0 | { |
590 | 0 | mindistance = distance[x]; |
591 | 0 | nextnode = x; |
592 | 0 | } |
593 | 0 | } |
594 | |
|
595 | 0 | visited[nextnode] = 1; |
596 | |
|
597 | 0 | for (size_t y = 0; y < count; y++) |
598 | 0 | { |
599 | 0 | if (!visited[y]) |
600 | 0 | { |
601 | 0 | UINT32 dist = mindistance + cost[nextnode][y]; |
602 | 0 | if (dist < distance[y]) |
603 | 0 | { |
604 | 0 | distance[y] = dist; |
605 | 0 | parent[y] = nextnode; |
606 | 0 | } |
607 | 0 | } |
608 | 0 | } |
609 | 0 | pos++; |
610 | 0 | } |
611 | |
|
612 | 0 | BOOL rc = TRUE; |
613 | 0 | for (size_t x = 0; x < count; x++) |
614 | 0 | { |
615 | 0 | if (x != start) |
616 | 0 | { |
617 | 0 | if (distance[x] == UINT32_MAX) |
618 | 0 | { |
619 | 0 | WLog_ERR(TAG, "monitor %" PRIu32 " not connected with monitor %" PRIuz, start, x); |
620 | 0 | rc = FALSE; |
621 | 0 | break; |
622 | 0 | } |
623 | 0 | } |
624 | 0 | } |
625 | 0 | alloc_free(cost); |
626 | 0 | free(distance); |
627 | 0 | free(visited); |
628 | 0 | free(parent); |
629 | |
|
630 | 0 | return rc; |
631 | 0 | } |
632 | | |
633 | | static BOOL freerdp_settings_client_monitors_have_gaps(const rdpSettings* settings) |
634 | 0 | { |
635 | 0 | BOOL rc = TRUE; |
636 | 0 | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); |
637 | 0 | if (count <= 1) |
638 | 0 | return FALSE; |
639 | | |
640 | 0 | UINT32** graph = alloc_array(count); |
641 | 0 | WINPR_ASSERT(graph); |
642 | |
|
643 | 0 | for (UINT32 x = 0; x < count; x++) |
644 | 0 | { |
645 | 0 | const rdpMonitor* monitor = |
646 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); |
647 | 0 | if (monitor_has_gaps(settings, x, count, monitor, graph)) |
648 | 0 | goto fail; |
649 | 0 | } |
650 | | |
651 | 0 | rc = !find_path_exists_with_dijkstra(graph, count, 0); |
652 | |
|
653 | 0 | fail: |
654 | 0 | alloc_free(graph); |
655 | |
|
656 | 0 | return rc; |
657 | 0 | } |
658 | | |
659 | | static void log_monitor(UINT32 idx, const rdpMonitor* monitor, wLog* log, DWORD level) |
660 | 0 | { |
661 | 0 | WINPR_ASSERT(monitor); |
662 | |
|
663 | 0 | WLog_Print(log, level, |
664 | 0 | "[%" PRIu32 "] [%s] {%dx%d-%dx%d} [%" PRIu32 "] {%" PRIu32 "x%" PRIu32 |
665 | 0 | ", orientation: %s [%" PRIu32 "], desktopScale: %" PRIu32 ", deviceScale: %" PRIu32 |
666 | 0 | "}", |
667 | 0 | idx, monitor->is_primary ? "primary" : " ", monitor->x, monitor->y, |
668 | 0 | monitor->width, monitor->height, monitor->orig_screen, |
669 | 0 | monitor->attributes.physicalWidth, monitor->attributes.physicalHeight, |
670 | 0 | freerdp_desktop_rotation_flags_to_string(monitor->attributes.orientation), |
671 | 0 | monitor->attributes.orientation, monitor->attributes.desktopScaleFactor, |
672 | 0 | monitor->attributes.deviceScaleFactor); |
673 | 0 | } |
674 | | |
675 | | static void log_monitor_configuration(const rdpSettings* settings, wLog* log, DWORD level) |
676 | 0 | { |
677 | 0 | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); |
678 | 0 | WLog_Print(log, level, "[BEGIN] MonitorDefArray[%" PRIu32 "]", count); |
679 | 0 | for (UINT32 x = 0; x < count; x++) |
680 | 0 | { |
681 | 0 | const rdpMonitor* monitor = |
682 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); |
683 | 0 | log_monitor(x, monitor, log, level); |
684 | 0 | } |
685 | 0 | WLog_Print(log, level, "[END] MonitorDefArray[%" PRIu32 "]", count); |
686 | 0 | } |
687 | | |
688 | | static BOOL freerdp_settings_client_monitors_overlap(const rdpSettings* settings) |
689 | 0 | { |
690 | 0 | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); |
691 | 0 | for (UINT32 x = 0; x < count; x++) |
692 | 0 | { |
693 | 0 | const rdpMonitor* monitor = |
694 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); |
695 | 0 | if (monitor_operlaps(settings, x, x + 1, count, monitor)) |
696 | 0 | return TRUE; |
697 | 0 | } |
698 | 0 | return FALSE; |
699 | 0 | } |
700 | | |
701 | | /* See [MS-RDPBCGR] 2.2.1.3.6.1 for details on limits |
702 | | * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/c3964b39-3d54-4ae1-a84a-ceaed311e0f6 |
703 | | */ |
704 | | static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpSettings* settings) |
705 | 0 | { |
706 | 0 | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); |
707 | 0 | BOOL havePrimary = FALSE; |
708 | 0 | BOOL foundOrigin = FALSE; |
709 | 0 | BOOL primaryIsOrigin = FALSE; |
710 | 0 | BOOL rc = TRUE; |
711 | |
|
712 | 0 | struct bounds_t bounds = WINPR_C_ARRAY_INIT; |
713 | |
|
714 | 0 | if (count == 0) |
715 | 0 | { |
716 | 0 | WLog_WARN(TAG, "Monitor configuration empty."); |
717 | 0 | return TRUE; |
718 | 0 | } |
719 | | |
720 | 0 | for (UINT32 x = 0; x < count; x++) |
721 | 0 | { |
722 | 0 | const rdpMonitor* monitor = |
723 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x); |
724 | 0 | struct bounds_t cur = { |
725 | 0 | .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height |
726 | 0 | }; |
727 | |
|
728 | 0 | bounds = union_rect(&bounds, &cur); |
729 | |
|
730 | 0 | if (monitor->is_primary) |
731 | 0 | { |
732 | 0 | if (havePrimary) |
733 | 0 | { |
734 | 0 | WLog_ERR(TAG, "Monitor configuration contains multiple primary monitors!"); |
735 | 0 | rc = FALSE; |
736 | 0 | } |
737 | 0 | havePrimary = TRUE; |
738 | 0 | } |
739 | |
|
740 | 0 | if ((monitor->x == 0) && (monitor->y == 0)) |
741 | 0 | { |
742 | 0 | if (foundOrigin) |
743 | 0 | { |
744 | 0 | WLog_ERR(TAG, "Monitor configuration does have multiple origin 0/0"); |
745 | 0 | rc = FALSE; |
746 | 0 | } |
747 | 0 | foundOrigin = TRUE; |
748 | 0 | primaryIsOrigin = monitor->is_primary != 0; |
749 | 0 | } |
750 | 0 | } |
751 | |
|
752 | 0 | if ((bounds.width > 32766) || (bounds.width < 200)) |
753 | 0 | { |
754 | 0 | WLog_ERR(TAG, |
755 | 0 | "Monitor configuration virtual desktop width must be 200 <= %" PRId32 " <= 32766", |
756 | 0 | bounds.width); |
757 | 0 | rc = FALSE; |
758 | 0 | } |
759 | 0 | if ((bounds.height > 32766) || (bounds.height < 200)) |
760 | 0 | { |
761 | 0 | WLog_ERR(TAG, |
762 | 0 | "Monitor configuration virtual desktop height must be 200 <= %" PRId32 " <= 32766", |
763 | 0 | bounds.height); |
764 | 0 | rc = FALSE; |
765 | 0 | } |
766 | |
|
767 | 0 | if (!havePrimary) |
768 | 0 | { |
769 | 0 | WLog_ERR(TAG, "Monitor configuration does not contain a primary monitor!"); |
770 | 0 | rc = FALSE; |
771 | 0 | } |
772 | 0 | if (!foundOrigin) |
773 | 0 | { |
774 | 0 | WLog_ERR(TAG, "Monitor configuration must start at 0/0 for first monitor!"); |
775 | 0 | rc = FALSE; |
776 | 0 | } |
777 | 0 | if (!primaryIsOrigin) |
778 | 0 | { |
779 | 0 | WLog_ERR(TAG, "Monitor configuration must start at 0/0 for primary monitor!"); |
780 | 0 | rc = FALSE; |
781 | 0 | } |
782 | |
|
783 | 0 | return rc; |
784 | 0 | } |
785 | | |
786 | | BOOL freerdp_settings_check_client_after_preconnect(const rdpSettings* settings) |
787 | 0 | { |
788 | 0 | wLog* log = WLog_Get(TAG); |
789 | 0 | BOOL rc = TRUE; |
790 | 0 | log_monitor_configuration(settings, log, WLOG_DEBUG); |
791 | 0 | if (freerdp_settings_client_monitors_overlap(settings)) |
792 | 0 | rc = FALSE; |
793 | 0 | if (freerdp_settings_client_monitors_have_gaps(settings)) |
794 | 0 | rc = FALSE; |
795 | 0 | if (!freerdp_settings_client_monitors_check_primary_and_origin(settings)) |
796 | 0 | rc = FALSE; |
797 | 0 | if (!rc) |
798 | 0 | { |
799 | 0 | DWORD level = WLOG_ERROR; |
800 | 0 | WLog_Print(log, level, "Invalid or unsupported monitor configuration detected"); |
801 | 0 | WLog_Print(log, level, "Check if the configuration is valid."); |
802 | 0 | WLog_Print(log, level, |
803 | 0 | "If you suspect a bug create a new issue at " |
804 | 0 | "https://github.com/FreeRDP/FreeRDP/issues/new"); |
805 | 0 | WLog_Print( |
806 | 0 | log, level, |
807 | 0 | "Provide at least the following log lines detailing your monitor configuration:"); |
808 | 0 | log_monitor_configuration(settings, log, level); |
809 | 0 | } |
810 | |
|
811 | 0 | return rc; |
812 | 0 | } |
813 | | |
814 | | BOOL freerdp_settings_set_default_order_support(rdpSettings* settings) |
815 | 98.4k | { |
816 | 98.4k | BYTE* OrderSupport = freerdp_settings_get_pointer_writable(settings, FreeRDP_OrderSupport); |
817 | 98.4k | if (!OrderSupport) |
818 | 0 | return FALSE; |
819 | | |
820 | 98.4k | ZeroMemory(OrderSupport, 32); |
821 | 98.4k | OrderSupport[NEG_DSTBLT_INDEX] = TRUE; |
822 | 98.4k | OrderSupport[NEG_PATBLT_INDEX] = TRUE; |
823 | 98.4k | OrderSupport[NEG_SCRBLT_INDEX] = TRUE; |
824 | 98.4k | OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; |
825 | 98.4k | OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; |
826 | 98.4k | OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; |
827 | 98.4k | OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; |
828 | 98.4k | OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; |
829 | 98.4k | OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; |
830 | 98.4k | OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; |
831 | 98.4k | OrderSupport[NEG_LINETO_INDEX] = TRUE; |
832 | 98.4k | OrderSupport[NEG_POLYLINE_INDEX] = TRUE; |
833 | 98.4k | OrderSupport[NEG_MEMBLT_INDEX] = |
834 | 98.4k | freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0; |
835 | 98.4k | OrderSupport[NEG_MEM3BLT_INDEX] = |
836 | 98.4k | freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0; |
837 | 98.4k | OrderSupport[NEG_MEMBLT_V2_INDEX] = |
838 | 98.4k | freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0; |
839 | 98.4k | OrderSupport[NEG_MEM3BLT_V2_INDEX] = |
840 | 98.4k | freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0; |
841 | 98.4k | OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; |
842 | 98.4k | OrderSupport[NEG_GLYPH_INDEX_INDEX] = |
843 | 98.4k | freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE; |
844 | 98.4k | OrderSupport[NEG_FAST_INDEX_INDEX] = |
845 | 98.4k | freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE; |
846 | 98.4k | OrderSupport[NEG_FAST_GLYPH_INDEX] = |
847 | 98.4k | freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE; |
848 | 98.4k | OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; |
849 | 98.4k | OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; |
850 | 98.4k | OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; |
851 | 98.4k | OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; |
852 | 98.4k | return TRUE; |
853 | 98.4k | } |
854 | | |
855 | | char* freerdp_settings_get_config_path(void) |
856 | 76.9k | { |
857 | 76.9k | return freerdp_GetConfigFilePath(FALSE, ""); |
858 | 76.9k | } |
859 | | |
860 | | rdpSettings* freerdp_settings_new(DWORD flags) |
861 | 98.4k | { |
862 | 98.4k | const BOOL server = ((flags & FREERDP_SETTINGS_SERVER_MODE) != 0); |
863 | 98.4k | const BOOL remote = ((flags & FREERDP_SETTINGS_REMOTE_MODE) != 0); |
864 | 98.4k | rdpSettings* settings = (rdpSettings*)calloc(1, sizeof(rdpSettings)); |
865 | | |
866 | 98.4k | if (!settings) |
867 | 0 | return nullptr; |
868 | | |
869 | 98.4k | { |
870 | 98.4k | const char* vendor = freerdp_getApplicationDetailsVendor(); |
871 | 98.4k | const char* product = freerdp_getApplicationDetailsProduct(); |
872 | 98.4k | const char* details = freerdp_getApplicationDetailsString(); |
873 | 98.4k | char* issuer1 = nullptr; |
874 | 98.4k | char* issuer2 = nullptr; |
875 | 98.4k | char* issuer3 = nullptr; |
876 | 98.4k | size_t len = 0; |
877 | 98.4k | (void)winpr_asprintf(&issuer1, &len, "%s-licenser", freerdp_getApplicationDetailsString()); |
878 | 98.4k | (void)winpr_asprintf(&issuer2, &len, "%s-licenser", freerdp_getApplicationDetailsVendor()); |
879 | 98.4k | (void)winpr_asprintf(&issuer3, &len, "%s-licenser", freerdp_getApplicationDetailsProduct()); |
880 | | |
881 | 98.4k | char* issuers[] = { WINPR_CAST_CONST_PTR_AWAY(vendor, char*), |
882 | 98.4k | WINPR_CAST_CONST_PTR_AWAY(product, char*), |
883 | 98.4k | WINPR_CAST_CONST_PTR_AWAY(details, char*), |
884 | 98.4k | issuer1, |
885 | 98.4k | issuer2, |
886 | 98.4k | issuer3 }; |
887 | | |
888 | 98.4k | const BOOL res = freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers)); |
889 | 98.4k | free(issuer1); |
890 | 98.4k | free(issuer2); |
891 | 98.4k | free(issuer3); |
892 | 98.4k | if (!res) |
893 | 0 | goto out_fail; |
894 | 98.4k | } |
895 | 98.4k | if (!server && !remote) |
896 | 69.8k | { |
897 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpUserAgent, |
898 | 69.8k | FREERDP_USER_AGENT)) |
899 | 0 | goto out_fail; |
900 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpMsUserAgent, |
901 | 69.8k | FREERDP_USER_AGENT)) |
902 | 0 | goto out_fail; |
903 | | |
904 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpReferer, "")) |
905 | 0 | goto out_fail; |
906 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAccessTokenFormat, |
907 | 69.8k | "ms-appx-web%%3a%%2f%%2fMicrosoft.AAD.BrokerPlugin%%2f%s")) |
908 | 0 | goto out_fail; |
909 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAccessAadFormat, |
910 | 69.8k | "https%%3A%%2F%%2F%s%%2F%s%%2Foauth2%%2Fnativeclient")) |
911 | 0 | goto out_fail; |
912 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdScope, |
913 | 69.8k | "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default%20openid%" |
914 | 69.8k | "20profile%20offline_access")) |
915 | | |
916 | 0 | goto out_fail; |
917 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdClientID, |
918 | 69.8k | "a85cf173-4192-42f8-81fa-777a763e6e2c")) |
919 | 0 | goto out_fail; |
920 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAzureActiveDirectory, |
921 | 69.8k | "login.microsoftonline.com")) |
922 | 0 | goto out_fail; |
923 | 69.8k | if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAadtenantid, "common")) |
924 | 0 | goto out_fail; |
925 | 69.8k | if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayAvdUseTenantid, FALSE)) |
926 | 0 | goto out_fail; |
927 | 69.8k | if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopPhysicalWidth, 1000)) |
928 | 0 | goto out_fail; |
929 | 69.8k | if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopPhysicalHeight, 1000)) |
930 | 0 | goto out_fail; |
931 | 69.8k | if (!freerdp_settings_set_uint16(settings, FreeRDP_DesktopOrientation, |
932 | 69.8k | ORIENTATION_LANDSCAPE)) |
933 | 0 | goto out_fail; |
934 | 69.8k | if (!freerdp_settings_set_uint32(settings, FreeRDP_DeviceScaleFactor, 100)) |
935 | 0 | goto out_fail; |
936 | 69.8k | if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopScaleFactor, 100)) |
937 | 0 | goto out_fail; |
938 | 69.8k | } |
939 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_SurfaceCommandsSupported, |
940 | 98.4k | SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS | |
941 | 98.4k | SURFCMDS_FRAME_MARKER)) |
942 | 0 | goto out_fail; |
943 | | |
944 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_RemoteFxRlgrMode, RLGR3)) |
945 | 0 | goto out_fail; |
946 | | |
947 | 98.4k | if (!freerdp_settings_set_uint16(settings, FreeRDP_CapsProtocolVersion, |
948 | 98.4k | TS_CAPS_PROTOCOLVERSION)) |
949 | 0 | goto out_fail; |
950 | | |
951 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_ClipboardFeatureMask, |
952 | 98.4k | CLIPRDR_FLAG_DEFAULT_MASK)) |
953 | 0 | goto out_fail; |
954 | 98.4k | if (!freerdp_settings_set_string(settings, FreeRDP_ServerLicenseCompanyName, |
955 | 98.4k | freerdp_getApplicationDetailsVendor())) |
956 | 0 | goto out_fail; |
957 | | |
958 | 98.4k | { |
959 | 98.4k | size_t len = 0; |
960 | 98.4k | char* val = nullptr; |
961 | 98.4k | (void)winpr_asprintf(&val, &len, "%s-licensing-server", |
962 | 98.4k | freerdp_getApplicationDetailsProduct()); |
963 | 98.4k | if (!val) |
964 | 0 | goto out_fail; |
965 | | |
966 | 98.4k | const BOOL rc = |
967 | 98.4k | freerdp_settings_set_string(settings, FreeRDP_ServerLicenseProductName, val); |
968 | 98.4k | free(val); |
969 | 98.4k | if (!rc) |
970 | 0 | goto out_fail; |
971 | 98.4k | } |
972 | | |
973 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerLicenseProductVersion, 1)) |
974 | 0 | goto out_fail; |
975 | | |
976 | 98.4k | if (!freerdp_settings_set_uint16(settings, FreeRDP_SupportedColorDepths, |
977 | 98.4k | RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | |
978 | 98.4k | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT)) |
979 | 0 | goto out_fail; |
980 | | |
981 | 98.4k | const UINT32 railflags = TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE | |
982 | 98.4k | TS_RAIL_CLIENTSTATUS_ZORDER_SYNC | |
983 | 98.4k | TS_RAIL_CLIENTSTATUS_WINDOW_RESIZE_MARGIN_SUPPORTED | |
984 | 98.4k | TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED | |
985 | 98.4k | TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED | |
986 | 98.4k | TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED; |
987 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppFeatureFlags, railflags)) |
988 | 0 | goto out_fail; |
989 | | |
990 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, TRUE) || |
991 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_HasHorizontalWheel, TRUE) || |
992 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_HasExtendedMouseEvent, TRUE) || |
993 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_HasQoeEvent, TRUE) || |
994 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, TRUE) || |
995 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_HiDefRemoteApp, TRUE) || |
996 | 98.4k | !freerdp_settings_set_uint32( |
997 | 98.4k | settings, FreeRDP_RemoteApplicationSupportMask, |
998 | 98.4k | RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED | |
999 | 98.4k | RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED | |
1000 | 98.4k | RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | |
1001 | 98.4k | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | |
1002 | 98.4k | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) || |
1003 | 98.4k | !freerdp_settings_set_uint16(settings, FreeRDP_TextANSICodePage, CP_UTF8) || |
1004 | 98.4k | !freerdp_settings_set_uint16(settings, FreeRDP_OrderSupportFlags, |
1005 | 98.4k | NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT | |
1006 | 98.4k | COLOR_INDEX_SUPPORT) || |
1007 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SupportHeartbeatPdu, TRUE) || |
1008 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_ServerMode, server) || |
1009 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_WaitForOutputBufferFlush, TRUE) || |
1010 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ClusterInfoFlags, REDIRECTION_SUPPORTED) || |
1011 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1024) || |
1012 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 768) || |
1013 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_Workarea, FALSE) || |
1014 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_Fullscreen, FALSE) || |
1015 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GrabKeyboard, TRUE) || |
1016 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_Decorations, TRUE) || |
1017 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_RdpVersion, RDP_VERSION_10_12) || |
1018 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32) || |
1019 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AadSecurity, FALSE) || |
1020 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_ExtSecurity, TRUE) || |
1021 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE) || |
1022 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE) || |
1023 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE) || |
1024 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE) || |
1025 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_NegotiateSecurityLayer, TRUE) || |
1026 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_RestrictedAdminModeRequired, FALSE) || |
1027 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_RestrictedAdminModeSupported, TRUE) || |
1028 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_MstscCookieMode, FALSE) || |
1029 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_CookieMaxLength, |
1030 | 98.4k | DEFAULT_COOKIE_MAX_LENGTH) || |
1031 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ClientBuild, |
1032 | 98.4k | 18363) || /* Windows 10, Version 1909 */ |
1033 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType, WINPR_KBD_TYPE_IBM_ENHANCED) || |
1034 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 0) || |
1035 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12) || |
1036 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardLayout, 0) || |
1037 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardHook, |
1038 | 98.4k | KEYBOARD_HOOK_FULLSCREEN_ONLY) || |
1039 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE) || |
1040 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SaltedChecksum, TRUE) || |
1041 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, 3389) || |
1042 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_GatewayPort, 443) || |
1043 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DesktopResize, TRUE) || |
1044 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_ToggleFullscreen, TRUE) || |
1045 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosX, UINT32_MAX) || |
1046 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosY, UINT32_MAX) || |
1047 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SoftwareGdi, TRUE) || |
1048 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_UnmapButtons, FALSE) || |
1049 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PERF_FLAG_NONE) || |
1050 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing, TRUE) || |
1051 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition, FALSE) || |
1052 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DisableWallpaper, FALSE) || |
1053 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag, TRUE) || |
1054 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims, TRUE) || |
1055 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DisableThemes, FALSE) || |
1056 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType, |
1057 | 98.4k | CONNECTION_TYPE_AUTODETECT) || |
1058 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect, TRUE) || |
1059 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods, ENCRYPTION_METHOD_NONE) || |
1060 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel, ENCRYPTION_LEVEL_NONE) || |
1061 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_FIPSMode, FALSE) || |
1062 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled, TRUE) || |
1063 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_LogonNotify, TRUE) || |
1064 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_BrushSupportLevel, BRUSH_COLOR_FULL) || |
1065 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_CompressionLevel, PACKET_COMPR_TYPE_RDP61) || |
1066 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_Authentication, TRUE) || |
1067 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AuthenticationOnly, FALSE) || |
1068 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_CredentialsFromStdin, FALSE) || |
1069 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DisableCredentialsDelegation, FALSE) || |
1070 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 2) || |
1071 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, 0) || |
1072 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE) || |
1073 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_KeySpec, AT_KEYEXCHANGE)) |
1074 | 0 | goto out_fail; |
1075 | | |
1076 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ChannelDefArray, nullptr, |
1077 | 98.4k | CHANNEL_MAX_COUNT)) |
1078 | 0 | goto out_fail; |
1079 | | |
1080 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, FALSE)) |
1081 | 0 | goto out_fail; |
1082 | | |
1083 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0)) |
1084 | 0 | goto out_fail; |
1085 | | |
1086 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, nullptr, 32)) |
1087 | 0 | goto out_fail; |
1088 | | |
1089 | 98.4k | if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0)) |
1090 | 0 | goto out_fail; |
1091 | | |
1092 | 98.4k | if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0)) |
1093 | 0 | goto out_fail; |
1094 | | |
1095 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, nullptr, 0)) |
1096 | 0 | goto out_fail; |
1097 | | |
1098 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_MultitransportFlags, |
1099 | 98.4k | TRANSPORT_TYPE_UDP_FECR)) |
1100 | 0 | goto out_fail; |
1101 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMultitransport, TRUE)) |
1102 | 0 | goto out_fail; |
1103 | | |
1104 | 98.4k | if (!settings_init_computer_name(settings)) |
1105 | 0 | goto out_fail; |
1106 | | |
1107 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, nullptr, 1)) |
1108 | 0 | goto out_fail; |
1109 | | |
1110 | 98.4k | if (!freerdp_capability_buffer_resize(settings, 32, FALSE)) |
1111 | 0 | goto out_fail; |
1112 | | |
1113 | 98.4k | { |
1114 | 98.4k | char tmp[32] = WINPR_C_ARRAY_INIT; |
1115 | 98.4k | if (!freerdp_settings_set_string_len(settings, FreeRDP_ClientProductId, tmp, sizeof(tmp))) |
1116 | 0 | goto out_fail; |
1117 | 98.4k | } |
1118 | | |
1119 | | /* [MS-RDPBCGR] 2.2.7.1.5 Pointer Capability Set (TS_POINTER_CAPABILITYSET) |
1120 | | * |
1121 | | * if we are in server mode send a reasonable large cache size, |
1122 | | * if we are in client mode just set the value to the maximum we want to |
1123 | | * support and during capability exchange that size will be limited to the |
1124 | | * sizes the server supports |
1125 | | * |
1126 | | * We have chosen 128 cursors in cache which is at worst 128 * 576kB (384x384 pixel cursor with |
1127 | | * 32bit color depth) |
1128 | | * */ |
1129 | 98.4k | if (freerdp_settings_get_bool(settings, FreeRDP_ServerMode)) |
1130 | 21.4k | { |
1131 | 21.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 25) || |
1132 | 21.4k | !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 25)) |
1133 | 0 | goto out_fail; |
1134 | 21.4k | } |
1135 | 76.9k | else |
1136 | 76.9k | { |
1137 | 76.9k | if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 128) || |
1138 | 76.9k | !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 128)) |
1139 | 0 | goto out_fail; |
1140 | 76.9k | } |
1141 | | |
1142 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_LargePointerFlag, |
1143 | 98.4k | (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) || |
1144 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SoundBeepsEnabled, TRUE) || |
1145 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DrawGdiPlusEnabled, FALSE) || |
1146 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowSkipAlpha, TRUE) || |
1147 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowColorSubsampling, FALSE) || |
1148 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowDynamicColorFidelity, TRUE) || |
1149 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_FrameMarkerCommandEnabled, TRUE) || |
1150 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled, TRUE) || |
1151 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AllowCacheWaitingList, TRUE)) |
1152 | 0 | goto out_fail; |
1153 | | |
1154 | 98.4k | const BITMAP_CACHE_V2_CELL_INFO CellInfo[5] = { |
1155 | 98.4k | { 600, FALSE }, { 600, FALSE }, { 65536, FALSE }, { 4096, FALSE }, { 2048, FALSE } |
1156 | 98.4k | }; |
1157 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_BitmapCacheV2CellInfo, CellInfo, |
1158 | 98.4k | ARRAYSIZE(CellInfo))) |
1159 | 0 | goto out_fail; |
1160 | | |
1161 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_NoBitmapCompressionHeader, TRUE) || |
1162 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, TRUE) || |
1163 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SuppressOutput, TRUE) || |
1164 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GLYPH_SUPPORT_NONE)) |
1165 | 0 | goto out_fail; |
1166 | 98.4k | settings->GlyphCache = calloc(10, sizeof(GLYPH_CACHE_DEFINITION)); |
1167 | | |
1168 | 98.4k | if (!settings->GlyphCache) |
1169 | 0 | goto out_fail; |
1170 | | |
1171 | 98.4k | settings->FragCache = calloc(1, sizeof(GLYPH_CACHE_DEFINITION)); |
1172 | | |
1173 | 98.4k | if (!settings->FragCache) |
1174 | 0 | goto out_fail; |
1175 | | |
1176 | 1.08M | for (size_t x = 0; x < 10; x++) |
1177 | 984k | { |
1178 | 984k | GLYPH_CACHE_DEFINITION cache = WINPR_C_ARRAY_INIT; |
1179 | 984k | cache.cacheEntries = 254; |
1180 | 984k | switch (x) |
1181 | 984k | { |
1182 | 98.4k | case 0: |
1183 | 196k | case 1: |
1184 | 196k | cache.cacheMaximumCellSize = 4; |
1185 | 196k | break; |
1186 | 98.4k | case 2: |
1187 | 196k | case 3: |
1188 | 196k | cache.cacheMaximumCellSize = 8; |
1189 | 196k | break; |
1190 | 98.4k | case 4: |
1191 | 98.4k | cache.cacheMaximumCellSize = 16; |
1192 | 98.4k | break; |
1193 | 98.4k | case 5: |
1194 | 98.4k | cache.cacheMaximumCellSize = 32; |
1195 | 98.4k | break; |
1196 | 98.4k | case 6: |
1197 | 98.4k | cache.cacheMaximumCellSize = 64; |
1198 | 98.4k | break; |
1199 | 98.4k | case 7: |
1200 | 98.4k | cache.cacheMaximumCellSize = 128; |
1201 | 98.4k | break; |
1202 | 98.4k | case 8: |
1203 | 98.4k | cache.cacheMaximumCellSize = 256; |
1204 | 98.4k | break; |
1205 | 98.4k | case 9: |
1206 | 98.4k | cache.cacheMaximumCellSize = 256; |
1207 | 98.4k | break; |
1208 | 0 | default: |
1209 | 0 | goto out_fail; |
1210 | 984k | } |
1211 | | |
1212 | 984k | if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache)) |
1213 | 0 | goto out_fail; |
1214 | 984k | } |
1215 | 98.4k | { |
1216 | 98.4k | GLYPH_CACHE_DEFINITION cache = WINPR_C_ARRAY_INIT; |
1217 | 98.4k | cache.cacheEntries = 256; |
1218 | 98.4k | cache.cacheMaximumCellSize = 256; |
1219 | 98.4k | if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache)) |
1220 | 0 | goto out_fail; |
1221 | 98.4k | } |
1222 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_OffscreenSupportLevel, 0) || |
1223 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheSize, 7680) || |
1224 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheEntries, 2000) || |
1225 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheSize, 2560) || |
1226 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheEntries, 256) || |
1227 | 98.4k | !freerdp_settings_set_string(settings, FreeRDP_ClientDir, client_dll) || |
1228 | 98.4k | !freerdp_settings_get_string(settings, FreeRDP_ClientDir) || |
1229 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_RemoteWndSupportLevel, |
1230 | 98.4k | WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) || |
1231 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCaches, 3) || |
1232 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCacheEntries, 12) || |
1233 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_VCChunkSize, |
1234 | 98.4k | (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH |
1235 | 98.4k | : CHANNEL_CHUNK_LENGTH) || |
1236 | | /* [MS-RDPBCGR] 2.2.7.2.7 Large Pointer Capability Set (TS_LARGE_POINTER_CAPABILITYSET) |
1237 | | requires at least this size */ |
1238 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_MultifragMaxRequestSize, |
1239 | 98.4k | server ? 0 : 608299) || |
1240 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayUseSameCredentials, FALSE) || |
1241 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE) || |
1242 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, TRUE) || |
1243 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE) || |
1244 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayUdpTransport, TRUE) || |
1245 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, TRUE) || |
1246 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpExtAuthSspiNtlm, FALSE) || |
1247 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GatewayArmTransport, FALSE) || |
1248 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_FastPathInput, TRUE) || |
1249 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_FastPathOutput, TRUE) || |
1250 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_LongCredentialsSupported, TRUE) || |
1251 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_FrameAcknowledge, 2) || |
1252 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_MouseMotion, TRUE) || |
1253 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_NSCodecColorLossLevel, 3) || |
1254 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowSubsampling, TRUE) || |
1255 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowDynamicColorFidelity, TRUE) || |
1256 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, FALSE) || |
1257 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_AutoReconnectMaxRetries, 20) || |
1258 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxThinClient, FALSE) || |
1259 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, TRUE) || |
1260 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, FALSE) || |
1261 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, FALSE) || |
1262 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxPlanar, TRUE) || |
1263 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxH264, FALSE) || |
1264 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, FALSE) || |
1265 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxCodecAV1, TRUE) || |
1266 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_GfxCodecAV1Profile, 1) || |
1267 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_GfxSendQoeAck, FALSE) || |
1268 | 98.4k | !freerdp_settings_set_bool(settings, FreeRDP_SupportDisplayControl, TRUE)) |
1269 | 0 | goto out_fail; |
1270 | 98.4k | { |
1271 | 98.4k | ARC_CS_PRIVATE_PACKET cookie = WINPR_C_ARRAY_INIT; |
1272 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ClientAutoReconnectCookie, &cookie, |
1273 | 98.4k | 1)) |
1274 | 0 | goto out_fail; |
1275 | 98.4k | } |
1276 | 98.4k | { |
1277 | 98.4k | ARC_SC_PRIVATE_PACKET cookie = WINPR_C_ARRAY_INIT; |
1278 | 98.4k | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerAutoReconnectCookie, &cookie, |
1279 | 98.4k | 1)) |
1280 | 0 | goto out_fail; |
1281 | 98.4k | } |
1282 | | |
1283 | 98.4k | settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION)calloc(1, sizeof(TIME_ZONE_INFORMATION)); |
1284 | | |
1285 | 98.4k | if (!settings->ClientTimeZone) |
1286 | 0 | goto out_fail; |
1287 | | |
1288 | 98.4k | if (!settings->ServerMode) |
1289 | 76.9k | { |
1290 | 76.9k | DYNAMIC_TIME_ZONE_INFORMATION dynamic = WINPR_C_ARRAY_INIT; |
1291 | 76.9k | TIME_ZONE_INFORMATION* tz = |
1292 | 76.9k | freerdp_settings_get_pointer_writable(settings, FreeRDP_ClientTimeZone); |
1293 | 76.9k | WINPR_ASSERT(tz); |
1294 | | |
1295 | 76.9k | GetTimeZoneInformation(tz); |
1296 | 76.9k | GetDynamicTimeZoneInformation(&dynamic); |
1297 | | |
1298 | 76.9k | if (!freerdp_settings_set_string_from_utf16N(settings, FreeRDP_DynamicDSTTimeZoneKeyName, |
1299 | 76.9k | dynamic.TimeZoneKeyName, |
1300 | 76.9k | ARRAYSIZE(dynamic.TimeZoneKeyName))) |
1301 | 0 | goto out_fail; |
1302 | | |
1303 | 76.9k | if (!freerdp_settings_set_bool(settings, FreeRDP_DynamicDaylightTimeDisabled, |
1304 | 76.9k | dynamic.DynamicDaylightTimeDisabled)) |
1305 | 0 | goto out_fail; |
1306 | 76.9k | } |
1307 | | |
1308 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_TcpKeepAlive, TRUE) || |
1309 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveRetries, 3) || |
1310 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveDelay, 5) || |
1311 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveInterval, 2) || |
1312 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_TcpAckTimeout, 9000) || |
1313 | 98.4k | !freerdp_settings_set_uint32(settings, FreeRDP_TcpConnectTimeout, 15000)) |
1314 | 0 | goto out_fail; |
1315 | | |
1316 | | /* Bound for waiting on a gateway HTTP response (status/header phase and body phase each), |
1317 | | * separate from FreeRDP_TcpConnectTimeout, which only bounds TCP connection establishment. */ |
1318 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayResponseTimeout, 15000)) |
1319 | 0 | goto out_fail; |
1320 | | |
1321 | 98.4k | if (!freerdp_settings_get_bool(settings, FreeRDP_ServerMode)) |
1322 | 76.9k | { |
1323 | 76.9k | BOOL rc = FALSE; |
1324 | 76.9k | char* path = nullptr; |
1325 | 76.9k | if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, TRUE)) |
1326 | 0 | goto out_fail; |
1327 | | /* these values are used only by the client part */ |
1328 | 76.9k | path = GetKnownPath(KNOWN_PATH_HOME); |
1329 | 76.9k | rc = freerdp_settings_set_string(settings, FreeRDP_HomePath, path); |
1330 | 76.9k | free(path); |
1331 | | |
1332 | 76.9k | if (!rc || !freerdp_settings_get_string(settings, FreeRDP_HomePath)) |
1333 | 0 | goto out_fail; |
1334 | | |
1335 | 76.9k | char* config = freerdp_settings_get_config_path(); |
1336 | 76.9k | rc = freerdp_settings_set_string(settings, FreeRDP_ConfigPath, config); |
1337 | 76.9k | if (rc) |
1338 | 76.9k | { |
1339 | 76.9k | char* action = GetCombinedPath(config, "action.sh"); |
1340 | 76.9k | rc = freerdp_settings_set_string(settings, FreeRDP_ActionScript, action); |
1341 | 76.9k | free(action); |
1342 | 76.9k | } |
1343 | | |
1344 | 76.9k | free(config); |
1345 | 76.9k | if (!rc) |
1346 | 0 | goto out_fail; |
1347 | 76.9k | } |
1348 | | |
1349 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_SmartcardLogon, FALSE)) |
1350 | 0 | goto out_fail; |
1351 | 98.4k | if (!freerdp_settings_set_uint32(settings, FreeRDP_TlsSecLevel, FREERDP_TLS_SECLEVEL_112BIT)) |
1352 | 0 | goto out_fail; |
1353 | 98.4k | settings->OrderSupport = calloc(1, 32); |
1354 | | |
1355 | 98.4k | if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion, TLS1_2_VERSION)) |
1356 | 0 | goto out_fail; |
1357 | 98.4k | if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMaxVersion, 0)) |
1358 | 0 | goto out_fail; |
1359 | | |
1360 | 98.4k | if (!settings->OrderSupport) |
1361 | 0 | goto out_fail; |
1362 | | |
1363 | 98.4k | if (!freerdp_settings_set_default_order_support(settings)) |
1364 | 0 | goto out_fail; |
1365 | | |
1366 | 98.4k | { |
1367 | 98.4k | const BOOL enable = freerdp_settings_get_bool(settings, FreeRDP_ServerMode); |
1368 | 98.4k | { |
1369 | 98.4k | const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline, |
1370 | 98.4k | FreeRDP_SupportStatusInfoPdu, |
1371 | 98.4k | FreeRDP_SupportErrorInfoPdu, |
1372 | 98.4k | FreeRDP_SupportAsymetricKeys }; |
1373 | | |
1374 | 492k | for (size_t x = 0; x < ARRAYSIZE(keys); x++) |
1375 | 393k | { |
1376 | 393k | if (!freerdp_settings_set_bool(settings, keys[x], enable)) |
1377 | 0 | goto out_fail; |
1378 | 393k | } |
1379 | 98.4k | } |
1380 | 98.4k | } |
1381 | | |
1382 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDynamicTimeZone, TRUE)) |
1383 | 0 | goto out_fail; |
1384 | 98.4k | if (!freerdp_settings_set_bool(settings, FreeRDP_SupportSkipChannelJoin, TRUE)) |
1385 | 0 | goto out_fail; |
1386 | | |
1387 | 98.4k | UUID corrId = WINPR_C_ARRAY_INIT; |
1388 | 98.4k | if (UuidCreate(&corrId) != RPC_S_OK) |
1389 | 0 | goto out_fail; |
1390 | | |
1391 | 98.4k | char buffer[64] = WINPR_C_ARRAY_INIT; |
1392 | 98.4k | if (!freerdp_settings_set_string(settings, FreeRDP_CorrelationId, |
1393 | 98.4k | guid2str(&corrId, buffer, sizeof(buffer)))) |
1394 | 0 | goto out_fail; |
1395 | | |
1396 | 98.4k | if (!settings_load_hkey_local_machine(settings)) |
1397 | 0 | goto out_fail; |
1398 | | |
1399 | 98.4k | return settings; |
1400 | 0 | out_fail: |
1401 | 0 | WINPR_PRAGMA_DIAG_PUSH |
1402 | 0 | WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC |
1403 | 0 | freerdp_settings_free(settings); |
1404 | 0 | WINPR_PRAGMA_DIAG_POP |
1405 | 0 | return nullptr; |
1406 | 98.4k | } |
1407 | | |
1408 | | static void freerdp_settings_free_internal(rdpSettings* settings) |
1409 | 141k | { |
1410 | 141k | freerdp_server_license_issuers_free(settings); |
1411 | 141k | freerdp_target_net_addresses_free(settings); |
1412 | 141k | freerdp_device_collection_free(settings); |
1413 | 141k | freerdp_static_channel_collection_free(settings); |
1414 | 141k | freerdp_dynamic_channel_collection_free(settings); |
1415 | | |
1416 | 141k | freerdp_capability_buffer_free(settings); |
1417 | | |
1418 | | /* Free all strings, set other pointers nullptr */ |
1419 | 141k | freerdp_settings_free_keys(settings, TRUE); |
1420 | 141k | } |
1421 | | |
1422 | | static void freerdp_settings_free_internal_ensure_reset(rdpSettings* settings) |
1423 | 21.4k | { |
1424 | 21.4k | settings->ServerLicenseProductIssuersCount = 0; |
1425 | 21.4k | settings->ServerLicenseProductIssuers = nullptr; |
1426 | | |
1427 | 21.4k | settings->ReceivedCapabilitiesSize = 0; |
1428 | 21.4k | } |
1429 | | |
1430 | | void freerdp_settings_free(rdpSettings* settings) |
1431 | 162k | { |
1432 | 162k | if (!settings) |
1433 | 42.8k | return; |
1434 | | |
1435 | 119k | freerdp_settings_free_internal(settings); |
1436 | 119k | free(settings); |
1437 | 119k | } |
1438 | | |
1439 | | static BOOL freerdp_settings_int_buffer_copy(rdpSettings* dst, const rdpSettings* settings) |
1440 | 21.4k | { |
1441 | 21.4k | BOOL rc = FALSE; |
1442 | | |
1443 | 21.4k | if (!dst || !settings) |
1444 | 0 | return FALSE; |
1445 | | |
1446 | 21.4k | typedef struct |
1447 | 21.4k | { |
1448 | 21.4k | FreeRDP_Settings_Keys_UInt32 lenKey; |
1449 | 21.4k | FreeRDP_Settings_Keys_Pointer pointerKey; |
1450 | 21.4k | } PointerDefs; |
1451 | | |
1452 | 21.4k | PointerDefs pointerDefs[] = { |
1453 | | /* */ |
1454 | 21.4k | { FreeRDP_LoadBalanceInfoLength, FreeRDP_LoadBalanceInfo }, |
1455 | 21.4k | { FreeRDP_ServerRandomLength, FreeRDP_ServerRandom }, |
1456 | 21.4k | { FreeRDP_ClientRandomLength, FreeRDP_ClientRandom }, |
1457 | 21.4k | { FreeRDP_ServerCertificateLength, FreeRDP_ServerCertificate }, |
1458 | 21.4k | { FreeRDP_ChannelDefArraySize, FreeRDP_ChannelDefArray }, |
1459 | 21.4k | { FreeRDP_NumMonitorIds, FreeRDP_MonitorIds }, |
1460 | 21.4k | { FreeRDP_BitmapCacheV2NumCells, FreeRDP_BitmapCacheV2CellInfo }, |
1461 | 21.4k | { FreeRDP_RedirectionPasswordLength, FreeRDP_RedirectionPassword }, |
1462 | 21.4k | { FreeRDP_RedirectionTsvUrlLength, FreeRDP_RedirectionTsvUrl }, |
1463 | 21.4k | { FreeRDP_RedirectionGuidLength, FreeRDP_RedirectionGuid }, |
1464 | 21.4k | { FreeRDP_MonitorDefArraySize, FreeRDP_MonitorDefArray } |
1465 | 21.4k | }; |
1466 | | |
1467 | 257k | for (size_t i = 0; i < ARRAYSIZE(pointerDefs); i++) |
1468 | 235k | { |
1469 | 235k | const PointerDefs* keys = &pointerDefs[i]; |
1470 | 235k | UINT32 n = freerdp_settings_get_uint32(settings, keys->lenKey); |
1471 | | |
1472 | 235k | const void* ptr = freerdp_settings_get_pointer(settings, keys->pointerKey); |
1473 | 235k | if (!freerdp_settings_set_pointer_len(dst, keys->pointerKey, ptr, n)) |
1474 | 0 | goto out_fail; |
1475 | 235k | } |
1476 | | |
1477 | 21.4k | if (!freerdp_server_license_issuers_copy(dst, settings->ServerLicenseProductIssuers, |
1478 | 21.4k | settings->ServerLicenseProductIssuersCount)) |
1479 | 0 | goto out_fail; |
1480 | | |
1481 | 21.4k | if (settings->RdpServerCertificate) |
1482 | 21.4k | { |
1483 | 21.4k | rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate); |
1484 | 21.4k | if (!cert) |
1485 | 0 | goto out_fail; |
1486 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_RdpServerCertificate, cert, 1)) |
1487 | 0 | { |
1488 | 0 | freerdp_certificate_free(cert); |
1489 | 0 | goto out_fail; |
1490 | 0 | } |
1491 | 21.4k | } |
1492 | 0 | else |
1493 | 0 | { |
1494 | 0 | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_RdpServerCertificate, nullptr, 0)) |
1495 | 0 | goto out_fail; |
1496 | 0 | } |
1497 | | |
1498 | 21.4k | if (settings->RdpServerRsaKey) |
1499 | 0 | { |
1500 | 0 | rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey); |
1501 | 0 | if (!key) |
1502 | 0 | goto out_fail; |
1503 | 0 | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_RdpServerRsaKey, key, 1)) |
1504 | 0 | { |
1505 | 0 | freerdp_key_free(key); |
1506 | 0 | goto out_fail; |
1507 | 0 | } |
1508 | 0 | } |
1509 | 21.4k | else |
1510 | 21.4k | { |
1511 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_RdpServerRsaKey, nullptr, 0)) |
1512 | 0 | goto out_fail; |
1513 | 21.4k | } |
1514 | | |
1515 | 21.4k | if (!freerdp_settings_set_uint32(dst, FreeRDP_ChannelCount, |
1516 | 21.4k | freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount))) |
1517 | 0 | goto out_fail; |
1518 | | |
1519 | 21.4k | if (settings->OrderSupport) |
1520 | 21.4k | { |
1521 | 21.4k | dst->OrderSupport = calloc(32, sizeof(BYTE)); |
1522 | 21.4k | if (!dst->OrderSupport) |
1523 | 0 | goto out_fail; |
1524 | | |
1525 | 21.4k | CopyMemory(dst->OrderSupport, settings->OrderSupport, 32); |
1526 | 21.4k | } |
1527 | | |
1528 | 21.4k | if (!freerdp_capability_buffer_copy(dst, settings)) |
1529 | 0 | goto out_fail; |
1530 | | |
1531 | 21.4k | { |
1532 | 21.4k | const UINT32 glyphCacheCount = 10; |
1533 | 21.4k | const GLYPH_CACHE_DEFINITION* glyphCache = |
1534 | 21.4k | freerdp_settings_get_pointer(settings, FreeRDP_GlyphCache); |
1535 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_GlyphCache, glyphCache, glyphCacheCount)) |
1536 | 0 | goto out_fail; |
1537 | 21.4k | } |
1538 | | |
1539 | 21.4k | { |
1540 | 21.4k | const UINT32 fragCacheCount = 1; |
1541 | 21.4k | const GLYPH_CACHE_DEFINITION* fragCache = |
1542 | 21.4k | freerdp_settings_get_pointer(settings, FreeRDP_FragCache); |
1543 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_FragCache, fragCache, fragCacheCount)) |
1544 | 0 | goto out_fail; |
1545 | 21.4k | } |
1546 | | |
1547 | 21.4k | if (!freerdp_settings_set_pointer_len( |
1548 | 21.4k | dst, FreeRDP_ClientAutoReconnectCookie, |
1549 | 21.4k | freerdp_settings_get_pointer(settings, FreeRDP_ClientAutoReconnectCookie), 1)) |
1550 | 0 | goto out_fail; |
1551 | 21.4k | if (!freerdp_settings_set_pointer_len( |
1552 | 21.4k | dst, FreeRDP_ServerAutoReconnectCookie, |
1553 | 21.4k | freerdp_settings_get_pointer(settings, FreeRDP_ServerAutoReconnectCookie), 1)) |
1554 | 0 | goto out_fail; |
1555 | | |
1556 | 21.4k | { |
1557 | 21.4k | const TIME_ZONE_INFORMATION* tz = |
1558 | 21.4k | freerdp_settings_get_pointer(settings, FreeRDP_ClientTimeZone); |
1559 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_ClientTimeZone, tz, 1)) |
1560 | 0 | goto out_fail; |
1561 | 21.4k | } |
1562 | | |
1563 | 21.4k | { |
1564 | 21.4k | const UINT32 nrports = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount); |
1565 | 21.4k | if (!freerdp_target_net_adresses_reset(dst, nrports)) |
1566 | 0 | goto out_fail; |
1567 | | |
1568 | 21.4k | for (UINT32 i = 0; i < nrports; i++) |
1569 | 0 | { |
1570 | 0 | const char* address = |
1571 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i); |
1572 | 0 | const UINT32* port = |
1573 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i); |
1574 | |
|
1575 | 0 | if (!freerdp_settings_set_pointer_array(dst, FreeRDP_TargetNetAddresses, i, address)) |
1576 | 0 | goto out_fail; |
1577 | 0 | if (!freerdp_settings_set_pointer_array(dst, FreeRDP_TargetNetPorts, i, port)) |
1578 | 0 | goto out_fail; |
1579 | 0 | } |
1580 | 21.4k | } |
1581 | | |
1582 | 21.4k | { |
1583 | 21.4k | const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize); |
1584 | 21.4k | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount); |
1585 | | |
1586 | 21.4k | if (len < count) |
1587 | 0 | goto out_fail; |
1588 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_DeviceArray, nullptr, len)) |
1589 | 0 | goto out_fail; |
1590 | 21.4k | if (!freerdp_settings_set_uint32(dst, FreeRDP_DeviceCount, count)) |
1591 | 0 | goto out_fail; |
1592 | | |
1593 | 21.4k | for (size_t index = 0; index < count; index++) |
1594 | 0 | { |
1595 | 0 | const RDPDR_DEVICE* argv = |
1596 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index); |
1597 | 0 | WINPR_ASSERT(argv); |
1598 | 0 | if (!freerdp_settings_set_pointer_array(dst, FreeRDP_DeviceArray, index, argv)) |
1599 | 0 | goto out_fail; |
1600 | 0 | } |
1601 | 21.4k | WINPR_ASSERT(dst->DeviceArray || (len == 0)); |
1602 | 21.4k | WINPR_ASSERT(len >= count); |
1603 | 21.4k | } |
1604 | 0 | { |
1605 | 21.4k | const UINT32 len = freerdp_settings_get_uint32(dst, FreeRDP_StaticChannelArraySize); |
1606 | 21.4k | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); |
1607 | | |
1608 | 21.4k | if (len < count) |
1609 | 0 | goto out_fail; |
1610 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_StaticChannelArray, nullptr, len)) |
1611 | 0 | goto out_fail; |
1612 | 21.4k | if (!freerdp_settings_set_uint32(dst, FreeRDP_StaticChannelCount, count)) |
1613 | 0 | goto out_fail; |
1614 | | |
1615 | 21.4k | for (size_t index = 0; index < count; index++) |
1616 | 0 | { |
1617 | 0 | const ADDIN_ARGV* argv = |
1618 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index); |
1619 | 0 | WINPR_ASSERT(argv); |
1620 | 0 | if (!freerdp_settings_set_pointer_array(dst, FreeRDP_StaticChannelArray, index, argv)) |
1621 | 0 | goto out_fail; |
1622 | 0 | } |
1623 | 21.4k | } |
1624 | 21.4k | { |
1625 | 21.4k | const UINT32 len = freerdp_settings_get_uint32(dst, FreeRDP_DynamicChannelArraySize); |
1626 | 21.4k | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); |
1627 | | |
1628 | 21.4k | if (len < count) |
1629 | 0 | goto out_fail; |
1630 | 21.4k | if (!freerdp_settings_set_pointer_len(dst, FreeRDP_DynamicChannelArray, nullptr, len)) |
1631 | 0 | goto out_fail; |
1632 | 21.4k | if (!freerdp_settings_set_uint32(dst, FreeRDP_DynamicChannelCount, count)) |
1633 | 0 | goto out_fail; |
1634 | | |
1635 | 21.4k | for (size_t index = 0; index < count; index++) |
1636 | 0 | { |
1637 | 0 | const ADDIN_ARGV* argv = |
1638 | 0 | freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index); |
1639 | 0 | WINPR_ASSERT(argv); |
1640 | 0 | if (!freerdp_settings_set_pointer_array(dst, FreeRDP_DynamicChannelArray, index, argv)) |
1641 | 0 | goto out_fail; |
1642 | 0 | } |
1643 | 21.4k | } |
1644 | | |
1645 | 21.4k | rc = freerdp_settings_set_string(dst, FreeRDP_ActionScript, |
1646 | 21.4k | freerdp_settings_get_string(settings, FreeRDP_ActionScript)); |
1647 | | |
1648 | 21.4k | out_fail: |
1649 | 21.4k | return rc; |
1650 | 21.4k | } |
1651 | | |
1652 | | BOOL freerdp_settings_copy(rdpSettings* dst, const rdpSettings* src) |
1653 | 21.4k | { |
1654 | 21.4k | BOOL rc = 0; |
1655 | | |
1656 | 21.4k | if (!dst || !src) |
1657 | 0 | return FALSE; |
1658 | | |
1659 | | /* This is required to free all non string buffers */ |
1660 | 21.4k | freerdp_settings_free_internal(dst); |
1661 | | |
1662 | | /* This copies everything except allocated non string buffers. reset all allocated buffers to |
1663 | | * nullptr to fix issues during cleanup */ |
1664 | 21.4k | rc = freerdp_settings_clone_keys(dst, src); |
1665 | 21.4k | if (!rc) |
1666 | 0 | goto out_fail; |
1667 | 21.4k | freerdp_settings_free_internal_ensure_reset(dst); |
1668 | | |
1669 | | /* Begin copying */ |
1670 | 21.4k | if (!freerdp_settings_int_buffer_copy(dst, src)) |
1671 | 0 | goto out_fail; |
1672 | 21.4k | return TRUE; |
1673 | 0 | out_fail: |
1674 | 0 | freerdp_settings_free_internal(dst); |
1675 | 0 | return FALSE; |
1676 | 21.4k | } |
1677 | | |
1678 | | rdpSettings* freerdp_settings_clone(const rdpSettings* settings) |
1679 | 21.4k | { |
1680 | 21.4k | rdpSettings* dst = (rdpSettings*)calloc(1, sizeof(rdpSettings)); |
1681 | | |
1682 | 21.4k | if (!freerdp_settings_copy(dst, settings)) |
1683 | 0 | goto out_fail; |
1684 | | |
1685 | 21.4k | return dst; |
1686 | 0 | out_fail: |
1687 | 0 | WINPR_PRAGMA_DIAG_PUSH |
1688 | 0 | WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC |
1689 | 0 | freerdp_settings_free(dst); |
1690 | 0 | WINPR_PRAGMA_DIAG_POP |
1691 | 0 | return nullptr; |
1692 | 21.4k | } |
1693 | | #ifdef _MSC_VER |
1694 | | #pragma warning(pop) |
1695 | | #endif |
1696 | | |
1697 | | BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity, |
1698 | | const rdpSettings* settings, |
1699 | | FreeRDP_Settings_Keys_String UserId, |
1700 | | FreeRDP_Settings_Keys_String DomainId, |
1701 | | const WCHAR* Password, size_t pwdLen) |
1702 | 0 | { |
1703 | 0 | WINPR_ASSERT(identity); |
1704 | 0 | WINPR_ASSERT(settings); |
1705 | |
|
1706 | 0 | size_t UserLen = 0; |
1707 | 0 | size_t DomainLen = 0; |
1708 | |
|
1709 | 0 | WCHAR* Username = freerdp_settings_get_string_as_utf16(settings, UserId, &UserLen); |
1710 | 0 | WCHAR* Domain = freerdp_settings_get_string_as_utf16(settings, DomainId, &DomainLen); |
1711 | |
|
1712 | 0 | const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen, |
1713 | 0 | Password, pwdLen); |
1714 | 0 | winpr_znfree(Username, UserLen * sizeof(WCHAR)); |
1715 | 0 | winpr_znfree(Domain, DomainLen * sizeof(WCHAR)); |
1716 | 0 | return (rc >= 0); |
1717 | 0 | } |
1718 | | |
1719 | | BOOL identity_set_from_settings(SEC_WINNT_AUTH_IDENTITY_W* identity, const rdpSettings* settings, |
1720 | | FreeRDP_Settings_Keys_String UserId, |
1721 | | FreeRDP_Settings_Keys_String DomainId, |
1722 | | FreeRDP_Settings_Keys_String PwdId) |
1723 | 0 | { |
1724 | 0 | WINPR_ASSERT(identity); |
1725 | 0 | WINPR_ASSERT(settings); |
1726 | |
|
1727 | 0 | size_t PwdLen = 0; |
1728 | |
|
1729 | 0 | WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, PwdId, &PwdLen); |
1730 | |
|
1731 | 0 | const BOOL rc = |
1732 | 0 | identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen); |
1733 | 0 | winpr_znfree(Password, PwdLen * sizeof(WCHAR)); |
1734 | 0 | return rc; |
1735 | 0 | } |
1736 | | |
1737 | | BOOL identity_set_from_smartcard_hash(SEC_WINNT_AUTH_IDENTITY_W* identity, |
1738 | | const rdpSettings* settings, |
1739 | | FreeRDP_Settings_Keys_String userId, |
1740 | | FreeRDP_Settings_Keys_String domainId, |
1741 | | FreeRDP_Settings_Keys_String pwdId, |
1742 | | WINPR_ATTR_UNUSED const BYTE* certSha1, |
1743 | | WINPR_ATTR_UNUSED size_t sha1len) |
1744 | 0 | { |
1745 | | #ifdef _WIN32 |
1746 | | CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), WINPR_C_ARRAY_INIT }; |
1747 | | LPWSTR marshalledCredentials = nullptr; |
1748 | | |
1749 | | memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len, sizeof(certInfo.rgbHashOfCert))); |
1750 | | |
1751 | | if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials)) |
1752 | | { |
1753 | | WLog_ERR(TAG, "error marshalling cert credentials"); |
1754 | | return FALSE; |
1755 | | } |
1756 | | |
1757 | | size_t pwdLen = 0; |
1758 | | WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, pwdId, &pwdLen); |
1759 | | const int rc = sspi_SetAuthIdentityWithLengthW(identity, marshalledCredentials, |
1760 | | _wcslen(marshalledCredentials), nullptr, 0, |
1761 | | Password, pwdLen); |
1762 | | winpr_znfree(Password, pwdLen * sizeof(WCHAR)); |
1763 | | CredFree(marshalledCredentials); |
1764 | | return (rc >= 0); |
1765 | | #else |
1766 | 0 | return identity_set_from_settings(identity, settings, userId, domainId, pwdId); |
1767 | 0 | #endif /* _WIN32 */ |
1768 | 0 | } |
1769 | | |
1770 | | const char* freerdp_settings_glyph_level_string(UINT32 level, char* buffer, size_t size) |
1771 | 0 | { |
1772 | 0 | const char* str = "GLYPH_SUPPORT_UNKNOWN"; |
1773 | 0 | switch (level) |
1774 | 0 | { |
1775 | 0 | case GLYPH_SUPPORT_NONE: |
1776 | 0 | str = "GLYPH_SUPPORT_NONE"; |
1777 | 0 | break; |
1778 | 0 | case GLYPH_SUPPORT_PARTIAL: |
1779 | 0 | str = "GLYPH_SUPPORT_PARTIAL"; |
1780 | 0 | break; |
1781 | 0 | case GLYPH_SUPPORT_FULL: |
1782 | 0 | str = "GLYPH_SUPPORT_FULL"; |
1783 | 0 | break; |
1784 | 0 | case GLYPH_SUPPORT_ENCODE: |
1785 | 0 | str = "GLYPH_SUPPORT_ENCODE"; |
1786 | 0 | break; |
1787 | 0 | default: |
1788 | 0 | break; |
1789 | 0 | } |
1790 | | |
1791 | 0 | (void)_snprintf(buffer, size, "%s[0x%08" PRIx32 "]", str, level); |
1792 | 0 | return buffer; |
1793 | 0 | } |
1794 | | |
1795 | | BOOL freerdp_target_net_adresses_reset(rdpSettings* settings, size_t size) |
1796 | 21.4k | { |
1797 | 21.4k | freerdp_target_net_addresses_free(settings); |
1798 | | |
1799 | 21.4k | return freerdp_target_net_addresses_resize(settings, size); |
1800 | 21.4k | } |
1801 | | |
1802 | | BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings) |
1803 | 0 | { |
1804 | 0 | const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); |
1805 | 0 | const BOOL fullscreen = freerdp_settings_get_bool(settings, FreeRDP_Fullscreen); |
1806 | 0 | const BOOL multimon = freerdp_settings_get_bool(settings, FreeRDP_UseMultimon); |
1807 | 0 | const BOOL useMonitors = fullscreen || multimon; |
1808 | |
|
1809 | 0 | const UINT32 size = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize); |
1810 | 0 | if (size == 0) |
1811 | 0 | { |
1812 | 0 | if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, nullptr, 16)) |
1813 | 0 | return FALSE; |
1814 | 0 | } |
1815 | | |
1816 | 0 | if (!useMonitors || (count == 0)) |
1817 | 0 | { |
1818 | 0 | const UINT32 width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth); |
1819 | 0 | const UINT32 height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight); |
1820 | 0 | const UINT32 pwidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalWidth); |
1821 | 0 | const UINT32 pheight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalHeight); |
1822 | 0 | const UINT16 orientation = |
1823 | 0 | freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation); |
1824 | 0 | const UINT32 desktopScaleFactor = |
1825 | 0 | freerdp_settings_get_uint32(settings, FreeRDP_DeviceScaleFactor); |
1826 | 0 | const UINT32 deviceScaleFactor = |
1827 | 0 | freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor); |
1828 | |
|
1829 | 0 | if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1)) |
1830 | 0 | return FALSE; |
1831 | | |
1832 | 0 | rdpMonitor monitor = WINPR_C_ARRAY_INIT; |
1833 | 0 | monitor.x = 0; |
1834 | 0 | monitor.y = 0; |
1835 | 0 | monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width); |
1836 | 0 | monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height); |
1837 | 0 | monitor.is_primary = TRUE; |
1838 | 0 | monitor.orig_screen = 0; |
1839 | 0 | monitor.attributes.physicalWidth = pwidth; |
1840 | 0 | monitor.attributes.physicalHeight = pheight; |
1841 | 0 | monitor.attributes.orientation = orientation; |
1842 | 0 | monitor.attributes.desktopScaleFactor = desktopScaleFactor; |
1843 | 0 | monitor.attributes.deviceScaleFactor = deviceScaleFactor; |
1844 | 0 | if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1)) |
1845 | 0 | return FALSE; |
1846 | 0 | } |
1847 | | |
1848 | 0 | return TRUE; |
1849 | 0 | } |
1850 | | |
1851 | | void freerdp_settings_sanitize_keyboard_type(wLog* log, rdpSettings* settings, const char* source) |
1852 | 3.35k | { |
1853 | 3.35k | WINPR_ASSERT(settings); |
1854 | | |
1855 | 3.35k | switch (settings->KeyboardType) |
1856 | 3.35k | { |
1857 | 1 | case WINPR_KBD_TYPE_IBM_PC_XT: |
1858 | 3 | case WINPR_KBD_TYPE_OLIVETTI_ICO: |
1859 | 15 | case WINPR_KBD_TYPE_IBM_PC_AT: |
1860 | 16 | case WINPR_KBD_TYPE_IBM_ENHANCED: |
1861 | 16 | case WINPR_KBD_TYPE_NOKIA_1050: |
1862 | 16 | case WINPR_KBD_TYPE_NOKIA_9140: |
1863 | 16 | case WINPR_KBD_TYPE_JAPANESE: |
1864 | 21 | case WINPR_KBD_TYPE_KOREAN: |
1865 | 21 | return; |
1866 | 3.33k | default: |
1867 | 3.33k | break; |
1868 | 3.35k | } |
1869 | | |
1870 | 3.33k | if (!log) |
1871 | 0 | log = WLog_Get(TAG); |
1872 | 3.33k | WLog_Print(log, WLOG_WARN, |
1873 | 3.33k | "%s: KeyboardType=0x%08" PRIx32 |
1874 | 3.33k | " is not a known WINPR_KBD_TYPE, using WINPR_KBD_TYPE_IBM_ENHANCED instead", |
1875 | 3.33k | source ? source : "settings", settings->KeyboardType); |
1876 | 3.33k | settings->KeyboardType = WINPR_KBD_TYPE_IBM_ENHANCED; |
1877 | 3.33k | } |
1878 | | |
1879 | | BOOL freerdp_settings_enforce_consistency(rdpSettings* settings) |
1880 | 0 | { |
1881 | 0 | if (freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheV3Enabled)) |
1882 | 0 | { |
1883 | 0 | settings->OrderSupportFlagsEx |= CACHE_BITMAP_V3_SUPPORT; |
1884 | 0 | settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT; |
1885 | 0 | } |
1886 | |
|
1887 | 0 | if (settings->FrameMarkerCommandEnabled) |
1888 | 0 | { |
1889 | 0 | settings->OrderSupportFlagsEx |= ALTSEC_FRAME_MARKER_SUPPORT; |
1890 | 0 | settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT; |
1891 | 0 | } |
1892 | 0 | return TRUE; |
1893 | 0 | } |