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