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