13 #define MAIN_NPANELS 8
14 #define RECONF_NPANELS 5
16 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
18 static char **negots = NULL;
19 static int nnegots = 0, negsize = 0;
20 static HWND logbox = NULL, abtbox = NULL;
22 static char hex[16] = "0123456789ABCDEF";
24 static void mungestr(char *in, char *out) {
28 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
29 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
31 *out++ = hex[((unsigned char)*in) >> 4];
32 *out++ = hex[((unsigned char)*in) & 15];
42 static void unmungestr(char *in, char *out) {
44 if (*in == '%' && in[1] && in[2]) {
47 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
48 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
59 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
60 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
63 static void wppi(HKEY key, LPCTSTR name, int value) {
64 RegSetValueEx(key, name, 0, REG_DWORD,
65 (CONST BYTE *)&value, sizeof(value));
68 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
69 LPTSTR val, int len) {
74 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
76 strncpy(val, def, len);
81 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
82 DWORD type, val, size;
86 RegQueryValueEx(key, name, 0, &type,
87 (BYTE *)&val, &size) != ERROR_SUCCESS ||
88 size != sizeof(val) || type != REG_DWORD)
94 static HINSTANCE hinst;
98 static void save_settings (char *section, int do_host) {
100 HKEY subkey1, sesskey;
103 p = malloc(3*strlen(section)+1);
104 mungestr(section, p);
106 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
107 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
112 RegCloseKey(subkey1);
114 wppi (sesskey, "Present", 1);
116 wpps (sesskey, "HostName", cfg.host);
117 wppi (sesskey, "PortNumber", cfg.port);
118 wpps (sesskey, "Protocol",
119 cfg.protocol == PROT_SSH ? "ssh" :
120 cfg.protocol == PROT_TELNET ? "telnet" : "raw" );
122 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
123 wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
124 wpps (sesskey, "TerminalType", cfg.termtype);
125 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
127 char buf[2*sizeof(cfg.environmt)], *p, *q;
133 if (c == '=' || c == ',' || c == '\\')
143 wpps (sesskey, "Environment", buf);
145 wpps (sesskey, "UserName", cfg.username);
146 wppi (sesskey, "NoPTY", cfg.nopty);
147 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
148 cfg.cipher == CIPHER_DES ? "des" : "3des");
149 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
150 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
151 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
152 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
153 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
154 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
155 wppi (sesskey, "ScrollbackLines", cfg.savelines);
156 wppi (sesskey, "DECOriginMode", cfg.dec_om);
157 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
158 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
159 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
160 wppi (sesskey, "TermWidth", cfg.width);
161 wppi (sesskey, "TermHeight", cfg.height);
162 wpps (sesskey, "Font", cfg.font);
163 wppi (sesskey, "FontIsBold", cfg.fontisbold);
164 wppi (sesskey, "FontCharSet", cfg.fontcharset);
165 wppi (sesskey, "FontHeight", cfg.fontheight);
166 wppi (sesskey, "FontVTMode", cfg.vtmode);
167 wppi (sesskey, "TryPalette", cfg.try_palette);
168 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
169 for (i=0; i<22; i++) {
170 char buf[20], buf2[30];
171 sprintf(buf, "Colour%d", i);
172 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
173 cfg.colours[i][1], cfg.colours[i][2]);
174 wpps (sesskey, buf, buf2);
176 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
177 for (i=0; i<256; i+=32) {
178 char buf[20], buf2[256];
180 sprintf(buf, "Wordness%d", i);
182 for (j=i; j<i+32; j++) {
183 sprintf(buf2+strlen(buf2), "%s%d",
184 (*buf2 ? "," : ""), cfg.wordness[j]);
186 wpps (sesskey, buf, buf2);
188 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
189 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
191 RegCloseKey(sesskey);
194 static void del_session (char *section) {
198 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
201 p = malloc(3*strlen(section)+1);
202 mungestr(section, p);
203 RegDeleteKey(subkey1, p);
206 RegCloseKey(subkey1);
209 static void load_settings (char *section, int do_host) {
211 HKEY subkey1, sesskey;
215 p = malloc(3*strlen(section)+1);
216 mungestr(section, p);
218 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
221 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
224 RegCloseKey(subkey1);
229 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
230 gppi (sesskey, "PortNumber", default_port, &cfg.port);
231 gpps (sesskey, "Protocol", "default", prot, 10);
232 if (!strcmp(prot, "ssh"))
233 cfg.protocol = PROT_SSH;
234 else if (!strcmp(prot, "telnet"))
235 cfg.protocol = PROT_TELNET;
236 else if (!strcmp(prot, "raw"))
237 cfg.protocol = PROT_RAW;
239 cfg.protocol = default_protocol;
241 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
242 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
243 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
244 sizeof(cfg.termtype));
245 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
246 sizeof(cfg.termspeed));
248 char buf[2*sizeof(cfg.environmt)], *p, *q;
249 gpps (sesskey, "Environment", "", buf, sizeof(buf));
253 while (*p && *p != ',') {
266 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
267 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
270 gpps (sesskey, "Cipher", "3des", cipher, 10);
271 if (!strcmp(cipher, "blowfish"))
272 cfg.cipher = CIPHER_BLOWFISH;
273 else if (!strcmp(cipher, "des"))
274 cfg.cipher = CIPHER_DES;
276 cfg.cipher = CIPHER_3DES;
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);
287 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
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, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
294 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
295 gppi (sesskey, "FontVTMode", VT_POORMAN, &cfg.vtmode);
296 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
297 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
298 for (i=0; i<22; i++) {
299 static char *defaults[] = {
300 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
301 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
302 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
303 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
304 "85,255,255", "187,187,187", "255,255,255"
306 char buf[20], buf2[30];
307 sprintf(buf, "Colour%d", i);
308 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
309 sscanf(buf2, "%d,%d,%d", &cfg.colours[i][0],
310 &cfg.colours[i][1], &cfg.colours[i][2]);
312 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
313 for (i=0; i<256; i+=32) {
314 static char *defaults[] = {
315 "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",
316 "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",
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,2",
318 "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",
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 "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",
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 "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"
324 char buf[20], buf2[256], *p;
326 sprintf(buf, "Wordness%d", i);
327 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
329 for (j=i; j<i+32; j++) {
331 while (*p && *p != ',') p++;
332 if (*p == ',') *p++ = '\0';
333 cfg.wordness[j] = atoi(q);
336 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
337 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
339 RegCloseKey(sesskey);
342 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
345 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
350 static int CALLBACK LogProc (HWND hwnd, UINT msg,
351 WPARAM wParam, LPARAM lParam) {
356 for (i=0; i<nnegots; i++)
357 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
358 0, (LPARAM)negots[i]);
360 /* case WM_CTLCOLORDLG: */
361 /* return (int) GetStockObject (LTGRAY_BRUSH); */
363 switch (LOWORD(wParam)) {
366 DestroyWindow (hwnd);
372 DestroyWindow (hwnd);
378 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
379 WPARAM wParam, LPARAM lParam) {
384 switch (LOWORD(wParam)) {
387 DestroyWindow (hwnd);
393 DestroyWindow (hwnd);
399 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
400 WPARAM wParam, LPARAM lParam) {
403 SetDlgItemText (hwnd, IDA_VERSION, ver);
405 /* case WM_CTLCOLORDLG: */
406 /* return (int) GetStockObject (LTGRAY_BRUSH); */
407 /* case WM_CTLCOLORSTATIC: */
408 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
409 /* return (int) GetStockObject (LTGRAY_BRUSH); */
411 switch (LOWORD(wParam)) {
414 DestroyWindow (hwnd);
417 EnableWindow(hwnd, 0);
418 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
420 EnableWindow(hwnd, 1);
426 DestroyWindow (hwnd);
432 static int GeneralPanelProc (HWND hwnd, UINT msg,
433 WPARAM wParam, LPARAM lParam) {
436 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
438 /* case WM_CTLCOLORDLG: */
439 /* return (int) GetStockObject (LTGRAY_BRUSH); */
440 /* case WM_CTLCOLORSTATIC: */
441 /* case WM_CTLCOLORBTN: */
442 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
443 /* return (int) GetStockObject (LTGRAY_BRUSH); */
445 DestroyWindow (hwnd);
451 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
452 WPARAM wParam, LPARAM lParam) {
457 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
458 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
459 for (i = 0; i < nsessions; i++)
460 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
461 0, (LPARAM) (sessions[i]));
462 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
463 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
464 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
465 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
466 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
470 * Button release should trigger WM_OK if there was a
471 * previous double click on the session list.
475 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
478 switch (LOWORD(wParam)) {
479 case IDC0_PROTTELNET:
482 if (HIWORD(wParam) == BN_CLICKED ||
483 HIWORD(wParam) == BN_DOUBLECLICKED) {
484 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
485 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
486 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
487 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
488 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
489 cfg.port = i ? 22 : 23;
490 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
495 if (HIWORD(wParam) == EN_CHANGE)
496 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
500 if (HIWORD(wParam) == EN_CHANGE)
501 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
504 if (HIWORD(wParam) == BN_CLICKED ||
505 HIWORD(wParam) == BN_DOUBLECLICKED)
506 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
509 if (HIWORD(wParam) == BN_CLICKED ||
510 HIWORD(wParam) == BN_DOUBLECLICKED)
511 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
514 if (HIWORD(wParam) == EN_CHANGE)
515 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
519 if (HIWORD(wParam) == BN_CLICKED ||
520 HIWORD(wParam) == BN_DOUBLECLICKED) {
525 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
527 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
533 strcpy (str, sessions[n]);
535 save_settings (str, !!strcmp(str, "Default Settings"));
536 get_sesslist (FALSE);
538 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
540 for (i = 0; i < nsessions; i++)
541 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
542 0, (LPARAM) (sessions[i]));
543 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
549 if (LOWORD(wParam) == IDC0_SESSLOAD &&
550 HIWORD(wParam) != BN_CLICKED &&
551 HIWORD(wParam) != BN_DOUBLECLICKED)
553 if (LOWORD(wParam) == IDC0_SESSLIST &&
554 HIWORD(wParam) != LBN_DBLCLK)
557 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
563 load_settings (sessions[n],
564 !!strcmp(sessions[n], "Default Settings"));
565 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
566 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
567 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
568 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
569 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
570 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
571 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
572 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
575 if (LOWORD(wParam) == IDC0_SESSLIST) {
577 * A double-click on a saved session should
578 * actually start the session, not just load it.
579 * Unless it's Default Settings or some other
580 * host-less set of saved settings.
589 if (HIWORD(wParam) == BN_CLICKED ||
590 HIWORD(wParam) == BN_DOUBLECLICKED) {
591 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
593 if (n == LB_ERR || n == 0) {
597 del_session(sessions[n]);
598 get_sesslist (FALSE);
600 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
602 for (i = 0; i < nsessions; i++)
603 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
604 0, (LPARAM) (sessions[i]));
605 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
610 return GeneralPanelProc (hwnd, msg, wParam, lParam);
613 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
614 WPARAM wParam, LPARAM lParam) {
617 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
618 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
619 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
620 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
621 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
622 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
623 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
624 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
625 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPAPPLIC,
626 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
629 if (HIWORD(wParam) == BN_CLICKED ||
630 HIWORD(wParam) == BN_DOUBLECLICKED)
631 switch (LOWORD(wParam)) {
634 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
638 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
642 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
646 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
650 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
654 return GeneralPanelProc (hwnd, msg, wParam, lParam);
657 static void fmtfont (char *buf) {
658 sprintf (buf, "Font: %s, ", cfg.font);
660 strcat(buf, "bold, ");
661 if (cfg.fontheight == 0)
662 strcat (buf, "default height");
664 sprintf (buf+strlen(buf), "%d-%s",
665 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
666 (cfg.fontheight < 0 ? "pixel" : "point"));
669 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
670 WPARAM wParam, LPARAM lParam) {
673 char fontstatic[256];
677 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
678 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
679 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
680 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
681 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
682 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
683 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
684 fmtfont (fontstatic);
685 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
686 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
687 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
688 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
689 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
693 switch (LOWORD(wParam)) {
695 if (HIWORD(wParam) == BN_CLICKED ||
696 HIWORD(wParam) == BN_DOUBLECLICKED)
697 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
700 if (HIWORD(wParam) == BN_CLICKED ||
701 HIWORD(wParam) == BN_DOUBLECLICKED)
702 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
705 if (HIWORD(wParam) == BN_CLICKED ||
706 HIWORD(wParam) == BN_DOUBLECLICKED)
707 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
710 if (HIWORD(wParam) == BN_CLICKED ||
711 HIWORD(wParam) == BN_DOUBLECLICKED)
712 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
715 if (HIWORD(wParam) == EN_CHANGE)
716 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
719 if (HIWORD(wParam) == EN_CHANGE)
720 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
723 if (HIWORD(wParam) == EN_CHANGE)
724 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
726 case IDC2_CHOOSEFONT:
727 lf.lfHeight = cfg.fontheight;
728 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
729 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
730 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
731 lf.lfCharSet = cfg.fontcharset;
732 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
733 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
734 lf.lfQuality = DEFAULT_QUALITY;
735 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
736 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
737 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
739 cf.lStructSize = sizeof(cf);
742 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
743 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
745 if (ChooseFont (&cf)) {
746 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
747 cfg.font[sizeof(cfg.font)-1] = '\0';
748 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
749 cfg.fontcharset = lf.lfCharSet;
750 cfg.fontheight = lf.lfHeight;
751 fmtfont (fontstatic);
752 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
755 case IDC2_VTXWINDOWS:
760 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
761 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
762 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
768 return GeneralPanelProc (hwnd, msg, wParam, lParam);
771 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
772 WPARAM wParam, LPARAM lParam) {
777 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
778 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
779 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
781 char *p = cfg.environmt;
783 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
788 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
789 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
792 switch (LOWORD(wParam)) {
794 if (HIWORD(wParam) == EN_CHANGE)
795 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
796 sizeof(cfg.termtype)-1);
799 if (HIWORD(wParam) == EN_CHANGE)
800 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
801 sizeof(cfg.termspeed)-1);
804 if (HIWORD(wParam) == EN_CHANGE)
805 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
806 sizeof(cfg.username)-1);
810 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
813 if (HIWORD(wParam) == BN_CLICKED ||
814 HIWORD(wParam) == BN_DOUBLECLICKED) {
815 char str[sizeof(cfg.environmt)];
817 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
822 p = str + strlen(str);
824 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
834 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
836 p[strlen(str)+1] = '\0';
837 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
839 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
840 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
842 MessageBox(hwnd, "Environment too big", "PuTTY Error",
843 MB_OK | MB_ICONERROR);
848 if (HIWORD(wParam) != BN_CLICKED &&
849 HIWORD(wParam) != BN_DOUBLECLICKED)
851 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
857 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
884 return GeneralPanelProc (hwnd, msg, wParam, lParam);
887 static int CALLBACK SshProc (HWND hwnd, UINT msg,
888 WPARAM wParam, LPARAM lParam) {
891 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
892 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
893 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
894 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
895 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
896 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
901 switch (LOWORD(wParam)) {
903 if (HIWORD(wParam) == EN_CHANGE)
904 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
905 sizeof(cfg.termtype)-1);
908 if (HIWORD(wParam) == EN_CHANGE)
909 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
910 sizeof(cfg.username)-1);
913 if (HIWORD(wParam) == BN_CLICKED ||
914 HIWORD(wParam) == BN_DOUBLECLICKED)
915 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
917 case IDC3_CIPHER3DES:
918 case IDC3_CIPHERBLOWF:
920 if (HIWORD(wParam) == BN_CLICKED ||
921 HIWORD(wParam) == BN_DOUBLECLICKED) {
922 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
923 cfg.cipher = CIPHER_3DES;
924 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
925 cfg.cipher = CIPHER_BLOWFISH;
926 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
927 cfg.cipher = CIPHER_DES;
933 return GeneralPanelProc (hwnd, msg, wParam, lParam);
936 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
937 WPARAM wParam, LPARAM lParam) {
942 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
943 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
945 static int tabs[4] = {25, 61, 96, 128};
946 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
949 for (i=0; i<256; i++) {
951 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
952 (i>=0x21 && i != 0x7F) ? i : ' ',
954 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
959 switch (LOWORD(wParam)) {
962 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
968 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
973 for (i=0; i<256; i++)
974 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
978 SendDlgItemMessage (hwnd, IDC4_CCLIST,
979 LB_DELETESTRING, i, 0);
980 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
981 (i>=0x21 && i != 0x7F) ? i : ' ',
983 SendDlgItemMessage (hwnd, IDC4_CCLIST,
993 return GeneralPanelProc (hwnd, msg, wParam, lParam);
996 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
997 WPARAM wParam, LPARAM lParam) {
998 static const char *const colours[] = {
999 "Default Foreground", "Default Bold Foreground",
1000 "Default Background", "Default Bold Background",
1001 "Cursor Text", "Cursor Colour",
1002 "ANSI Black", "ANSI Black Bold",
1003 "ANSI Red", "ANSI Red Bold",
1004 "ANSI Green", "ANSI Green Bold",
1005 "ANSI Yellow", "ANSI Yellow Bold",
1006 "ANSI Blue", "ANSI Blue Bold",
1007 "ANSI Magenta", "ANSI Magenta Bold",
1008 "ANSI Cyan", "ANSI Cyan Bold",
1009 "ANSI White", "ANSI White Bold"
1011 static const int permanent[] = {
1012 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1013 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1014 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1018 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1019 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1022 for (i=0; i<22; i++)
1023 if (cfg.bold_colour || permanent[i])
1024 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1025 (LPARAM) colours[i]);
1027 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1028 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1029 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1030 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1033 switch (LOWORD(wParam)) {
1034 case IDC5_BOLDCOLOUR:
1035 if (HIWORD(wParam) == BN_CLICKED ||
1036 HIWORD(wParam) == BN_DOUBLECLICKED) {
1038 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1039 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1040 if (cfg.bold_colour && n!=22) {
1041 for (i=0; i<22; i++)
1043 SendDlgItemMessage (hwnd, IDC5_LIST,
1045 (LPARAM) colours[i]);
1046 } else if (!cfg.bold_colour && n!=12) {
1049 SendDlgItemMessage (hwnd, IDC5_LIST,
1050 LB_DELETESTRING, i, 0);
1055 if (HIWORD(wParam) == BN_CLICKED ||
1056 HIWORD(wParam) == BN_DOUBLECLICKED)
1057 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1060 if (HIWORD(wParam) == LBN_DBLCLK ||
1061 HIWORD(wParam) == LBN_SELCHANGE) {
1062 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1064 if (!cfg.bold_colour)
1065 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1066 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1067 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1068 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1072 if (HIWORD(wParam) == BN_CLICKED ||
1073 HIWORD(wParam) == BN_DOUBLECLICKED) {
1074 static CHOOSECOLOR cc;
1075 static DWORD custom[16] = {0}; /* zero initialisers */
1076 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1078 if (!cfg.bold_colour)
1079 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1080 cc.lStructSize = sizeof(cc);
1081 cc.hwndOwner = hwnd;
1082 cc.hInstance = hinst;
1083 cc.lpCustColors = custom;
1084 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1086 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1087 if (ChooseColor(&cc)) {
1089 (unsigned char) (cc.rgbResult & 0xFF);
1091 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1093 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1094 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1096 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1098 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1106 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1109 static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
1110 WPARAM wParam, LPARAM lParam) {
1113 CheckDlgButton (hwnd, IDC6_ENABLEKOIWINXLAT, cfg.xlat_enablekoiwin);
1114 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1116 switch (LOWORD(wParam)) {
1117 case IDC6_ENABLEKOIWINXLAT:
1118 if (HIWORD(wParam) == BN_CLICKED ||
1119 HIWORD(wParam) == BN_DOUBLECLICKED) {
1120 cfg.xlat_enablekoiwin =
1121 IsDlgButtonChecked (hwnd, IDC6_ENABLEKOIWINXLAT);
1124 case IDC6_CAPSLOCKCYR:
1125 if (HIWORD(wParam) == BN_CLICKED ||
1126 HIWORD(wParam) == BN_DOUBLECLICKED) {
1127 cfg.xlat_capslockcyr =
1128 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1133 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1136 static DLGPROC panelproc[NPANELS] = {
1137 ConnectionProc, KeyboardProc, TerminalProc,
1138 TelnetProc, SshProc, SelectionProc, ColourProc, LanguageProc
1140 static char *panelids[NPANELS] = {
1141 MAKEINTRESOURCE(IDD_PANEL0),
1142 MAKEINTRESOURCE(IDD_PANEL1),
1143 MAKEINTRESOURCE(IDD_PANEL2),
1144 MAKEINTRESOURCE(IDD_PANEL3),
1145 MAKEINTRESOURCE(IDD_PANEL35),
1146 MAKEINTRESOURCE(IDD_PANEL4),
1147 MAKEINTRESOURCE(IDD_PANEL5),
1148 MAKEINTRESOURCE(IDD_PANEL6)
1151 static char *names[NPANELS] = {
1152 "Connection", "Keyboard", "Terminal", "Telnet",
1153 "SSH", "Selection", "Colours", "Language"
1156 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1157 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1159 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1160 WPARAM wParam, LPARAM lParam,
1161 int npanels, int *panelnums, HWND *page) {
1166 { /* centre the window */
1169 hw = GetDesktopWindow();
1170 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1171 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1172 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1173 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1176 { /* initialise the tab control */
1180 hw = GetDlgItem (hwnd, IDC_TAB);
1181 for (i=0; i<npanels; i++) {
1182 tab.mask = TCIF_TEXT;
1183 tab.pszText = names[panelnums[i]];
1184 TabCtrl_InsertItem (hw, i, &tab);
1186 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1187 hwnd, panelproc[panelnums[0]]);*/
1188 *page = CreateDialog (hinst, panelids[panelnums[0]],
1189 hwnd, panelproc[panelnums[0]]);
1190 SetWindowLong (*page, GWL_EXSTYLE,
1191 GetWindowLong (*page, GWL_EXSTYLE) |
1192 WS_EX_CONTROLPARENT);
1197 if (LOWORD(wParam) == IDC_TAB &&
1198 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1199 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1201 DestroyWindow (*page);
1202 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1203 hwnd, panelproc[panelnums[i]]);*/
1204 *page = CreateDialog (hinst, panelids[panelnums[i]],
1205 hwnd, panelproc[panelnums[i]]);
1206 SetWindowLong (*page, GWL_EXSTYLE,
1207 GetWindowLong (*page, GWL_EXSTYLE) |
1208 WS_EX_CONTROLPARENT);
1209 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1213 /* case WM_CTLCOLORDLG: */
1214 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1216 switch (LOWORD(wParam)) {
1219 EndDialog (hwnd, 1);
1224 EndDialog (hwnd, 0);
1229 EndDialog (hwnd, 0);
1235 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1236 WPARAM wParam, LPARAM lParam) {
1241 static HWND page = NULL;
1243 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1246 * If the Connection panel is active and the Session List
1247 * box is selected, we treat a press of Open to have an
1248 * implicit press of Load preceding it.
1250 hw = GetDlgItem (hwnd, IDC_TAB);
1251 i = TabCtrl_GetCurSel(hw);
1252 if (panelproc[mainp[i]] == ConnectionProc &&
1253 page && implicit_load_ok) {
1254 SendMessage (page, WM_COMMAND,
1255 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1259 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1260 EnableWindow(hwnd, 0);
1261 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1262 GetParent(hwnd), AboutProc);
1263 EnableWindow(hwnd, 1);
1265 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1266 MAIN_NPANELS, mainp, &page);
1269 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1270 WPARAM wParam, LPARAM lParam) {
1272 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1273 RECONF_NPANELS, reconfp, &page);
1276 void get_sesslist(int allocate) {
1277 static char *buffer;
1278 int buflen, bufsize, i, ret;
1279 char otherbuf[2048];
1284 if (RegCreateKey(HKEY_CURRENT_USER,
1285 puttystr, &subkey1) != ERROR_SUCCESS)
1288 buflen = bufsize = 0;
1292 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1293 if (ret == ERROR_SUCCESS) {
1294 bufsize = buflen + 2048;
1295 buffer = srealloc(buffer, bufsize);
1296 unmungestr(otherbuf, buffer+buflen);
1297 buflen += strlen(buffer+buflen)+1;
1299 } while (ret == ERROR_SUCCESS);
1300 buffer = srealloc(buffer, buflen+1);
1301 buffer[buflen] = '\0';
1304 nsessions = 1; /* "Default Settings" counts as one */
1306 if (strcmp(p, "Default Settings"))
1312 sessions = smalloc(nsessions * sizeof(char *));
1313 sessions[0] = "Default Settings";
1317 if (strcmp(p, "Default Settings"))
1328 int do_config (void) {
1332 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1333 get_sesslist(FALSE);
1338 int do_reconfig (HWND hwnd) {
1342 backup_cfg = cfg; /* structure copy */
1343 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1345 cfg = backup_cfg; /* structure copy */
1349 void do_defaults (char *session) {
1351 load_settings (session, TRUE);
1353 load_settings ("Default Settings", FALSE);
1356 void lognegot (char *string) {
1357 if (nnegots >= negsize) {
1359 negots = srealloc (negots, negsize * sizeof(*negots));
1361 negots[nnegots] = smalloc(1+strlen(string));
1362 strcpy (negots[nnegots], string);
1365 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1369 void shownegot (HWND hwnd) {
1371 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1373 ShowWindow (logbox, SW_SHOWNORMAL);
1377 void showabout (HWND hwnd) {
1379 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1381 ShowWindow (abtbox, SW_SHOWNORMAL);
1385 void verify_ssh_host_key(char *host, struct RSAKey *key) {
1386 char *keystr, *otherstr, *mungedhost;
1391 * Format the key into a string.
1393 len = rsastr_len(key);
1394 keystr = malloc(len);
1396 fatalbox("Out of memory");
1397 rsastr_fmt(keystr, key);
1400 * Now read a saved key in from the registry and see what it
1403 otherstr = malloc(len);
1404 mungedhost = malloc(3*strlen(host)+1);
1405 if (!otherstr || !mungedhost)
1406 fatalbox("Out of memory");
1408 mungestr(host, mungedhost);
1410 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1411 &rkey) != ERROR_SUCCESS) {
1412 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1413 "in the registry. There is thus no way to tell\n"
1414 "if the remote host is what you think it is.\n"
1415 "Connect anyway?", "PuTTY Problem",
1416 MB_ICONWARNING | MB_YESNO) == IDNO)
1419 DWORD readlen = len;
1423 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1424 &type, otherstr, &readlen);
1426 if (ret == ERROR_MORE_DATA ||
1427 (ret == ERROR_SUCCESS && type == REG_SZ &&
1428 strcmp(otherstr, keystr))) {
1429 if (MessageBox(NULL,
1430 "This host's host key is different from the\n"
1431 "one cached in the registry! Someone may be\n"
1432 "impersonating this host for malicious reasons;\n"
1433 "alternatively, the host key may have changed\n"
1434 "due to sloppy system administration.\n"
1435 "Replace key in registry and connect?",
1436 "PuTTY: Security Warning",
1437 MB_ICONWARNING | MB_YESNO) == IDNO)
1439 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1441 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1442 if (MessageBox(NULL,
1443 "This host's host key is not cached in the\n"
1444 "registry. Do you want to add it to the cache\n"
1445 "and carry on connecting?",
1447 MB_ICONWARNING | MB_YESNO) == IDNO)
1449 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,