Improve error handling in registry code
[sgt/putty] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #include <winsock.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include "putty.h"
9 #include "ssh.h"
10 #include "win_res.h"
11
12 #define NPANELS 7
13 #define MAIN_NPANELS 7
14 #define RECONF_NPANELS 4
15
16 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
17
18 static void get_sesslist(int allocate);
19
20 static char **negots = NULL;
21 static int nnegots = 0, negsize = 0;
22 static HWND logbox = NULL, abtbox = NULL;
23
24 static char hex[16] = "0123456789ABCDEF";
25
26 static void mungestr(char *in, char *out) {
27 int candot = 0;
28
29 while (*in) {
30 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
31 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
32 *out++ = '%';
33 *out++ = hex[((unsigned char)*in) >> 4];
34 *out++ = hex[((unsigned char)*in) & 15];
35 } else
36 *out++ = *in;
37 in++;
38 candot = 1;
39 }
40 *out = '\0';
41 return;
42 }
43
44 static void unmungestr(char *in, char *out) {
45 int candot = 0;
46
47 while (*in) {
48 if (*in == '%' && in[1] && in[2]) {
49 int i, j;
50
51 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
52 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
53
54 *out++ = (i<<4) + j;
55 in += 3;
56 } else
57 *out++ = *in++;
58 }
59 *out = '\0';
60 return;
61 }
62
63 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
64 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
65 }
66
67 static void wppi(HKEY key, LPCTSTR name, int value) {
68 RegSetValueEx(key, name, 0, REG_DWORD,
69 (CONST BYTE *)&value, sizeof(value));
70 }
71
72 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
73 LPTSTR val, int len) {
74 DWORD type, size;
75 size = len;
76
77 if (key == NULL ||
78 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
79 type != REG_SZ) {
80 strncpy(val, def, len);
81 val[len-1] = '\0';
82 }
83 }
84
85 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
86 DWORD type, val, size;
87 size = sizeof(val);
88
89 if (key == NULL ||
90 RegQueryValueEx(key, name, 0, &type,
91 (BYTE *)&val, &size) != ERROR_SUCCESS ||
92 size != sizeof(val) || type != REG_DWORD)
93 *i = def;
94 else
95 *i = val;
96 }
97
98 static HINSTANCE hinst;
99
100 static char **sessions;
101 static int nsessions;
102
103 static int readytogo;
104
105 static void save_settings (char *section, int do_host) {
106 int i;
107 HKEY subkey1, sesskey;
108 char *p;
109
110 p = malloc(3*strlen(section)+1);
111 mungestr(section, p);
112
113 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
114 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
115 sesskey = NULL;
116 }
117
118 free(p);
119 RegCloseKey(subkey1);
120
121 wppi (sesskey, "Present", 1);
122 if (do_host) {
123 wpps (sesskey, "HostName", cfg.host);
124 wppi (sesskey, "PortNumber", cfg.port);
125 wpps (sesskey, "Protocol",
126 cfg.protocol == PROT_SSH ? "ssh" : "telnet");
127 }
128 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
129 wpps (sesskey, "TerminalType", cfg.termtype);
130 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
131 {
132 char buf[2*sizeof(cfg.environmt)], *p, *q;
133 p = buf;
134 q = cfg.environmt;
135 while (*q) {
136 while (*q) {
137 int c = *q++;
138 if (c == '=' || c == ',' || c == '\\')
139 *p++ = '\\';
140 if (c == '\t')
141 c = '=';
142 *p++ = c;
143 }
144 *p++ = ',';
145 q++;
146 }
147 *p = '\0';
148 wpps (sesskey, "Environment", buf);
149 }
150 wpps (sesskey, "UserName", cfg.username);
151 wppi (sesskey, "NoPTY", cfg.nopty);
152 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
153 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
154 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
155 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
156 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
157 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
158 wppi (sesskey, "ScrollbackLines", cfg.savelines);
159 wppi (sesskey, "DECOriginMode", cfg.dec_om);
160 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
161 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
162 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
163 wppi (sesskey, "TermWidth", cfg.width);
164 wppi (sesskey, "TermHeight", cfg.height);
165 wpps (sesskey, "Font", cfg.font);
166 wppi (sesskey, "FontIsBold", cfg.fontisbold);
167 wppi (sesskey, "FontHeight", cfg.fontheight);
168 wppi (sesskey, "FontVTMode", cfg.vtmode);
169 wppi (sesskey, "TryPalette", cfg.try_palette);
170 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
171 for (i=0; i<22; i++) {
172 char buf[20], buf2[30];
173 sprintf(buf, "Colour%d", i);
174 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
175 cfg.colours[i][1], cfg.colours[i][2]);
176 wpps (sesskey, buf, buf2);
177 }
178 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
179 for (i=0; i<256; i+=32) {
180 char buf[20], buf2[256];
181 int j;
182 sprintf(buf, "Wordness%d", i);
183 *buf2 = '\0';
184 for (j=i; j<i+32; j++) {
185 sprintf(buf2+strlen(buf2), "%s%d",
186 (*buf2 ? "," : ""), cfg.wordness[j]);
187 }
188 wpps (sesskey, buf, buf2);
189 }
190
191 RegCloseKey(sesskey);
192 }
193
194 static void del_session (char *section) {
195 HKEY subkey1;
196 char *p;
197
198 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
199 return;
200
201 p = malloc(3*strlen(section)+1);
202 mungestr(section, p);
203 RegDeleteKey(subkey1, p);
204 free(p);
205
206 RegCloseKey(subkey1);
207 }
208
209 static void load_settings (char *section, int do_host) {
210 int i;
211 HKEY subkey1, sesskey;
212 char *p;
213
214 p = malloc(3*strlen(section)+1);
215 mungestr(section, p);
216
217 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
218 sesskey = NULL;
219 } else {
220 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
221 sesskey = NULL;
222 }
223 RegCloseKey(subkey1);
224 }
225
226 free(p);
227
228 if (do_host) {
229 char prot[10];
230 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
231 gppi (sesskey, "PortNumber", 23, &cfg.port);
232 gpps (sesskey, "Protocol", "telnet", prot, 10);
233 if (!strcmp(prot, "ssh"))
234 cfg.protocol = PROT_SSH;
235 else
236 cfg.protocol = PROT_TELNET;
237 } else {
238 cfg.port = 23;
239 *cfg.host = '\0';
240 }
241 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
242 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
243 sizeof(cfg.termtype));
244 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
245 sizeof(cfg.termspeed));
246 {
247 char buf[2*sizeof(cfg.environmt)], *p, *q;
248 gpps (sesskey, "Environment", "", buf, sizeof(buf));
249 p = buf;
250 q = cfg.environmt;
251 while (*p) {
252 while (*p && *p != ',') {
253 int c = *p++;
254 if (c == '=')
255 c = '\t';
256 if (c == '\\')
257 c = *p++;
258 *p++ = c;
259 }
260 if (*p == ',') p++;
261 *q++ = '\0';
262 }
263 *q = '\0';
264 }
265 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
266 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
267 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
268 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
269 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
270 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
271 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
272 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
273 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
274 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
275 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
276 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
277 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
278 gppi (sesskey, "TermWidth", 80, &cfg.width);
279 gppi (sesskey, "TermHeight", 24, &cfg.height);
280 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
281 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
282 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
283 gppi (sesskey, "FontVTMode", VT_POORMAN, &cfg.vtmode);
284 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
285 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
286 for (i=0; i<22; i++) {
287 static char *defaults[] = {
288 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
289 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
290 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
291 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
292 "85,255,255", "187,187,187", "255,255,255"
293 };
294 char buf[20], buf2[30];
295 sprintf(buf, "Colour%d", i);
296 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
297 sscanf(buf2, "%d,%d,%d", &cfg.colours[i][0],
298 &cfg.colours[i][1], &cfg.colours[i][2]);
299 }
300 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
301 for (i=0; i<256; i+=32) {
302 static char *defaults[] = {
303 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
304 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
305 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
306 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
307 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
308 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
309 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
310 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
311 };
312 char buf[20], buf2[256], *p;
313 int j;
314 sprintf(buf, "Wordness%d", i);
315 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
316 p = buf2;
317 for (j=i; j<i+32; j++) {
318 char *q = p;
319 while (*p && *p != ',') p++;
320 if (*p == ',') *p++ = '\0';
321 cfg.wordness[j] = atoi(q);
322 }
323 }
324 RegCloseKey(sesskey);
325 }
326
327 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
328 BOOL ok;
329 int n;
330 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
331 if (ok)
332 *result = n;
333 }
334
335 static int CALLBACK LogProc (HWND hwnd, UINT msg,
336 WPARAM wParam, LPARAM lParam) {
337 int i;
338
339 switch (msg) {
340 case WM_INITDIALOG:
341 for (i=0; i<nnegots; i++)
342 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
343 0, (LPARAM)negots[i]);
344 return 1;
345 /* case WM_CTLCOLORDLG: */
346 /* return (int) GetStockObject (LTGRAY_BRUSH); */
347 case WM_COMMAND:
348 switch (LOWORD(wParam)) {
349 case IDOK:
350 logbox = NULL;
351 DestroyWindow (hwnd);
352 return 0;
353 }
354 return 0;
355 case WM_CLOSE:
356 logbox = NULL;
357 DestroyWindow (hwnd);
358 return 0;
359 }
360 return 0;
361 }
362
363 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
364 WPARAM wParam, LPARAM lParam) {
365 switch (msg) {
366 case WM_INITDIALOG:
367 return 1;
368 case WM_COMMAND:
369 switch (LOWORD(wParam)) {
370 case IDOK:
371 abtbox = NULL;
372 DestroyWindow (hwnd);
373 return 0;
374 }
375 return 0;
376 case WM_CLOSE:
377 abtbox = NULL;
378 DestroyWindow (hwnd);
379 return 0;
380 }
381 return 0;
382 }
383
384 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
385 WPARAM wParam, LPARAM lParam) {
386 switch (msg) {
387 case WM_INITDIALOG:
388 SetDlgItemText (hwnd, IDA_VERSION, ver);
389 return 1;
390 /* case WM_CTLCOLORDLG: */
391 /* return (int) GetStockObject (LTGRAY_BRUSH); */
392 /* case WM_CTLCOLORSTATIC: */
393 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
394 /* return (int) GetStockObject (LTGRAY_BRUSH); */
395 case WM_COMMAND:
396 switch (LOWORD(wParam)) {
397 case IDOK:
398 abtbox = NULL;
399 DestroyWindow (hwnd);
400 return 0;
401 case IDA_LICENCE:
402 EnableWindow(hwnd, 0);
403 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
404 NULL, LicenceProc);
405 EnableWindow(hwnd, 1);
406 return 0;
407 }
408 return 0;
409 case WM_CLOSE:
410 abtbox = NULL;
411 DestroyWindow (hwnd);
412 return 0;
413 }
414 return 0;
415 }
416
417 static int GeneralPanelProc (HWND hwnd, UINT msg,
418 WPARAM wParam, LPARAM lParam) {
419 switch (msg) {
420 case WM_INITDIALOG:
421 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
422 return 1;
423 /* case WM_CTLCOLORDLG: */
424 /* return (int) GetStockObject (LTGRAY_BRUSH); */
425 /* case WM_CTLCOLORSTATIC: */
426 /* case WM_CTLCOLORBTN: */
427 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
428 /* return (int) GetStockObject (LTGRAY_BRUSH); */
429 case WM_CLOSE:
430 DestroyWindow (hwnd);
431 return 1;
432 }
433 return 0;
434 }
435
436 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
437 WPARAM wParam, LPARAM lParam) {
438 int i;
439
440 switch (msg) {
441 case WM_INITDIALOG:
442 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
443 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
444 for (i = 0; i < nsessions; i++)
445 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
446 0, (LPARAM) (sessions[i]));
447 CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
448 cfg.protocol==PROT_SSH ? IDC0_PROTSSH : IDC0_PROTTELNET);
449 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
450 break;
451 case WM_LBUTTONUP:
452 /*
453 * Button release should trigger WM_OK if there was a
454 * previous double click on the session list.
455 */
456 ReleaseCapture();
457 if (readytogo)
458 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
459 break;
460 case WM_COMMAND:
461 switch (LOWORD(wParam)) {
462 case IDC0_PROTTELNET:
463 case IDC0_PROTSSH:
464 if (HIWORD(wParam) == BN_CLICKED ||
465 HIWORD(wParam) == BN_DOUBLECLICKED) {
466 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
467 cfg.protocol = i ? PROT_SSH : PROT_TELNET;
468 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
469 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
470 cfg.port = i ? 22 : 23;
471 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
472 }
473 }
474 break;
475 case IDC0_HOST:
476 if (HIWORD(wParam) == EN_CHANGE)
477 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
478 sizeof(cfg.host)-1);
479 break;
480 case IDC0_PORT:
481 if (HIWORD(wParam) == EN_CHANGE)
482 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
483 break;
484 case IDC0_CLOSEEXIT:
485 if (HIWORD(wParam) == BN_CLICKED ||
486 HIWORD(wParam) == BN_DOUBLECLICKED)
487 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
488 break;
489 case IDC0_SESSEDIT:
490 if (HIWORD(wParam) == EN_CHANGE)
491 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
492 (WPARAM) -1, 0);
493 break;
494 case IDC0_SESSSAVE:
495 if (HIWORD(wParam) == BN_CLICKED ||
496 HIWORD(wParam) == BN_DOUBLECLICKED) {
497 /*
498 * Save a session
499 */
500 char str[2048];
501 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
502 if (!*str) {
503 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
504 LB_GETCURSEL, 0, 0);
505 if (n == LB_ERR) {
506 MessageBeep(0);
507 break;
508 }
509 strcpy (str, sessions[n]);
510 }
511 save_settings (str, !!strcmp(str, "Default Settings"));
512 get_sesslist (FALSE);
513 get_sesslist (TRUE);
514 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
515 0, 0);
516 for (i = 0; i < nsessions; i++)
517 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
518 0, (LPARAM) (sessions[i]));
519 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
520 (WPARAM) -1, 0);
521 }
522 break;
523 case IDC0_SESSLIST:
524 case IDC0_SESSLOAD:
525 if (LOWORD(wParam) == IDC0_SESSLOAD &&
526 HIWORD(wParam) != BN_CLICKED &&
527 HIWORD(wParam) != BN_DOUBLECLICKED)
528 break;
529 if (LOWORD(wParam) == IDC0_SESSLIST &&
530 HIWORD(wParam) != LBN_DBLCLK)
531 break;
532 {
533 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
534 LB_GETCURSEL, 0, 0);
535 if (n == LB_ERR) {
536 MessageBeep(0);
537 break;
538 }
539 load_settings (sessions[n],
540 !!strcmp(sessions[n], "Default Settings"));
541 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
542 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
543 CheckRadioButton (hwnd, IDC0_PROTTELNET, IDC0_PROTSSH,
544 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
545 IDC0_PROTTELNET));
546 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
547 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
548 (WPARAM) -1, 0);
549 }
550 if (LOWORD(wParam) == IDC0_SESSLIST) {
551 /*
552 * A double-click on a saved session should
553 * actually start the session, not just load it.
554 * Unless it's Default Settings or some other
555 * host-less set of saved settings.
556 */
557 if (*cfg.host) {
558 readytogo = TRUE;
559 SetCapture(hwnd);
560 }
561 }
562 break;
563 case IDC0_SESSDEL:
564 if (HIWORD(wParam) == BN_CLICKED ||
565 HIWORD(wParam) == BN_DOUBLECLICKED) {
566 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
567 LB_GETCURSEL, 0, 0);
568 if (n == LB_ERR || n == 0) {
569 MessageBeep(0);
570 break;
571 }
572 del_session(sessions[n]);
573 get_sesslist (FALSE);
574 get_sesslist (TRUE);
575 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
576 0, 0);
577 for (i = 0; i < nsessions; i++)
578 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
579 0, (LPARAM) (sessions[i]));
580 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
581 (WPARAM) -1, 0);
582 }
583 }
584 }
585 return GeneralPanelProc (hwnd, msg, wParam, lParam);
586 }
587
588 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
589 WPARAM wParam, LPARAM lParam) {
590 switch (msg) {
591 case WM_INITDIALOG:
592 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
593 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
594 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
595 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
596 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
597 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
598 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
599 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
600 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPAPPLIC,
601 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
602 break;
603 case WM_COMMAND:
604 if (HIWORD(wParam) == BN_CLICKED ||
605 HIWORD(wParam) == BN_DOUBLECLICKED)
606 switch (LOWORD(wParam)) {
607 case IDC1_DEL008:
608 case IDC1_DEL127:
609 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
610 break;
611 case IDC1_HOMETILDE:
612 case IDC1_HOMERXVT:
613 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
614 break;
615 case IDC1_FUNCTILDE:
616 case IDC1_FUNCLINUX:
617 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
618 break;
619 case IDC1_KPNORMAL:
620 case IDC1_KPAPPLIC:
621 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
622 break;
623 case IDC1_CURNORMAL:
624 case IDC1_CURAPPLIC:
625 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
626 break;
627 }
628 }
629 return GeneralPanelProc (hwnd, msg, wParam, lParam);
630 }
631
632 static void fmtfont (char *buf) {
633 sprintf (buf, "Font: %s, ", cfg.font);
634 if (cfg.fontisbold)
635 strcat(buf, "bold, ");
636 if (cfg.fontheight == 0)
637 strcat (buf, "default height");
638 else
639 sprintf (buf+strlen(buf), "%d-%s",
640 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
641 (cfg.fontheight < 0 ? "pixel" : "point"));
642 }
643
644 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
645 WPARAM wParam, LPARAM lParam) {
646 CHOOSEFONT cf;
647 LOGFONT lf;
648 char fontstatic[256];
649
650 switch (msg) {
651 case WM_INITDIALOG:
652 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
653 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
654 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
655 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
656 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
657 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
658 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
659 fmtfont (fontstatic);
660 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
661 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
662 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
663 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
664 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
665 IDC2_VTPOORMAN);
666 break;
667 case WM_COMMAND:
668 switch (LOWORD(wParam)) {
669 case IDC2_WRAPMODE:
670 if (HIWORD(wParam) == BN_CLICKED ||
671 HIWORD(wParam) == BN_DOUBLECLICKED)
672 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
673 break;
674 case IDC2_WINNAME:
675 if (HIWORD(wParam) == BN_CLICKED ||
676 HIWORD(wParam) == BN_DOUBLECLICKED)
677 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
678 break;
679 case IDC2_DECOM:
680 if (HIWORD(wParam) == BN_CLICKED ||
681 HIWORD(wParam) == BN_DOUBLECLICKED)
682 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
683 break;
684 case IDC2_LFHASCR:
685 if (HIWORD(wParam) == BN_CLICKED ||
686 HIWORD(wParam) == BN_DOUBLECLICKED)
687 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
688 break;
689 case IDC2_ROWSEDIT:
690 if (HIWORD(wParam) == EN_CHANGE)
691 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
692 break;
693 case IDC2_COLSEDIT:
694 if (HIWORD(wParam) == EN_CHANGE)
695 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
696 break;
697 case IDC2_SAVEEDIT:
698 if (HIWORD(wParam) == EN_CHANGE)
699 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
700 break;
701 case IDC2_CHOOSEFONT:
702 lf.lfHeight = cfg.fontheight;
703 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
704 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
705 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
706 lf.lfCharSet = ANSI_CHARSET;
707 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
708 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
709 lf.lfQuality = DEFAULT_QUALITY;
710 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
711 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
712 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
713
714 cf.lStructSize = sizeof(cf);
715 cf.hwndOwner = hwnd;
716 cf.lpLogFont = &lf;
717 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
718 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
719
720 if (ChooseFont (&cf)) {
721 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
722 cfg.font[sizeof(cfg.font)-1] = '\0';
723 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
724 cfg.fontheight = lf.lfHeight;
725 fmtfont (fontstatic);
726 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
727 }
728 break;
729 case IDC2_VTXWINDOWS:
730 case IDC2_VTOEMANSI:
731 case IDC2_VTOEMONLY:
732 case IDC2_VTPOORMAN:
733 cfg.vtmode =
734 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
735 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
736 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
737 VT_POORMAN);
738 break;
739 }
740 break;
741 }
742 return GeneralPanelProc (hwnd, msg, wParam, lParam);
743 }
744
745 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
746 WPARAM wParam, LPARAM lParam) {
747 int i;
748
749 switch (msg) {
750 case WM_INITDIALOG:
751 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
752 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
753 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
754 {
755 char *p = cfg.environmt;
756 while (*p) {
757 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
758 (LPARAM) p);
759 p += strlen(p)+1;
760 }
761 }
762 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
763 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
764 break;
765 case WM_COMMAND:
766 switch (LOWORD(wParam)) {
767 case IDC3_TTEDIT:
768 if (HIWORD(wParam) == EN_CHANGE)
769 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
770 sizeof(cfg.termtype)-1);
771 break;
772 case IDC3_TSEDIT:
773 if (HIWORD(wParam) == EN_CHANGE)
774 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
775 sizeof(cfg.termspeed)-1);
776 break;
777 case IDC3_LOGEDIT:
778 if (HIWORD(wParam) == EN_CHANGE)
779 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
780 sizeof(cfg.username)-1);
781 break;
782 case IDC3_EMBSD:
783 case IDC3_EMRFC:
784 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
785 break;
786 case IDC3_ENVADD:
787 if (HIWORD(wParam) == BN_CLICKED ||
788 HIWORD(wParam) == BN_DOUBLECLICKED) {
789 char str[sizeof(cfg.environmt)];
790 char *p;
791 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
792 if (!*str) {
793 MessageBeep(0);
794 break;
795 }
796 p = str + strlen(str);
797 *p++ = '\t';
798 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
799 if (!*p) {
800 MessageBeep(0);
801 break;
802 }
803 p = cfg.environmt;
804 while (*p) {
805 while (*p) p++;
806 p++;
807 }
808 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
809 strcpy (p, str);
810 p[strlen(str)+1] = '\0';
811 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
812 0, (LPARAM)str);
813 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
814 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
815 } else {
816 MessageBox(hwnd, "Environment too big", "PuTTY Error",
817 MB_OK | MB_ICONERROR);
818 }
819 }
820 break;
821 case IDC3_ENVREMOVE:
822 if (HIWORD(wParam) != BN_CLICKED &&
823 HIWORD(wParam) != BN_DOUBLECLICKED)
824 break;
825 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
826 if (i == LB_ERR)
827 MessageBeep (0);
828 else {
829 char *p, *q;
830
831 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
832 i, 0);
833 p = cfg.environmt;
834 while (i > 0) {
835 if (!*p)
836 goto disaster;
837 while (*p) p++;
838 p++;
839 i--;
840 }
841 q = p;
842 if (!*p)
843 goto disaster;
844 while (*p) p++;
845 p++;
846 while (*p) {
847 while (*p)
848 *q++ = *p++;
849 *q++ = *p++;
850 }
851 *q = '\0';
852 disaster:;
853 }
854 break;
855 }
856 break;
857 }
858 return GeneralPanelProc (hwnd, msg, wParam, lParam);
859 }
860
861 static int CALLBACK SshProc (HWND hwnd, UINT msg,
862 WPARAM wParam, LPARAM lParam) {
863 switch (msg) {
864 case WM_INITDIALOG:
865 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
866 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
867 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
868 break;
869 case WM_COMMAND:
870 switch (LOWORD(wParam)) {
871 case IDC3_TTEDIT:
872 if (HIWORD(wParam) == EN_CHANGE)
873 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
874 sizeof(cfg.termtype)-1);
875 break;
876 case IDC3_LOGEDIT:
877 if (HIWORD(wParam) == EN_CHANGE)
878 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
879 sizeof(cfg.username)-1);
880 break;
881 case IDC3_NOPTY:
882 if (HIWORD(wParam) == BN_CLICKED ||
883 HIWORD(wParam) == BN_DOUBLECLICKED)
884 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
885 break;
886 }
887 break;
888 }
889 return GeneralPanelProc (hwnd, msg, wParam, lParam);
890 }
891
892 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
893 WPARAM wParam, LPARAM lParam) {
894 int i;
895
896 switch (msg) {
897 case WM_INITDIALOG:
898 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
899 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
900 {
901 static int tabs[4] = {25, 61, 96, 128};
902 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
903 (LPARAM) tabs);
904 }
905 for (i=0; i<256; i++) {
906 char str[100];
907 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
908 (i>=0x21 && i != 0x7F) ? i : ' ',
909 cfg.wordness[i]);
910 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
911 (LPARAM) str);
912 }
913 break;
914 case WM_COMMAND:
915 switch (LOWORD(wParam)) {
916 case IDC4_MBWINDOWS:
917 case IDC4_MBXTERM:
918 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
919 break;
920 case IDC4_CCSET:
921 {
922 BOOL ok;
923 int i;
924 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
925
926 if (!ok)
927 MessageBeep (0);
928 else {
929 for (i=0; i<256; i++)
930 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
931 i, 0)) {
932 char str[100];
933 cfg.wordness[i] = n;
934 SendDlgItemMessage (hwnd, IDC4_CCLIST,
935 LB_DELETESTRING, i, 0);
936 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
937 (i>=0x21 && i != 0x7F) ? i : ' ',
938 cfg.wordness[i]);
939 SendDlgItemMessage (hwnd, IDC4_CCLIST,
940 LB_INSERTSTRING, i,
941 (LPARAM)str);
942 }
943 }
944 }
945 break;
946 }
947 break;
948 }
949 return GeneralPanelProc (hwnd, msg, wParam, lParam);
950 }
951
952 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
953 WPARAM wParam, LPARAM lParam) {
954 static const char *const colours[] = {
955 "Default Foreground", "Default Bold Foreground",
956 "Default Background", "Default Bold Background",
957 "Cursor Text", "Cursor Colour",
958 "ANSI Black", "ANSI Black Bold",
959 "ANSI Red", "ANSI Red Bold",
960 "ANSI Green", "ANSI Green Bold",
961 "ANSI Yellow", "ANSI Yellow Bold",
962 "ANSI Blue", "ANSI Blue Bold",
963 "ANSI Magenta", "ANSI Magenta Bold",
964 "ANSI Cyan", "ANSI Cyan Bold",
965 "ANSI White", "ANSI White Bold"
966 };
967 static const int permanent[] = {
968 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
969 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
970 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
971 };
972 switch (msg) {
973 case WM_INITDIALOG:
974 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
975 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
976 {
977 int i;
978 for (i=0; i<22; i++)
979 if (cfg.bold_colour || permanent[i])
980 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
981 (LPARAM) colours[i]);
982 }
983 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
984 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
985 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
986 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
987 break;
988 case WM_COMMAND:
989 switch (LOWORD(wParam)) {
990 case IDC5_BOLDCOLOUR:
991 if (HIWORD(wParam) == BN_CLICKED ||
992 HIWORD(wParam) == BN_DOUBLECLICKED) {
993 int n, i;
994 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
995 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
996 if (cfg.bold_colour && n!=22) {
997 for (i=0; i<22; i++)
998 if (!permanent[i])
999 SendDlgItemMessage (hwnd, IDC5_LIST,
1000 LB_INSERTSTRING, i,
1001 (LPARAM) colours[i]);
1002 } else if (!cfg.bold_colour && n!=12) {
1003 for (i=22; i-- ;)
1004 if (!permanent[i])
1005 SendDlgItemMessage (hwnd, IDC5_LIST,
1006 LB_DELETESTRING, i, 0);
1007 }
1008 }
1009 break;
1010 case IDC5_PALETTE:
1011 if (HIWORD(wParam) == BN_CLICKED ||
1012 HIWORD(wParam) == BN_DOUBLECLICKED)
1013 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1014 break;
1015 case IDC5_LIST:
1016 if (HIWORD(wParam) == LBN_DBLCLK ||
1017 HIWORD(wParam) == LBN_SELCHANGE) {
1018 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1019 0, 0);
1020 if (!cfg.bold_colour)
1021 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1022 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1023 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1024 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1025 }
1026 break;
1027 case IDC5_CHANGE:
1028 if (HIWORD(wParam) == BN_CLICKED ||
1029 HIWORD(wParam) == BN_DOUBLECLICKED) {
1030 static CHOOSECOLOR cc;
1031 static DWORD custom[16] = {0}; /* zero initialisers */
1032 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1033 0, 0);
1034 if (!cfg.bold_colour)
1035 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1036 cc.lStructSize = sizeof(cc);
1037 cc.hwndOwner = hwnd;
1038 cc.hInstance = hinst;
1039 cc.lpCustColors = custom;
1040 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1041 cfg.colours[i][2]);
1042 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1043 if (ChooseColor(&cc)) {
1044 cfg.colours[i][0] =
1045 (unsigned char) (cc.rgbResult & 0xFF);
1046 cfg.colours[i][1] =
1047 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1048 cfg.colours[i][2] =
1049 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1050 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1051 FALSE);
1052 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1053 FALSE);
1054 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1055 FALSE);
1056 }
1057 }
1058 break;
1059 }
1060 break;
1061 }
1062 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1063 }
1064
1065 static DLGPROC panelproc[NPANELS] = {
1066 ConnectionProc, KeyboardProc, TerminalProc,
1067 TelnetProc, SshProc, SelectionProc, ColourProc
1068 };
1069 static char *panelids[NPANELS] = {
1070 MAKEINTRESOURCE(IDD_PANEL0),
1071 MAKEINTRESOURCE(IDD_PANEL1),
1072 MAKEINTRESOURCE(IDD_PANEL2),
1073 MAKEINTRESOURCE(IDD_PANEL3),
1074 MAKEINTRESOURCE(IDD_PANEL35),
1075 MAKEINTRESOURCE(IDD_PANEL4),
1076 MAKEINTRESOURCE(IDD_PANEL5)
1077 };
1078 static char *names[NPANELS] = {
1079 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1080 };
1081
1082 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6 };
1083 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6 };
1084
1085 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1086 WPARAM wParam, LPARAM lParam,
1087 int npanels, int *panelnums, HWND *page) {
1088 HWND hw;
1089
1090 switch (msg) {
1091 case WM_INITDIALOG:
1092 { /* centre the window */
1093 RECT rs, rd;
1094
1095 hw = GetDesktopWindow();
1096 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1097 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1098 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1099 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1100 }
1101 *page = NULL;
1102 { /* initialise the tab control */
1103 TC_ITEMHEADER tab;
1104 int i;
1105
1106 hw = GetDlgItem (hwnd, IDC_TAB);
1107 for (i=0; i<npanels; i++) {
1108 tab.mask = TCIF_TEXT;
1109 tab.pszText = names[panelnums[i]];
1110 TabCtrl_InsertItem (hw, i, &tab);
1111 }
1112 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1113 hwnd, panelproc[panelnums[0]]);*/
1114 *page = CreateDialog (hinst, panelids[panelnums[0]],
1115 hwnd, panelproc[panelnums[0]]);
1116 SetWindowLong (*page, GWL_EXSTYLE,
1117 GetWindowLong (*page, GWL_EXSTYLE) |
1118 WS_EX_CONTROLPARENT);
1119 }
1120 SetFocus (*page);
1121 return 0;
1122 case WM_NOTIFY:
1123 if (LOWORD(wParam) == IDC_TAB &&
1124 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1125 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1126 if (*page)
1127 DestroyWindow (*page);
1128 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1129 hwnd, panelproc[panelnums[i]]);*/
1130 *page = CreateDialog (hinst, panelids[panelnums[i]],
1131 hwnd, panelproc[panelnums[i]]);
1132 SetWindowLong (*page, GWL_EXSTYLE,
1133 GetWindowLong (*page, GWL_EXSTYLE) |
1134 WS_EX_CONTROLPARENT);
1135 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1136 return 0;
1137 }
1138 break;
1139 /* case WM_CTLCOLORDLG: */
1140 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1141 case WM_COMMAND:
1142 switch (LOWORD(wParam)) {
1143 case IDOK:
1144 if (*cfg.host)
1145 EndDialog (hwnd, 1);
1146 else
1147 MessageBeep (0);
1148 return 0;
1149 case IDCANCEL:
1150 EndDialog (hwnd, 0);
1151 return 0;
1152 }
1153 return 0;
1154 case WM_CLOSE:
1155 EndDialog (hwnd, 0);
1156 return 0;
1157 }
1158 return 0;
1159 }
1160
1161 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1162 WPARAM wParam, LPARAM lParam) {
1163 #if 0
1164 HWND hw;
1165 int i;
1166 #endif
1167 static HWND page = NULL;
1168
1169 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1170 #if 0
1171 /*
1172 * If the Connection panel is active and the Session List
1173 * box is selected, we treat a press of Open to have an
1174 * implicit press of Load preceding it.
1175 */
1176 hw = GetDlgItem (hwnd, IDC_TAB);
1177 i = TabCtrl_GetCurSel(hw);
1178 if (panelproc[mainp[i]] == ConnectionProc &&
1179 page && implicit_load_ok) {
1180 SendMessage (page, WM_COMMAND,
1181 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1182 }
1183 #endif
1184 }
1185 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1186 EnableWindow(hwnd, 0);
1187 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1188 GetParent(hwnd), AboutProc);
1189 EnableWindow(hwnd, 1);
1190 }
1191 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1192 MAIN_NPANELS, mainp, &page);
1193 }
1194
1195 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1196 WPARAM wParam, LPARAM lParam) {
1197 static HWND page;
1198 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1199 RECONF_NPANELS, reconfp, &page);
1200 }
1201
1202 static void get_sesslist(int allocate) {
1203 static char *buffer;
1204 int buflen, bufsize, i, ret;
1205 char otherbuf[2048];
1206 char *p;
1207 HKEY subkey1;
1208
1209 if (allocate) {
1210 if (RegCreateKey(HKEY_CURRENT_USER,
1211 puttystr, &subkey1) != ERROR_SUCCESS)
1212 return;
1213
1214 buflen = bufsize = 0;
1215 buffer = NULL;
1216 i = 0;
1217 do {
1218 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1219 if (ret == ERROR_SUCCESS) {
1220 bufsize = buflen + 2048;
1221 buffer = srealloc(buffer, bufsize);
1222 unmungestr(otherbuf, buffer+buflen);
1223 buflen += strlen(buffer+buflen)+1;
1224 }
1225 } while (ret == ERROR_SUCCESS);
1226 buffer = srealloc(buffer, buflen+1);
1227 buffer[buflen] = '\0';
1228
1229 p = buffer;
1230 nsessions = 1; /* "Default Settings" counts as one */
1231 while (*p) {
1232 if (strcmp(p, "Default Settings"))
1233 nsessions++;
1234 while (*p) p++;
1235 p++;
1236 }
1237
1238 sessions = smalloc(nsessions * sizeof(char *));
1239 sessions[0] = "Default Settings";
1240 p = buffer;
1241 i = 1;
1242 while (*p) {
1243 if (strcmp(p, "Default Settings"))
1244 sessions[i++] = p;
1245 while (*p) p++;
1246 p++;
1247 }
1248 } else {
1249 sfree (buffer);
1250 sfree (sessions);
1251 }
1252 }
1253
1254 int do_config (void) {
1255 int ret;
1256
1257 get_sesslist(TRUE);
1258 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1259 get_sesslist(FALSE);
1260
1261 return ret;
1262 }
1263
1264 int do_reconfig (HWND hwnd) {
1265 Config backup_cfg;
1266 int ret;
1267
1268 backup_cfg = cfg; /* structure copy */
1269 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1270 if (!ret)
1271 cfg = backup_cfg; /* structure copy */
1272 return ret;
1273 }
1274
1275 void do_defaults (char *session) {
1276 if (session)
1277 load_settings (session, TRUE);
1278 else
1279 load_settings ("Default Settings", FALSE);
1280 }
1281
1282 void lognegot (char *string) {
1283 if (nnegots >= negsize) {
1284 negsize += 64;
1285 negots = srealloc (negots, negsize * sizeof(*negots));
1286 }
1287 negots[nnegots] = smalloc(1+strlen(string));
1288 strcpy (negots[nnegots], string);
1289 nnegots++;
1290 if (logbox)
1291 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1292 0, (LPARAM)string);
1293 }
1294
1295 void shownegot (HWND hwnd) {
1296 if (!logbox) {
1297 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1298 hwnd, LogProc);
1299 ShowWindow (logbox, SW_SHOWNORMAL);
1300 }
1301 }
1302
1303 void showabout (HWND hwnd) {
1304 if (!abtbox) {
1305 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1306 hwnd, AboutProc);
1307 ShowWindow (abtbox, SW_SHOWNORMAL);
1308 }
1309 }
1310
1311 void verify_ssh_host_key(char *host, struct RSAKey *key) {
1312 char *keystr, *otherstr, *mungedhost;
1313 int len;
1314 HKEY rkey;
1315
1316 /*
1317 * Format the key into a string.
1318 */
1319 len = rsastr_len(key);
1320 keystr = malloc(len);
1321 if (!keystr)
1322 fatalbox("Out of memory");
1323 rsastr_fmt(keystr, key);
1324
1325 /*
1326 * Now read a saved key in from the registry and see what it
1327 * says.
1328 */
1329 otherstr = malloc(len);
1330 mungedhost = malloc(3*strlen(host)+1);
1331 if (!otherstr || !mungedhost)
1332 fatalbox("Out of memory");
1333
1334 mungestr(host, mungedhost);
1335
1336 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1337 &rkey) != ERROR_SUCCESS) {
1338 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1339 "in the registry. There is thus no way to tell\n"
1340 "if the remote host is what you think it is.\n"
1341 "Connect anyway?", "PuTTY Problem",
1342 MB_ICONWARNING | MB_YESNO) == IDNO)
1343 exit(0);
1344 } else {
1345 DWORD readlen = len;
1346 DWORD type;
1347 int ret;
1348
1349 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1350 &type, otherstr, &readlen);
1351
1352 if (ret == ERROR_MORE_DATA ||
1353 (ret == ERROR_SUCCESS && type == REG_SZ &&
1354 strcmp(otherstr, keystr))) {
1355 if (MessageBox(NULL,
1356 "This host's host key is different from the\n"
1357 "one cached in the registry! Someone may be\n"
1358 "impersonating this host for malicious reasons;\n"
1359 "alternatively, the host key may have changed\n"
1360 "due to sloppy system administration.\n"
1361 "Replace key in registry and connect?",
1362 "PuTTY: Security Warning",
1363 MB_ICONWARNING | MB_YESNO) == IDNO)
1364 exit(0);
1365 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1366 strlen(keystr)+1);
1367 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1368 if (MessageBox(NULL,
1369 "This host's host key is not cached in the\n"
1370 "registry. Do you want to add it to the cache\n"
1371 "and carry on connecting?",
1372 "PuTTY: New Host",
1373 MB_ICONWARNING | MB_YESNO) == IDNO)
1374 exit(0);
1375 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1376 strlen(keystr)+1);
1377 }
1378
1379 RegCloseKey(rkey);
1380 }
1381 }