1 /*
2    rdesktop: A Remote Desktop Protocol client.
3    Connection settings dialog
4    Copyright (C) Ged Murphy 2007
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "precomp.h"
22 
23 #include <winreg.h>
24 #include <commdlg.h>
25 
26 #define MAX_KEY_NAME 255
27 
28 HINSTANCE hInst;
29 
30 static VOID ReLoadGeneralPage(PINFO pInfo);
31 static VOID ReLoadDisplayPage(PINFO pInfo);
32 
33 static VOID
34 DoOpenFile(PINFO pInfo)
35 {
36     OPENFILENAMEW ofn;
37     WCHAR szFileName[MAX_PATH] = L"Default.rdp";
38     static WCHAR szFilter[] = L"Remote Desktop Files (*.RDP)\0*.rdp\0";
39 
40     ZeroMemory(&ofn, sizeof(ofn));
41     ofn.lStructSize   = sizeof(OPENFILENAMEW);
42     ofn.hwndOwner     = pInfo->hGeneralPage;
43     ofn.nMaxFile      = MAX_PATH;
44     ofn.nMaxFileTitle = MAX_PATH;
45     ofn.lpstrDefExt   = L"RDP";
46     ofn.lpstrFilter   = szFilter;
47     ofn.lpstrFile     = szFileName;
48     ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST;
49 
50     if (GetOpenFileNameW(&ofn))
51     {
52         LoadRdpSettingsFromFile(pInfo->pRdpSettings, szFileName);
53         ReLoadGeneralPage(pInfo);
54         ReLoadDisplayPage(pInfo);
55     }
56 }
57 
58 
59 static VOID
60 DoSaveAs(PINFO pInfo)
61 {
62     OPENFILENAMEW ofn;
63     WCHAR szFileName[MAX_PATH] = L"Default.rdp";
64     static WCHAR szFilter[] = L"Remote Desktop Files (*.RDP)\0*.rdp\0";
65 
66     ZeroMemory(&ofn, sizeof(ofn));
67     ofn.lStructSize   = sizeof(OPENFILENAMEW);
68     ofn.hwndOwner     = pInfo->hGeneralPage;
69     ofn.nMaxFile      = MAX_PATH;
70     ofn.nMaxFileTitle = MAX_PATH;
71     ofn.lpstrDefExt   = L"RDP";
72     ofn.lpstrFilter   = szFilter;
73     ofn.lpstrFile     = szFileName;
74     ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
75 
76     if (GetSaveFileNameW(&ofn))
77     {
78         SaveAllSettings(pInfo);
79         SaveRdpSettingsToFile(szFileName, pInfo->pRdpSettings);
80     }
81 }
82 
83 
84 static VOID
85 OnTabWndSelChange(PINFO pInfo)
86 {
87     switch (TabCtrl_GetCurSel(pInfo->hTab))
88     {
89         case 0: //General
90             ShowWindow(pInfo->hGeneralPage, SW_SHOW);
91             ShowWindow(pInfo->hDisplayPage, SW_HIDE);
92             BringWindowToTop(pInfo->hGeneralPage);
93             break;
94         case 1: //Display
95             ShowWindow(pInfo->hGeneralPage, SW_HIDE);
96             ShowWindow(pInfo->hDisplayPage, SW_SHOW);
97             BringWindowToTop(pInfo->hDisplayPage);
98             break;
99     }
100 }
101 
102 
103 static VOID
104 LoadUsernameHint(HWND hDlg, INT iCur)
105 {
106     WCHAR szValue[MAXVALUE+1000];
107     WCHAR szName[MAX_KEY_NAME];
108     WCHAR szKeyName[] = L"Software\\Microsoft\\Terminal Server Client\\Servers";
109     PWCHAR lpAddress;
110     HKEY hKey;
111     HKEY hSubKey;
112     LONG lRet = ERROR_SUCCESS;
113     INT iIndex = 0;
114     DWORD dwSize = MAX_KEY_NAME;
115 
116     SendDlgItemMessageW(hDlg, IDC_SERVERCOMBO, CB_GETLBTEXT, (WPARAM)iCur, (LPARAM)szValue);
117 
118     /* remove possible port number */
119     lpAddress = wcstok(szValue, L":");
120 
121     if (lpAddress == NULL)
122         return;
123 
124     if (RegOpenKeyExW(HKEY_CURRENT_USER,
125                       szKeyName,
126                       0,
127                       KEY_READ,
128                       &hKey) == ERROR_SUCCESS)
129     {
130         while (lRet == ERROR_SUCCESS)
131         {
132             dwSize = MAX_KEY_NAME;
133 
134             lRet = RegEnumKeyExW(hKey, iIndex, szName, &dwSize, NULL, NULL, NULL, NULL);
135 
136             if(lRet == ERROR_SUCCESS && wcscmp(szName, lpAddress) == 0)
137             {
138                 if(RegOpenKeyExW(hKey, szName, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
139                     break;
140 
141                 dwSize = MAXVALUE * sizeof(WCHAR);
142 
143                 if(RegQueryValueExW(hKey, L"UsernameHint", 0,  NULL, (LPBYTE)szValue, &dwSize) == ERROR_SUCCESS)
144                 {
145                     SetDlgItemTextW(hDlg, IDC_NAMEEDIT, szValue);
146                 }
147 
148                 RegCloseKey(hSubKey);
149                 break;
150             }
151             iIndex++;
152         }
153         RegCloseKey(hKey);
154     }
155 }
156 
157 
158 static VOID
159 FillServerAddressCombo(PINFO pInfo)
160 {
161     HKEY hKey;
162     WCHAR KeyName[] = L"Software\\Microsoft\\Terminal Server Client\\Default";
163     WCHAR Name[MAX_KEY_NAME];
164     LONG ret = ERROR_SUCCESS;
165     DWORD size;
166     INT i = 0;
167     BOOL found = FALSE;
168 
169     if (RegOpenKeyExW(HKEY_CURRENT_USER,
170                       KeyName,
171                       0,
172                       KEY_READ,
173                       &hKey) == ERROR_SUCCESS)
174     {
175         while (ret == ERROR_SUCCESS)
176         {
177             size = MAX_KEY_NAME;
178             ret = RegEnumValueW(hKey,
179                                 i,
180                                 Name,
181                                 &size,
182                                 NULL,
183                                 NULL,
184                                 NULL,
185                                 NULL);
186             if (ret == ERROR_SUCCESS)
187             {
188                 size = sizeof(Name);
189                 if (RegQueryValueExW(hKey,
190                                      Name,
191                                      0,
192                                      NULL,
193                                      NULL,
194                                      &size) == ERROR_SUCCESS)
195                 {
196                     LPWSTR lpAddress = HeapAlloc(GetProcessHeap(),
197                                                  0,
198                                                  size);
199                     if (lpAddress)
200                     {
201                         if (RegQueryValueExW(hKey,
202                                              Name,
203                                              0,
204                                              NULL,
205                                              (LPBYTE)lpAddress,
206                                              &size) == ERROR_SUCCESS)
207                         {
208                             SendDlgItemMessageW(pInfo->hGeneralPage,
209                                                 IDC_SERVERCOMBO,
210                                                 CB_ADDSTRING,
211                                                 0,
212                                                 (LPARAM)lpAddress);
213                             found = TRUE;
214                         }
215 
216                         HeapFree(GetProcessHeap(),
217                                  0,
218                                  lpAddress);
219                     }
220                 }
221             }
222 
223             i++;
224         }
225         RegCloseKey(hKey);
226     }
227 
228     if (LoadStringW(hInst,
229                     IDS_BROWSESERVER,
230                     Name,
231                     sizeof(Name) / sizeof(WCHAR)))
232     {
233         SendDlgItemMessageW(pInfo->hGeneralPage,
234                             IDC_SERVERCOMBO,
235                             CB_ADDSTRING,
236                             0,
237                             (LPARAM)Name);
238     }
239 
240     if(found)
241     {
242         SendDlgItemMessageW(pInfo->hGeneralPage,
243                             IDC_SERVERCOMBO,
244                             CB_SETCURSEL,
245                             0,
246                             0);
247         LoadUsernameHint(pInfo->hGeneralPage, 0);
248     }
249 
250 }
251 
252 
253 static VOID
254 ReLoadGeneralPage(PINFO pInfo)
255 {
256     LPWSTR lpText;
257 
258     /* add file address */
259     lpText = GetStringFromSettings(pInfo->pRdpSettings,
260                                    L"full address");
261     if (lpText)
262     {
263         SetDlgItemTextW(pInfo->hGeneralPage,
264                         IDC_SERVERCOMBO,
265                         lpText);
266     }
267 
268     /* set user name */
269     lpText = GetStringFromSettings(pInfo->pRdpSettings,
270                                    L"username");
271     if (lpText)
272     {
273         SetDlgItemTextW(pInfo->hGeneralPage,
274                         IDC_NAMEEDIT,
275                         lpText);
276     }
277 }
278 
279 
280 static VOID
281 GeneralOnInit(HWND hwnd,
282               PINFO pInfo)
283 {
284     SetWindowLongPtrW(hwnd,
285                       GWLP_USERDATA,
286                       (LONG_PTR)pInfo);
287 
288     pInfo->hGeneralPage = hwnd;
289 
290     SetWindowPos(pInfo->hGeneralPage,
291                  NULL,
292                  2,
293                  22,
294                  0,
295                  0,
296                  SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
297 
298     pInfo->hLogon = LoadImageW(hInst,
299                                MAKEINTRESOURCEW(IDI_LOGON),
300                                IMAGE_ICON,
301                                32,
302                                32,
303                                LR_DEFAULTCOLOR);
304     if (pInfo->hLogon)
305     {
306         SendDlgItemMessageW(pInfo->hGeneralPage,
307                             IDC_LOGONICON,
308                             STM_SETICON,
309                             (WPARAM)pInfo->hLogon,
310                             0);
311     }
312 
313     pInfo->hConn = LoadImageW(hInst,
314                               MAKEINTRESOURCEW(IDI_CONN),
315                               IMAGE_ICON,
316                               32,
317                               32,
318                               LR_DEFAULTCOLOR);
319     if (pInfo->hConn)
320     {
321         SendDlgItemMessageW(pInfo->hGeneralPage,
322                             IDC_CONNICON,
323                             STM_SETICON,
324                             (WPARAM)pInfo->hConn,
325                             0);
326     }
327 
328     FillServerAddressCombo(pInfo);
329     ReLoadGeneralPage(pInfo);
330 }
331 
332 
333 INT_PTR CALLBACK
334 GeneralDlgProc(HWND hDlg,
335                UINT message,
336                WPARAM wParam,
337                LPARAM lParam)
338 {
339     PINFO pInfo = (PINFO)GetWindowLongPtrW(hDlg,
340                                            GWLP_USERDATA);
341 
342     switch (message)
343     {
344         case WM_INITDIALOG:
345             GeneralOnInit(hDlg, (PINFO)lParam);
346             return TRUE;
347 
348         case WM_COMMAND:
349         {
350             switch(LOWORD(wParam))
351             {
352                 case IDC_SERVERCOMBO:
353                     if (HIWORD(wParam) == CBN_SELCHANGE)
354                     {
355                         INT last, cur;
356 
357                         cur = SendDlgItemMessageW(hDlg,
358                                                   IDC_SERVERCOMBO,
359                                                   CB_GETCURSEL,
360                                                   0,
361                                                   0);
362 
363                         last = SendDlgItemMessageW(hDlg,
364                                                    IDC_SERVERCOMBO,
365                                                    CB_GETCOUNT,
366                                                    0,
367                                                    0);
368                         if ((cur + 1) == last)
369                             MessageBoxW(hDlg, L"SMB is not yet supported", L"RDP error", MB_ICONERROR);
370                         else
371                         {
372                             LoadUsernameHint(hDlg, cur);
373                         }
374                     }
375                     break;
376 
377                 case IDC_SAVE:
378                     SaveAllSettings(pInfo);
379                     SaveRdpSettingsToFile(NULL, pInfo->pRdpSettings);
380                 break;
381 
382                 case IDC_SAVEAS:
383                     DoSaveAs(pInfo);
384                 break;
385 
386                 case IDC_OPEN:
387                     DoOpenFile(pInfo);
388                 break;
389             }
390 
391             break;
392         }
393 
394         case WM_CLOSE:
395         {
396             if (pInfo->hLogon)
397                 DestroyIcon(pInfo->hLogon);
398 
399             if (pInfo->hConn)
400                 DestroyIcon(pInfo->hConn);
401 
402             break;
403         }
404     }
405 
406     return 0;
407 }
408 
409 
410 static PSETTINGS_ENTRY
411 GetPossibleSettings(IN LPCWSTR lpDeviceName,
412                     OUT DWORD* pSettingsCount,
413                     OUT PSETTINGS_ENTRY* CurrentSettings)
414 {
415     DEVMODEW devmode;
416     DWORD NbSettings = 0;
417     DWORD iMode = 0;
418     DWORD dwFlags = 0;
419     PSETTINGS_ENTRY Settings = NULL;
420     HDC hDC;
421     PSETTINGS_ENTRY Current;
422     DWORD bpp, xres, yres, checkbpp;
423 
424     /* Get current settings */
425     *CurrentSettings = NULL;
426     hDC = CreateICW(NULL, lpDeviceName, NULL, NULL);
427     bpp = GetDeviceCaps(hDC, PLANES);
428     bpp *= GetDeviceCaps(hDC, BITSPIXEL);
429     xres = GetDeviceCaps(hDC, HORZRES);
430     yres = GetDeviceCaps(hDC, VERTRES);
431     DeleteDC(hDC);
432 
433     /* List all settings */
434     devmode.dmSize = (WORD)sizeof(DEVMODE);
435     devmode.dmDriverExtra = 0;
436 
437     if (!EnumDisplaySettingsExW(lpDeviceName, ENUM_CURRENT_SETTINGS, &devmode, dwFlags))
438         return NULL;
439 
440     while (EnumDisplaySettingsExW(lpDeviceName, iMode, &devmode, dwFlags))
441     {
442         if (devmode.dmBitsPerPel==8 ||
443             devmode.dmBitsPerPel==16 ||
444             devmode.dmBitsPerPel==24 ||
445             devmode.dmBitsPerPel==32)
446         {
447             checkbpp=1;
448         }
449         else
450             checkbpp=0;
451 
452         if (devmode.dmPelsWidth < 640 ||
453             devmode.dmPelsHeight < 480 || checkbpp == 0)
454         {
455             iMode++;
456             continue;
457         }
458 
459         Current = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_ENTRY));
460         if (Current != NULL)
461         {
462             /* Sort resolutions by increasing height, and BPP */
463             PSETTINGS_ENTRY Previous = NULL;
464             PSETTINGS_ENTRY Next = Settings;
465             Current->dmPelsWidth = devmode.dmPelsWidth;
466             Current->dmPelsHeight = devmode.dmPelsHeight;
467             Current->dmBitsPerPel = devmode.dmBitsPerPel;
468             while (Next != NULL &&
469                    (Next->dmPelsWidth < Current->dmPelsWidth ||
470                     (Next->dmPelsWidth == Current->dmPelsWidth && Next->dmPelsHeight < Current->dmPelsHeight) ||
471                     (Next->dmPelsHeight == Current->dmPelsHeight &&
472                      Next->dmPelsWidth == Current->dmPelsWidth &&
473                      Next->dmBitsPerPel < Current->dmBitsPerPel )))
474             {
475                 Previous = Next;
476                 Next = Next->Flink;
477             }
478             Current->Blink = Previous;
479             Current->Flink = Next;
480             if (Previous == NULL)
481                 Settings = Current;
482             else
483                 Previous->Flink = Current;
484             if (Next != NULL)
485                 Next->Blink = Current;
486             if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
487             {
488                 *CurrentSettings = Current;
489             }
490             NbSettings++;
491         }
492         iMode++;
493     }
494 
495     *pSettingsCount = NbSettings;
496     return Settings;
497 }
498 
499 
500 static BOOL
501 AddDisplayDevice(PINFO pInfo, PDISPLAY_DEVICEW DisplayDevice)
502 {
503     PDISPLAY_DEVICE_ENTRY newEntry = NULL;
504     LPWSTR description = NULL;
505     LPWSTR name = NULL;
506     LPWSTR key = NULL;
507     LPWSTR devid = NULL;
508     SIZE_T descriptionSize, nameSize, keySize, devidSize;
509     PSETTINGS_ENTRY Current;
510     DWORD ResolutionsCount = 1;
511     DWORD i;
512 
513     newEntry = HeapAlloc(GetProcessHeap(),
514                          0,
515                          sizeof(DISPLAY_DEVICE_ENTRY));
516     if (!newEntry) goto ByeBye;
517     ZeroMemory(newEntry, sizeof(DISPLAY_DEVICE_ENTRY));
518 
519     newEntry->Settings = GetPossibleSettings(DisplayDevice->DeviceName,
520                                              &newEntry->SettingsCount,
521                                              &newEntry->CurrentSettings);
522     if (!newEntry->Settings) goto ByeBye;
523 
524     newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
525     newEntry->InitialSettings.dmPelsHeight = newEntry->CurrentSettings->dmPelsHeight;
526     newEntry->InitialSettings.dmBitsPerPel = newEntry->CurrentSettings->dmBitsPerPel;
527 
528     /* Count different resolutions */
529     for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
530     {
531         if (Current->Flink != NULL &&
532             ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
533             (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
534         {
535             ResolutionsCount++;
536         }
537     }
538 
539     newEntry->Resolutions = HeapAlloc(GetProcessHeap(),
540                                       0,
541                                       ResolutionsCount * (sizeof(RESOLUTION_INFO) + 1));
542     if (!newEntry->Resolutions) goto ByeBye;
543 
544     newEntry->ResolutionsCount = ResolutionsCount;
545 
546     /* Fill resolutions infos */
547     for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
548     {
549         if (Current->Flink == NULL ||
550             (Current->Flink != NULL &&
551             ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
552             (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
553         {
554             newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
555             newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
556             i++;
557         }
558     }
559 
560     /* fullscreen */
561     newEntry->Resolutions[i].dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
562     newEntry->Resolutions[i].dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
563 
564     descriptionSize = (wcslen(DisplayDevice->DeviceString) + 1) * sizeof(WCHAR);
565     description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
566     if (!description) goto ByeBye;
567 
568     nameSize = (wcslen(DisplayDevice->DeviceName) + 1) * sizeof(WCHAR);
569     name = HeapAlloc(GetProcessHeap(), 0, nameSize);
570     if (!name) goto ByeBye;
571 
572     keySize = (wcslen(DisplayDevice->DeviceKey) + 1) * sizeof(WCHAR);
573     key = HeapAlloc(GetProcessHeap(), 0, keySize);
574     if (!key) goto ByeBye;
575 
576     devidSize = (wcslen(DisplayDevice->DeviceID) + 1) * sizeof(WCHAR);
577     devid = HeapAlloc(GetProcessHeap(), 0, devidSize);
578     if (!devid) goto ByeBye;
579 
580     memcpy(description, DisplayDevice->DeviceString, descriptionSize);
581     memcpy(name, DisplayDevice->DeviceName, nameSize);
582     memcpy(key, DisplayDevice->DeviceKey, keySize);
583     memcpy(devid, DisplayDevice->DeviceID, devidSize);
584     newEntry->DeviceDescription = description;
585     newEntry->DeviceName = name;
586     newEntry->DeviceKey = key;
587     newEntry->DeviceID = devid;
588     newEntry->DeviceStateFlags = DisplayDevice->StateFlags;
589     newEntry->Flink = pInfo->DisplayDeviceList;
590     pInfo->DisplayDeviceList = newEntry;
591     return TRUE;
592 
593 ByeBye:
594     if (newEntry != NULL)
595     {
596         if (newEntry->Settings != NULL)
597         {
598             Current = newEntry->Settings;
599             while (Current != NULL)
600             {
601                 PSETTINGS_ENTRY Next = Current->Flink;
602                 HeapFree(GetProcessHeap(), 0, Current);
603                 Current = Next;
604             }
605         }
606         if (newEntry->Resolutions != NULL)
607             HeapFree(GetProcessHeap(), 0, newEntry->Resolutions);
608         HeapFree(GetProcessHeap(), 0, newEntry);
609     }
610     if (description != NULL)
611         HeapFree(GetProcessHeap(), 0, description);
612     if (name != NULL)
613         HeapFree(GetProcessHeap(), 0, name);
614     if (key != NULL)
615         HeapFree(GetProcessHeap(), 0, key);
616     if (devid != NULL)
617         HeapFree(GetProcessHeap(), 0, devid);
618     return FALSE;
619 }
620 
621 
622 static VOID
623 OnResolutionChanged(PINFO pInfo, INT position)
624 {
625     WCHAR Buffer[64];
626     INT MaxSlider;
627 
628     MaxSlider = SendDlgItemMessageW(pInfo->hDisplayPage,
629                                     IDC_GEOSLIDER,
630                                     TBM_GETRANGEMAX,
631                                     0,
632                                     0);
633 
634     if (position == MaxSlider)
635     {
636         LoadStringW(hInst,
637                     IDS_FULLSCREEN,
638                     Buffer,
639                     sizeof(Buffer) / sizeof(WCHAR));
640     }
641     else
642     {
643         WCHAR Pixel[64];
644 
645         if (LoadStringW(hInst,
646                         IDS_PIXEL,
647                         Pixel,
648                         sizeof(Pixel) / sizeof(WCHAR)))
649         {
650             swprintf(Buffer,
651                      Pixel,
652                      pInfo->DisplayDeviceList->Resolutions[position].dmPelsWidth,
653                      pInfo->DisplayDeviceList->Resolutions[position].dmPelsHeight,
654                      Pixel);
655         }
656     }
657 
658     SendDlgItemMessageW(pInfo->hDisplayPage,
659                         IDC_SETTINGS_RESOLUTION_TEXT,
660                         WM_SETTEXT,
661                         0,
662                         (LPARAM)Buffer);
663 }
664 
665 
666 static VOID
667 FillResolutionsAndColors(PINFO pInfo)
668 {
669     PSETTINGS_ENTRY Current;
670     DWORD index, i, num;
671     DWORD MaxBpp = 0;
672     UINT types[5];
673 
674     pInfo->CurrentDisplayDevice = pInfo->DisplayDeviceList; /* Update global variable */
675 
676     /* find max bpp */
677     SendDlgItemMessageW(pInfo->hDisplayPage,
678                         IDC_BPPCOMBO,
679                         CB_RESETCONTENT,
680                         0,
681                         0);
682     for (Current = pInfo->DisplayDeviceList->Settings; Current != NULL; Current = Current->Flink)
683     {
684         if (Current->dmBitsPerPel > MaxBpp)
685             MaxBpp = Current->dmBitsPerPel;
686     }
687     switch (MaxBpp)
688     {
689         case 32: num = 4; break;
690         case 24: num = 3; break;
691         case 16: num = 2; break;
692         case 15: num = 1; break;
693         case 8:  num = 0; break;
694         default: num = 0; break;
695     }
696 
697     types[0] = IDS_256COLORS;
698     types[1] = IDS_HIGHCOLOR15;
699     types[2] = IDS_HIGHCOLOR16;
700     types[3] = IDS_HIGHCOLOR24;
701     types[4] = IDS_HIGHCOLOR32;
702 
703     /* Fill color depths combo box */
704     SendDlgItemMessageW(pInfo->hDisplayPage,
705                         IDC_BPPCOMBO,
706                         CB_RESETCONTENT,
707                         0,
708                         0);
709 
710     for (i = 0, Current = pInfo->DisplayDeviceList->Settings;
711          i <= num && Current != NULL;
712          i++, Current = Current->Flink)
713     {
714         WCHAR Buffer[64];
715         if (LoadStringW(hInst,
716                         types[i],
717                         Buffer,
718                         sizeof(Buffer) / sizeof(WCHAR)))
719         {
720             index = (DWORD)SendDlgItemMessageW(pInfo->hDisplayPage,
721                                                IDC_BPPCOMBO,
722                                                CB_FINDSTRINGEXACT,
723                                                (WPARAM)-1,
724                                                (LPARAM)Buffer);
725             if (index == (DWORD)CB_ERR)
726             {
727                 index = (DWORD)SendDlgItemMessageW(pInfo->hDisplayPage,
728                                                    IDC_BPPCOMBO,
729                                                    CB_ADDSTRING,
730                                                    0,
731                                                    (LPARAM)Buffer);
732                 SendDlgItemMessageW(pInfo->hDisplayPage,
733                                     IDC_BPPCOMBO,
734                                     CB_SETITEMDATA,
735                                     index,
736                                     types[i]);
737             }
738         }
739     }
740 
741     /* Fill resolutions slider */
742     SendDlgItemMessageW(pInfo->hDisplayPage,
743                         IDC_GEOSLIDER,
744                         TBM_CLEARTICS,
745                         TRUE,
746                         0);
747     SendDlgItemMessageW(pInfo->hDisplayPage,
748                         IDC_GEOSLIDER,
749                         TBM_SETRANGE,
750                         TRUE,
751                         MAKELONG(0, pInfo->DisplayDeviceList->ResolutionsCount)); //extra 1 for full screen
752 
753 
754 }
755 
756 
757 static VOID
758 ReLoadDisplayPage(PINFO pInfo)
759 {
760     DWORD index;
761     INT width, height, pos = 0;
762     INT bpp, num, i, screenmode;
763     BOOL bSet = FALSE;
764 
765     /* get fullscreen info */
766     screenmode = GetIntegerFromSettings(pInfo->pRdpSettings, L"screen mode id");
767 
768     /* set trackbar position */
769     width = GetIntegerFromSettings(pInfo->pRdpSettings, L"desktopwidth");
770     height = GetIntegerFromSettings(pInfo->pRdpSettings, L"desktopheight");
771 
772     if (width != -1 && height != -1)
773     {
774         if(screenmode == 2)
775         {
776             pos = SendDlgItemMessageW(pInfo->hDisplayPage,
777                                       IDC_GEOSLIDER,
778                                       TBM_GETRANGEMAX,
779                                       0,
780                                       0);
781         }
782         else
783         {
784             for (index = 0; index < pInfo->CurrentDisplayDevice->ResolutionsCount; index++)
785             {
786                 if (pInfo->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == width &&
787                     pInfo->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == height)
788                 {
789                     pos = index;
790                     break;
791                 }
792             }
793         }
794     }
795 
796     /* set slider position */
797     SendDlgItemMessageW(pInfo->hDisplayPage,
798                         IDC_GEOSLIDER,
799                         TBM_SETPOS,
800                         TRUE,
801                         pos);
802 
803     OnResolutionChanged(pInfo, pos);
804 
805 
806      /* set color combo */
807     bpp = GetIntegerFromSettings(pInfo->pRdpSettings, L"session bpp");
808 
809     num = SendDlgItemMessageW(pInfo->hDisplayPage,
810                               IDC_BPPCOMBO,
811                               CB_GETCOUNT,
812                               0,
813                               0);
814     for (i = 0; i < num; i++)
815     {
816         INT data = SendDlgItemMessageW(pInfo->hDisplayPage,
817                                        IDC_BPPCOMBO,
818                                        CB_GETITEMDATA,
819                                        i,
820                                        0);
821         if (data == bpp)
822         {
823             SendDlgItemMessageW(pInfo->hDisplayPage,
824                                 IDC_BPPCOMBO,
825                                 CB_SETCURSEL,
826                                 i,
827                                 0);
828             bSet = TRUE;
829             break;
830         }
831     }
832 
833     if (!bSet)
834     {
835         SendDlgItemMessageW(pInfo->hDisplayPage,
836                             IDC_BPPCOMBO,
837                             CB_SETCURSEL,
838                             num - 1,
839                             0);
840     }
841 }
842 
843 
844 static VOID
845 DisplayOnInit(HWND hwnd,
846               PINFO pInfo)
847 {
848     DISPLAY_DEVICEW displayDevice;
849     DWORD iDevNum = 0;
850     BOOL GotDev = FALSE;
851 
852     SetWindowLongPtrW(hwnd,
853                       GWLP_USERDATA,
854                       (LONG_PTR)pInfo);
855 
856     pInfo->hDisplayPage = hwnd;
857 
858     SetWindowPos(pInfo->hDisplayPage,
859                  NULL,
860                  2,
861                  22,
862                  0,
863                  0,
864                  SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
865 
866         pInfo->hRemote = LoadImageW(hInst,
867                                     MAKEINTRESOURCEW(IDI_REMOTE),
868                                     IMAGE_ICON,
869                                     32,
870                                     32,
871                                     LR_DEFAULTCOLOR);
872         if (pInfo->hRemote)
873         {
874             SendDlgItemMessageW(pInfo->hDisplayPage,
875                                 IDC_REMICON,
876                                 STM_SETICON,
877                                 (WPARAM)pInfo->hRemote,
878                                 0);
879         }
880 
881         pInfo->hColor = LoadImageW(hInst,
882                                    MAKEINTRESOURCEW(IDI_COLORS),
883                                    IMAGE_ICON,
884                                    32,
885                                    32,
886                                   LR_DEFAULTCOLOR);
887         if (pInfo->hColor)
888         {
889             SendDlgItemMessageW(pInfo->hDisplayPage,
890                                 IDC_COLORSICON,
891                                 STM_SETICON,
892                                 (WPARAM)pInfo->hColor,
893                                 0);
894         }
895 
896         pInfo->hSpectrum = LoadImageW(hInst,
897                                       MAKEINTRESOURCEW(IDB_SPECT),
898                                       IMAGE_BITMAP,
899                                       0,
900                                       0,
901                                       LR_DEFAULTCOLOR);
902         if (pInfo->hSpectrum)
903         {
904             GetObjectW(pInfo->hSpectrum,
905                        sizeof(BITMAP),
906                        &pInfo->bitmap);
907         }
908 
909         /* Get video cards list */
910         displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
911         while (EnumDisplayDevicesW(NULL, iDevNum, &displayDevice, 0x1))
912         {
913             if ((displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0)
914             {
915                 if (AddDisplayDevice(pInfo, &displayDevice))
916                     GotDev = TRUE;
917             }
918             iDevNum++;
919         }
920 
921         if (GotDev)
922         {
923             FillResolutionsAndColors(pInfo);
924             ReLoadDisplayPage(pInfo);
925         }
926 }
927 
928 
929 INT_PTR CALLBACK
930 DisplayDlgProc(HWND hDlg,
931                UINT message,
932                WPARAM wParam,
933                LPARAM lParam)
934 {
935     PINFO pInfo = (PINFO)GetWindowLongPtrW(hDlg,
936                                            GWLP_USERDATA);
937 
938     switch (message)
939     {
940         case WM_INITDIALOG:
941             DisplayOnInit(hDlg, (PINFO)lParam);
942             return TRUE;
943 
944         case WM_DRAWITEM:
945         {
946             LPDRAWITEMSTRUCT lpDrawItem;
947             lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
948             if(lpDrawItem->CtlID == IDC_COLORIMAGE)
949             {
950                 HDC hdcMem;
951                 HBITMAP hSpecOld;
952                 hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
953                 if (hdcMem != NULL)
954                 {
955                     hSpecOld = SelectObject(hdcMem, pInfo->hSpectrum);
956                     StretchBlt(lpDrawItem->hDC,
957                                lpDrawItem->rcItem.left,
958                                lpDrawItem->rcItem.top,
959                                lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
960                                lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
961                                hdcMem,
962                                0,
963                                0,
964                                pInfo->bitmap.bmWidth,
965                                pInfo->bitmap.bmHeight,
966                                SRCCOPY);
967                     SelectObject(hdcMem, hSpecOld);
968                     DeleteDC(hdcMem);
969                 }
970             }
971             break;
972         }
973 
974         case WM_HSCROLL:
975         {
976             switch (LOWORD(wParam))
977             {
978                 case TB_LINEUP:
979                 case TB_LINEDOWN:
980                 case TB_PAGEUP:
981                 case TB_PAGEDOWN:
982                 case TB_TOP:
983                 case TB_BOTTOM:
984                 case TB_ENDTRACK:
985                 {
986                     INT newPosition = (DWORD)SendDlgItemMessageW(hDlg, IDC_GEOSLIDER, TBM_GETPOS, 0, 0);
987                     OnResolutionChanged(pInfo, newPosition);
988                     break;
989                 }
990 
991                 case TB_THUMBTRACK:
992                     OnResolutionChanged(pInfo, HIWORD(wParam));
993                     break;
994             }
995             break;
996         }
997 
998         case WM_CLOSE:
999         {
1000             if (pInfo->hRemote)
1001                 DestroyIcon(pInfo->hRemote);
1002 
1003             if (pInfo->hColor)
1004                 DestroyIcon(pInfo->hColor);
1005 
1006             if (pInfo->hSpectrum)
1007                 DeleteObject(pInfo->hSpectrum);
1008 
1009             break;
1010         }
1011 
1012         break;
1013     }
1014     return 0;
1015 }
1016 
1017 
1018 static BOOL
1019 OnMainCreate(HWND hwnd,
1020              PRDPSETTINGS pRdpSettings)
1021 {
1022     PINFO pInfo;
1023     TCITEMW item;
1024     BOOL bRet = FALSE;
1025 
1026     pInfo = HeapAlloc(GetProcessHeap(),
1027                       HEAP_ZERO_MEMORY,
1028                       sizeof(INFO));
1029     if (pInfo)
1030     {
1031         SetWindowLongPtrW(hwnd,
1032                           GWLP_USERDATA,
1033                           (LONG_PTR)pInfo);
1034 
1035         pInfo->hSelf = hwnd;
1036 
1037         /* add main settings pointer */
1038         pInfo->pRdpSettings = pRdpSettings;
1039 
1040         /* set the dialog icons */
1041         pInfo->hMstscSm = LoadImageW(hInst,
1042                                    MAKEINTRESOURCEW(IDI_MSTSC),
1043                                    IMAGE_ICON,
1044                                    16,
1045                                    16,
1046                                    LR_DEFAULTCOLOR);
1047         if (pInfo->hMstscSm)
1048         {
1049             SendMessageW(hwnd,
1050                          WM_SETICON,
1051                          ICON_SMALL,
1052                         (WPARAM)pInfo->hMstscSm);
1053         }
1054         pInfo->hMstscLg = LoadImageW(hInst,
1055                                    MAKEINTRESOURCEW(IDI_MSTSC),
1056                                    IMAGE_ICON,
1057                                    32,
1058                                    32,
1059                                    LR_DEFAULTCOLOR);
1060         if (pInfo->hMstscLg)
1061         {
1062             SendMessageW(hwnd,
1063                          WM_SETICON,
1064                          ICON_BIG,
1065                         (WPARAM)pInfo->hMstscLg);
1066         }
1067 
1068         pInfo->hHeader = (HBITMAP)LoadImageW(hInst,
1069                                              MAKEINTRESOURCEW(IDB_HEADER),
1070                                              IMAGE_BITMAP,
1071                                              0,
1072                                              0,
1073                                              LR_DEFAULTCOLOR);
1074         if (pInfo->hHeader)
1075         {
1076             GetObjectW(pInfo->hHeader,
1077                        sizeof(BITMAP),
1078                        &pInfo->headerbitmap);
1079         }
1080 
1081         /* setup the tabs */
1082         pInfo->hTab = GetDlgItem(hwnd, IDC_TAB);
1083         if (pInfo->hTab)
1084         {
1085             if (CreateDialogParamW(hInst,
1086                                    MAKEINTRESOURCEW(IDD_GENERAL),
1087                                    pInfo->hTab,
1088                                    GeneralDlgProc,
1089                                    (LPARAM)pInfo))
1090             {
1091                 WCHAR str[256];
1092                 ZeroMemory(&item, sizeof(TCITEM));
1093                 item.mask = TCIF_TEXT;
1094                 if (LoadStringW(hInst, IDS_TAB_GENERAL, str, 256))
1095                     item.pszText = str;
1096                 item.cchTextMax = 256;
1097                 (void)TabCtrl_InsertItem(pInfo->hTab, 0, &item);
1098             }
1099 
1100             if (CreateDialogParamW(hInst,
1101                                    MAKEINTRESOURCEW(IDD_DISPLAY),
1102                                    pInfo->hTab,
1103                                    DisplayDlgProc,
1104                                    (LPARAM)pInfo))
1105             {
1106                 WCHAR str[256];
1107                 ZeroMemory(&item, sizeof(TCITEM));
1108                 item.mask = TCIF_TEXT;
1109                 if (LoadStringW(hInst, IDS_TAB_DISPLAY, str, 256))
1110                     item.pszText = str;
1111                 item.cchTextMax = 256;
1112                 (void)TabCtrl_InsertItem(pInfo->hTab, 1, &item);
1113             }
1114 
1115             OnTabWndSelChange(pInfo);
1116         }
1117     }
1118 
1119     return bRet;
1120 }
1121 
1122 static void Cleanup(PINFO pInfo)
1123 {
1124     if (pInfo)
1125     {
1126         if (pInfo->hMstscSm)
1127             DestroyIcon(pInfo->hMstscSm);
1128         if (pInfo->hMstscLg)
1129             DestroyIcon(pInfo->hMstscLg);
1130         if (pInfo->hHeader)
1131             DeleteObject(pInfo->hHeader);
1132         if (pInfo->hSpectrum)
1133             DeleteObject(pInfo->hSpectrum);
1134         if (pInfo->hRemote)
1135             DestroyIcon(pInfo->hRemote);
1136         if (pInfo->hLogon)
1137             DestroyIcon(pInfo->hLogon);
1138         if (pInfo->hConn)
1139             DestroyIcon(pInfo->hConn);
1140         if (pInfo->hColor)
1141             DestroyIcon(pInfo->hColor);
1142         HeapFree(GetProcessHeap(),
1143                  0,
1144                  pInfo);
1145     }
1146 }
1147 
1148 static INT_PTR CALLBACK
1149 DlgProc(HWND hDlg,
1150         UINT Message,
1151         WPARAM wParam,
1152         LPARAM lParam)
1153 {
1154     PINFO pInfo;
1155 
1156     /* Get the window context */
1157     pInfo = (PINFO)GetWindowLongPtrW(hDlg,
1158                                      GWLP_USERDATA);
1159     if (pInfo == NULL && Message != WM_INITDIALOG)
1160     {
1161         goto HandleDefaultMessage;
1162     }
1163 
1164     switch(Message)
1165     {
1166         case WM_INITDIALOG:
1167             OnMainCreate(hDlg, (PRDPSETTINGS)lParam);
1168         break;
1169 
1170         case WM_COMMAND:
1171         {
1172             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1173             {
1174                 if (LOWORD(wParam) == IDOK )
1175                 {
1176                     SaveAllSettings(pInfo);
1177                     SaveRdpSettingsToFile(NULL, pInfo->pRdpSettings);
1178                 }
1179                 Cleanup(pInfo);
1180                 EndDialog(hDlg, LOWORD(wParam));
1181             }
1182 
1183             break;
1184         }
1185 
1186         case WM_NOTIFY:
1187         {
1188             //INT idctrl;
1189             LPNMHDR pnmh;
1190             //idctrl = (int)wParam;
1191             pnmh = (LPNMHDR)lParam;
1192             if (//(pnmh->hwndFrom == pInfo->hSelf) &&
1193                 (pnmh->idFrom == IDC_TAB) &&
1194                 (pnmh->code == TCN_SELCHANGE))
1195             {
1196                 OnTabWndSelChange(pInfo);
1197             }
1198 
1199             break;
1200         }
1201 
1202         case WM_PAINT:
1203         {
1204             PAINTSTRUCT ps;
1205             HDC hdc;
1206 
1207             hdc = BeginPaint(hDlg, &ps);
1208             if (hdc != NULL)
1209             {
1210                 HDC hdcMem = CreateCompatibleDC(hdc);
1211                 if (hdcMem)
1212                 {
1213                     WCHAR szBuffer[32];
1214                     RECT bmpRc, txtRc;
1215                     LOGFONTW lf;
1216                     HFONT hFont, hFontOld;
1217                     HBITMAP hBmpOld;
1218 
1219                     GetClientRect(pInfo->hSelf, &bmpRc);
1220 
1221                     hBmpOld = SelectObject(hdcMem, pInfo->hHeader);
1222                     StretchBlt(hdc,
1223                                0,
1224                                0,
1225                                bmpRc.right,
1226                                pInfo->headerbitmap.bmHeight,
1227                                hdcMem,
1228                                0,
1229                                0,
1230                                pInfo->headerbitmap.bmWidth,
1231                                pInfo->headerbitmap.bmHeight,
1232                                SRCCOPY);
1233 
1234                     SelectObject(hdcMem, hBmpOld);
1235                     txtRc.left = bmpRc.right / 4;
1236                     txtRc.top = 10;
1237                     txtRc.right = bmpRc.right * 3 / 4;
1238                     txtRc.bottom = pInfo->headerbitmap.bmHeight / 2;
1239 
1240                     ZeroMemory(&lf, sizeof(LOGFONTW));
1241 
1242                     if (LoadStringW(hInst,
1243                                     IDS_HEADERTEXT1,
1244                                     szBuffer,
1245                                     sizeof(szBuffer) / sizeof(WCHAR)))
1246                     {
1247                         lf.lfHeight = 20;
1248                         lf.lfCharSet = OEM_CHARSET;
1249                         lf.lfQuality = DEFAULT_QUALITY;
1250                         lf.lfWeight = FW_MEDIUM;
1251                         wcscpy(lf.lfFaceName, L"Tahoma");
1252 
1253                         hFont = CreateFontIndirectW(&lf);
1254                         if (hFont)
1255                         {
1256                             hFontOld = SelectObject(hdc, hFont);
1257 
1258                             DPtoLP(hdc, (PPOINT)&txtRc, 2);
1259                             SetTextColor(hdc, RGB(255,255,255));
1260                             SetBkMode(hdc, TRANSPARENT);
1261                             DrawTextW(hdc,
1262                                       szBuffer,
1263                                       -1,
1264                                       &txtRc,
1265                                       DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP | DT_CENTER); //DT_CENTER makes the text visible in RTL layouts...
1266                             SelectObject(hdc, hFontOld);
1267                             DeleteObject(hFont);
1268                         }
1269                     }
1270 
1271                     txtRc.left = bmpRc.right / 4;
1272                     txtRc.top = txtRc.bottom - 5;
1273 #ifdef __REACTOS__
1274                     txtRc.right = bmpRc.right * 4 / 5;
1275 #else
1276                     txtRc.right = bmpRc.right * 3 / 4;
1277 #endif
1278                     txtRc.bottom = pInfo->headerbitmap.bmHeight * 9 / 10;
1279 
1280                     if (LoadStringW(hInst,
1281                                     IDS_HEADERTEXT2,
1282                                     szBuffer,
1283                                     sizeof(szBuffer) / sizeof(WCHAR)))
1284                     {
1285                         lf.lfHeight = 24;
1286                         lf.lfCharSet = OEM_CHARSET;
1287                         lf.lfQuality = DEFAULT_QUALITY;
1288                         lf.lfWeight = FW_EXTRABOLD;
1289                         wcscpy(lf.lfFaceName, L"Tahoma");
1290 
1291                         hFont = CreateFontIndirectW(&lf);
1292                         if (hFont)
1293                         {
1294                             hFontOld = SelectObject(hdc, hFont);
1295 
1296                             DPtoLP(hdc, (PPOINT)&txtRc, 2);
1297                             SetTextColor(hdc, RGB(255,255,255));
1298                             SetBkMode(hdc, TRANSPARENT);
1299                             DrawTextW(hdc,
1300                                       szBuffer,
1301                                       -1,
1302                                       &txtRc,
1303                                       DT_TOP | DT_SINGLELINE);
1304                             SelectObject(hdc, hFontOld);
1305                             DeleteObject(hFont);
1306                         }
1307                     }
1308 
1309                     DeleteDC(hdcMem);
1310                 }
1311 
1312                 EndPaint(hDlg, &ps);
1313             }
1314 
1315             break;
1316         }
1317 
1318         case WM_CLOSE:
1319         {
1320             Cleanup(pInfo);
1321             EndDialog(hDlg, 0);
1322         }
1323         break;
1324 
1325 HandleDefaultMessage:
1326         default:
1327             return FALSE;
1328     }
1329 
1330     return FALSE;
1331 }
1332 
1333 
1334 BOOL
1335 OpenRDPConnectDialog(HINSTANCE hInstance,
1336                      PRDPSETTINGS pRdpSettings)
1337 {
1338     INITCOMMONCONTROLSEX iccx;
1339 
1340     hInst = hInstance;
1341 
1342     iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
1343     iccx.dwICC = ICC_TAB_CLASSES;
1344     InitCommonControlsEx(&iccx);
1345 
1346     return (DialogBoxParamW(hInst,
1347                             MAKEINTRESOURCEW(IDD_CONNECTDIALOG),
1348                             NULL,
1349                             DlgProc,
1350                             (LPARAM)pRdpSettings) == IDOK);
1351 }
1352