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