[MSTSC] Fix parsing of settings. Patch by Stas'M. Thanks. CORE-13223
[reactos.git] / reactos / base / applications / mstsc / settings.c
1
2 #include "precomp.h"
3
4 /* update NUM_SETTINGS in precomp.h */
5 LPWSTR lpSettings[NUM_SETTINGS] =
6 {
7 L"desktopwidth",
8 L"desktopheight",
9 L"session bpp",
10 L"full address",
11 L"username",
12 L"screen mode id",
13 };
14
15 VOID
16 SaveAllSettings(PINFO pInfo)
17 {
18 INT ret;
19 WCHAR szValue[MAXVALUE];
20
21 /* server */
22 if (GetDlgItemText(pInfo->hGeneralPage,
23 IDC_SERVERCOMBO,
24 szValue,
25 MAXVALUE))
26 {
27 SetStringToSettings(pInfo->pRdpSettings,
28 L"full address",
29 szValue);
30 }
31
32 /* resolution and fullscreen*/
33 ret = SendDlgItemMessage(pInfo->hDisplayPage,
34 IDC_GEOSLIDER,
35 TBM_GETPOS,
36 0,
37 0);
38 if (ret != -1)
39 {
40 SetIntegerToSettings(pInfo->pRdpSettings,
41 L"screen mode id",
42 (ret == SendDlgItemMessageW(pInfo->hDisplayPage, IDC_GEOSLIDER, TBM_GETRANGEMAX, 0, 0)) ? 2 : 1);
43 SetIntegerToSettings(pInfo->pRdpSettings,
44 L"desktopwidth",
45 pInfo->DisplayDeviceList->Resolutions[ret].dmPelsWidth);
46 SetIntegerToSettings(pInfo->pRdpSettings,
47 L"desktopheight",
48 pInfo->DisplayDeviceList->Resolutions[ret].dmPelsHeight);
49 }
50
51 /* bpp */
52 ret = SendDlgItemMessage(pInfo->hDisplayPage,
53 IDC_BPPCOMBO,
54 CB_GETCURSEL,
55 0,
56 0);
57 if (ret != CB_ERR)
58 {
59 ret = SendDlgItemMessage(pInfo->hDisplayPage,
60 IDC_BPPCOMBO,
61 CB_GETITEMDATA,
62 ret,
63 0);
64 if (ret != CB_ERR)
65 {
66 SetIntegerToSettings(pInfo->pRdpSettings,
67 L"session bpp",
68 ret);
69 }
70 }
71
72 /* user name */
73 if (GetDlgItemText(pInfo->hGeneralPage,
74 IDC_NAMEEDIT,
75 szValue,
76 MAXVALUE))
77 {
78 SetStringToSettings(pInfo->pRdpSettings,
79 L"username",
80 szValue);
81 }
82 }
83
84
85 BOOL
86 SetIntegerToSettings(PRDPSETTINGS pRdpSettings,
87 LPWSTR lpKey,
88 INT Value)
89 {
90 BOOL bRet = FALSE;
91
92 if (pRdpSettings)
93 {
94 INT i;
95
96 for (i = 0; i < pRdpSettings->NumSettings; i++)
97 {
98 if (wcscmp(pRdpSettings->pSettings[i].Key, lpKey) == 0)
99 {
100 if (pRdpSettings->pSettings[i].Type == 0)
101 pRdpSettings->pSettings[i].Type = L'i';
102
103 pRdpSettings->pSettings[i].Value.i = Value;
104 bRet = TRUE;
105 break;
106 }
107 }
108 }
109
110 return bRet;
111 }
112
113
114 BOOL
115 SetStringToSettings(PRDPSETTINGS pRdpSettings,
116 LPWSTR lpKey,
117 LPWSTR lpValue)
118 {
119 BOOL bRet = FALSE;
120
121 if (pRdpSettings)
122 {
123 INT i;
124
125 for (i = 0; i < pRdpSettings->NumSettings; i++)
126 {
127 if (wcscmp(pRdpSettings->pSettings[i].Key, lpKey) == 0)
128 {
129 if (pRdpSettings->pSettings[i].Type == 0)
130 pRdpSettings->pSettings[i].Type = L's';
131
132 wcscpy(pRdpSettings->pSettings[i].Value.s, lpValue);
133 bRet = TRUE;
134 break;
135 }
136 }
137 }
138
139 return bRet;
140 }
141
142
143 INT
144 GetIntegerFromSettings(PRDPSETTINGS pRdpSettings,
145 LPWSTR lpKey)
146 {
147 INT Value = -1;
148
149 if (pRdpSettings)
150 {
151 INT i;
152
153 for (i = 0; i < pRdpSettings->NumSettings; i++)
154 {
155 if (wcscmp(pRdpSettings->pSettings[i].Key, lpKey) == 0)
156 {
157 if (pRdpSettings->pSettings[i].Type == L'i')
158 {
159 Value = pRdpSettings->pSettings[i].Value.i;
160 break;
161 }
162 }
163 }
164 }
165
166 return Value;
167 }
168
169
170 LPWSTR
171 GetStringFromSettings(PRDPSETTINGS pRdpSettings,
172 LPWSTR lpKey)
173 {
174 LPWSTR lpValue = NULL;
175
176 if (pRdpSettings)
177 {
178 INT i;
179
180 for (i = 0; i < pRdpSettings->NumSettings; i++)
181 {
182 if (wcscmp(pRdpSettings->pSettings[i].Key, lpKey) == 0)
183 {
184 if (pRdpSettings->pSettings[i].Type == L's')
185 {
186 lpValue = pRdpSettings->pSettings[i].Value.s;
187 break;
188 }
189 }
190 }
191 }
192
193 return lpValue;
194 }
195
196
197 static BOOL
198 WriteRdpFile(HANDLE hFile,
199 PRDPSETTINGS pRdpSettings)
200 {
201 WCHAR line[MAXKEY + MAXVALUE + 4];
202 DWORD BytesToWrite, BytesWritten;
203 BOOL bRet;
204 INT i, k;
205
206 for (i = 0; i < pRdpSettings->NumSettings; i++)
207 {
208 /* only write out values in the lpSettings struct */
209 for (k = 0; k < NUM_SETTINGS; k++)
210 {
211 if (wcscmp(lpSettings[k], pRdpSettings->pSettings[i].Key) == 0)
212 {
213 if (pRdpSettings->pSettings[i].Type == L'i')
214 {
215 _snwprintf(line, MAXKEY + MAXVALUE + 4, L"%s:i:%d\r\n",
216 pRdpSettings->pSettings[i].Key,
217 pRdpSettings->pSettings[i].Value.i);
218 }
219 else
220 {
221 _snwprintf(line, MAXKEY + MAXVALUE + 4, L"%s:s:%s\r\n",
222 pRdpSettings->pSettings[i].Key,
223 pRdpSettings->pSettings[i].Value.s);
224 }
225
226 BytesToWrite = wcslen(line) * sizeof(WCHAR);
227
228 bRet = WriteFile(hFile,
229 line,
230 BytesToWrite,
231 &BytesWritten,
232 NULL);
233 if (!bRet || BytesWritten == 0)
234 return FALSE;
235 }
236 }
237 }
238
239 return TRUE;
240 }
241
242
243 static VOID
244 ParseSettings(PRDPSETTINGS pRdpSettings,
245 LPWSTR lpBuffer)
246 {
247 LPWSTR lpStr = lpBuffer;
248 WCHAR szSeps[] = L":\r\n";
249 WCHAR szNewline[] = L"\r\n";
250 LPWSTR lpToken;
251 BOOL bFound;
252 INT i;
253
254 /* move past unicode byte order */
255 if (lpStr[0] == 0xFEFF || lpStr[0] == 0xFFFE)
256 lpStr += 1;
257
258 lpToken = wcstok(lpStr, szSeps);
259 while (lpToken)
260 {
261 bFound = FALSE;
262
263 for (i = 0; i < pRdpSettings->NumSettings && !bFound; i++)
264 {
265 if (wcscmp(lpToken, pRdpSettings->pSettings[i].Key) == 0)
266 {
267 lpToken = wcstok(NULL, szSeps);
268 if (lpToken[0] == L'i')
269 {
270 pRdpSettings->pSettings[i].Type = lpToken[0];
271 lpToken = wcstok(NULL, szSeps);
272 if (lpToken != NULL)
273 pRdpSettings->pSettings[i].Value.i = _wtoi(lpToken);
274 }
275 else if (lpToken[0] == L's')
276 {
277 pRdpSettings->pSettings[i].Type = lpToken[0];
278 if (lpToken[2] == 13 || lpToken[2] == 10 || lpToken[2] == 0)
279 lpToken[0] = 0; // terminate string
280 else
281 lpToken = wcstok(NULL, szNewline);
282 if (lpToken != NULL)
283 wcscpy(pRdpSettings->pSettings[i].Value.s, lpToken);
284 }
285 bFound = TRUE;
286 }
287 }
288
289 /* move past the type and value */
290 if (!bFound)
291 lpToken = wcstok(NULL, szNewline);
292
293 /* move to next key */
294 lpToken = wcstok(NULL, szSeps);
295 }
296 }
297
298
299 static LPWSTR
300 ReadRdpFile(HANDLE hFile)
301 {
302 LPWSTR lpBuffer = NULL;
303 DWORD BytesToRead, BytesRead;
304 BOOL bRes;
305
306 if (hFile)
307 {
308 BytesToRead = GetFileSize(hFile, NULL);
309 if (BytesToRead)
310 {
311 lpBuffer = HeapAlloc(GetProcessHeap(),
312 0,
313 BytesToRead + 2);
314 if (lpBuffer)
315 {
316 bRes = ReadFile(hFile,
317 lpBuffer,
318 BytesToRead,
319 &BytesRead,
320 NULL);
321 if (bRes)
322 {
323 lpBuffer[BytesRead / 2] = 0;
324 }
325 else
326 {
327 HeapFree(GetProcessHeap(),
328 0,
329 lpBuffer);
330
331 lpBuffer = NULL;
332 }
333 }
334 }
335 }
336
337 return lpBuffer;
338 }
339
340
341 static HANDLE
342 OpenRdpFile(LPWSTR path, BOOL bWrite)
343 {
344 HANDLE hFile = NULL;
345
346 if (path)
347 {
348 hFile = CreateFileW(path,
349 bWrite ? GENERIC_WRITE : GENERIC_READ,
350 0,
351 NULL,
352 bWrite ? CREATE_ALWAYS : OPEN_EXISTING,
353 FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN,
354 NULL);
355 }
356
357 return hFile;
358 }
359
360
361 static VOID
362 CloseRdpFile(HANDLE hFile)
363 {
364 if (hFile)
365 CloseHandle(hFile);
366 }
367
368
369 BOOL
370 SaveRdpSettingsToFile(LPWSTR lpFile,
371 PRDPSETTINGS pRdpSettings)
372 {
373 WCHAR pszPath[MAX_PATH];
374 HANDLE hFile;
375 BOOL bRet = FALSE;
376
377 /* use default file */
378 if (lpFile == NULL)
379 {
380 HRESULT hr;
381 LPITEMIDLIST lpidl= NULL;
382
383 hr = SHGetFolderLocation(NULL,
384 CSIDL_PERSONAL,
385 NULL,
386 0,
387 &lpidl);
388 if (hr == S_OK)
389 {
390 if (SHGetPathFromIDListW(lpidl, pszPath))
391 {
392 wcscat(pszPath, L"\\Default.rdp");
393 lpFile = pszPath;
394 CoTaskMemFree(lpidl);
395 }
396 }
397 }
398
399 if (lpFile)
400 {
401 hFile = OpenRdpFile(lpFile, TRUE);
402 if (hFile)
403 {
404 if (WriteRdpFile(hFile, pRdpSettings))
405 {
406 bRet = TRUE;
407 }
408
409 CloseRdpFile(hFile);
410 }
411 }
412
413 return bRet;
414 }
415
416
417 BOOL
418 LoadRdpSettingsFromFile(PRDPSETTINGS pRdpSettings,
419 LPWSTR lpFile)
420 {
421 WCHAR pszPath[MAX_PATH];
422 HANDLE hFile;
423 BOOL bRet = FALSE;
424
425 /* use default file */
426 if (lpFile == NULL)
427 {
428 HRESULT hr;
429 LPITEMIDLIST lpidl= NULL;
430
431 hr = SHGetFolderLocation(NULL,
432 CSIDL_PERSONAL,
433 NULL,
434 0,
435 &lpidl);
436 if (hr == S_OK)
437 {
438 if (SHGetPathFromIDListW(lpidl, pszPath))
439 {
440 wcscat(pszPath, L"\\Default.rdp");
441 lpFile = pszPath;
442 CoTaskMemFree(lpidl);
443 }
444 }
445 }
446
447 if (lpFile)
448 {
449 LPWSTR lpBuffer = NULL;
450
451 hFile = OpenRdpFile(lpFile, FALSE);
452 if (hFile)
453 {
454 lpBuffer = ReadRdpFile(hFile);
455 if (lpBuffer)
456 {
457 ParseSettings(pRdpSettings, lpBuffer);
458
459 HeapFree(GetProcessHeap(),
460 0,
461 lpBuffer);
462
463 bRet = TRUE;
464 }
465
466 CloseRdpFile(hFile);
467 }
468 }
469
470 return bRet;
471 }
472
473
474 BOOL
475 InitRdpSettings(PRDPSETTINGS pRdpSettings)
476 {
477 BOOL bRet = FALSE;
478
479 pRdpSettings->pSettings = HeapAlloc(GetProcessHeap(),
480 0,
481 sizeof(SETTINGS) * NUM_SETTINGS);
482 if (pRdpSettings->pSettings)
483 {
484 INT i;
485
486 for (i = 0; i < NUM_SETTINGS; i++)
487 {
488 wcscpy(pRdpSettings->pSettings[i].Key, lpSettings[i]);
489 pRdpSettings->pSettings[i].Type = (WCHAR)0;
490 pRdpSettings->pSettings[i].Value.i = 0;
491 }
492
493 pRdpSettings->NumSettings = NUM_SETTINGS;
494
495 bRet = TRUE;
496 }
497
498 return bRet;
499 }