13 #define MAIN_NPANELS 7
14 #define RECONF_NPANELS 4
16 static const char *const puttystr
= PUTTY_REG_POS
"\\Sessions";
18 static void get_sesslist(int allocate
);
20 static char **negots
= NULL
;
21 static int nnegots
= 0, negsize
= 0;
22 static HWND logbox
= NULL
, abtbox
= NULL
;
24 static char hex
[16] = "0123456789ABCDEF";
26 static void mungestr(char *in
, char *out
) {
30 if (*in
== ' ' || *in
== '\\' || *in
== '*' || *in
== '?' ||
31 *in
== '%' || *in
< ' ' || *in
> '~' || (*in
== '.' && !candot
)) {
33 *out
++ = hex
[((unsigned char)*in
) >> 4];
34 *out
++ = hex
[((unsigned char)*in
) & 15];
44 static void unmungestr(char *in
, char *out
) {
46 if (*in
== '%' && in
[1] && in
[2]) {
49 i
= in
[1] - '0'; i
-= (i
> 9 ?
7 : 0);
50 j
= in
[2] - '0'; j
-= (j
> 9 ?
7 : 0);
61 static void wpps(HKEY key
, LPCTSTR name
, LPCTSTR value
) {
62 RegSetValueEx(key
, name
, 0, REG_SZ
, value
, 1+strlen(value
));
65 static void wppi(HKEY key
, LPCTSTR name
, int value
) {
66 RegSetValueEx(key
, name
, 0, REG_DWORD
,
67 (CONST BYTE
*)&value
, sizeof(value
));
70 static void gpps(HKEY key
, LPCTSTR name
, LPCTSTR def
,
71 LPTSTR val
, int len
) {
76 RegQueryValueEx(key
, name
, 0, &type
, val
, &size
) != ERROR_SUCCESS
||
78 strncpy(val
, def
, len
);
83 static void gppi(HKEY key
, LPCTSTR name
, int def
, int *i
) {
84 DWORD type
, val
, size
;
88 RegQueryValueEx(key
, name
, 0, &type
,
89 (BYTE
*)&val
, &size
) != ERROR_SUCCESS
||
90 size
!= sizeof(val
) || type
!= REG_DWORD
)
96 static HINSTANCE hinst
;
98 static char **sessions
;
101 static int readytogo
;
103 static void save_settings (char *section
, int do_host
) {
105 HKEY subkey1
, sesskey
;
108 p
= malloc(3*strlen(section
)+1);
109 mungestr(section
, p
);
111 if (RegCreateKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
)!=ERROR_SUCCESS
||
112 RegCreateKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
117 RegCloseKey(subkey1
);
119 wppi (sesskey
, "Present", 1);
121 wpps (sesskey
, "HostName", cfg
.host
);
122 wppi (sesskey
, "PortNumber", cfg
.port
);
123 wpps (sesskey
, "Protocol",
124 cfg
.protocol
== PROT_SSH ?
"ssh" : "telnet");
126 wppi (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
127 wpps (sesskey
, "TerminalType", cfg
.termtype
);
128 wpps (sesskey
, "TerminalSpeed", cfg
.termspeed
);
130 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
136 if (c
== '=' || c
== ',' || c
== '\\')
146 wpps (sesskey
, "Environment", buf
);
148 wpps (sesskey
, "UserName", cfg
.username
);
149 wppi (sesskey
, "NoPTY", cfg
.nopty
);
150 wpps (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
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
);
178 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
179 for (i
=0; i
<256; i
+=32) {
180 char buf
[20], buf2
[256];
182 sprintf(buf
, "Wordness%d", i
);
184 for (j
=i
; j
<i
+32; j
++) {
185 sprintf(buf2
+strlen(buf2
), "%s%d",
186 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
188 wpps (sesskey
, buf
, buf2
);
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
;
214 p
= malloc(3*strlen(section
)+1);
215 mungestr(section
, p
);
217 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
220 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
223 RegCloseKey(subkey1
);
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
;
236 cfg
.protocol
= PROT_TELNET
;
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
));
247 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
248 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
252 while (*p
&& *p
!= ',') {
265 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
266 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
269 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
270 if (!strcmp(cipher
, "blowfish"))
271 cfg
.cipher
= CIPHER_BLOWFISH
;
273 cfg
.cipher
= CIPHER_3DES
;
275 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
276 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
277 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
278 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.linux_funkeys
);
279 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
280 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
281 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
282 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
283 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
284 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
285 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
286 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
287 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
288 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
289 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
290 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
291 gppi (sesskey
, "FontVTMode", VT_POORMAN
, &cfg
.vtmode
);
292 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
293 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
294 for (i
=0; i
<22; i
++) {
295 static char *defaults
[] = {
296 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
297 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
298 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
299 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
300 "85,255,255", "187,187,187", "255,255,255"
302 char buf
[20], buf2
[30];
303 sprintf(buf
, "Colour%d", i
);
304 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
305 sscanf(buf2
, "%d,%d,%d", &cfg
.colours
[i
][0],
306 &cfg
.colours
[i
][1], &cfg
.colours
[i
][2]);
308 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
309 for (i
=0; i
<256; i
+=32) {
310 static char *defaults
[] = {
311 "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",
312 "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",
313 "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",
314 "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",
315 "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",
316 "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",
317 "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",
318 "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"
320 char buf
[20], buf2
[256], *p
;
322 sprintf(buf
, "Wordness%d", i
);
323 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
325 for (j
=i
; j
<i
+32; j
++) {
327 while (*p
&& *p
!= ',') p
++;
328 if (*p
== ',') *p
++ = '\0';
329 cfg
.wordness
[j
] = atoi(q
);
332 RegCloseKey(sesskey
);
335 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
338 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
343 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
344 WPARAM wParam
, LPARAM lParam
) {
349 for (i
=0; i
<nnegots
; i
++)
350 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
351 0, (LPARAM
)negots
[i
]);
353 /* case WM_CTLCOLORDLG: */
354 /* return (int) GetStockObject (LTGRAY_BRUSH); */
356 switch (LOWORD(wParam
)) {
359 DestroyWindow (hwnd
);
365 DestroyWindow (hwnd
);
371 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
372 WPARAM wParam
, LPARAM lParam
) {
377 switch (LOWORD(wParam
)) {
380 DestroyWindow (hwnd
);
386 DestroyWindow (hwnd
);
392 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
393 WPARAM wParam
, LPARAM lParam
) {
396 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
398 /* case WM_CTLCOLORDLG: */
399 /* return (int) GetStockObject (LTGRAY_BRUSH); */
400 /* case WM_CTLCOLORSTATIC: */
401 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
402 /* return (int) GetStockObject (LTGRAY_BRUSH); */
404 switch (LOWORD(wParam
)) {
407 DestroyWindow (hwnd
);
410 EnableWindow(hwnd
, 0);
411 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
413 EnableWindow(hwnd
, 1);
419 DestroyWindow (hwnd
);
425 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
426 WPARAM wParam
, LPARAM lParam
) {
429 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
431 /* case WM_CTLCOLORDLG: */
432 /* return (int) GetStockObject (LTGRAY_BRUSH); */
433 /* case WM_CTLCOLORSTATIC: */
434 /* case WM_CTLCOLORBTN: */
435 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
436 /* return (int) GetStockObject (LTGRAY_BRUSH); */
438 DestroyWindow (hwnd
);
444 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
445 WPARAM wParam
, LPARAM lParam
) {
450 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
451 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
452 for (i
= 0; i
< nsessions
; i
++)
453 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
454 0, (LPARAM
) (sessions
[i
]));
455 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
456 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
: IDC0_PROTTELNET
);
457 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
461 * Button release should trigger WM_OK if there was a
462 * previous double click on the session list.
466 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
469 switch (LOWORD(wParam
)) {
470 case IDC0_PROTTELNET
:
472 if (HIWORD(wParam
) == BN_CLICKED
||
473 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
474 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
475 cfg
.protocol
= i ? PROT_SSH
: PROT_TELNET
;
476 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
477 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
478 cfg
.port
= i ?
22 : 23;
479 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
484 if (HIWORD(wParam
) == EN_CHANGE
)
485 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
489 if (HIWORD(wParam
) == EN_CHANGE
)
490 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
493 if (HIWORD(wParam
) == BN_CLICKED
||
494 HIWORD(wParam
) == BN_DOUBLECLICKED
)
495 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
498 if (HIWORD(wParam
) == EN_CHANGE
)
499 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
503 if (HIWORD(wParam
) == BN_CLICKED
||
504 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
509 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
511 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
517 strcpy (str
, sessions
[n
]);
519 save_settings (str
, !!strcmp(str
, "Default Settings"));
520 get_sesslist (FALSE
);
522 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
524 for (i
= 0; i
< nsessions
; i
++)
525 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
526 0, (LPARAM
) (sessions
[i
]));
527 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
533 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
534 HIWORD(wParam
) != BN_CLICKED
&&
535 HIWORD(wParam
) != BN_DOUBLECLICKED
)
537 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
538 HIWORD(wParam
) != LBN_DBLCLK
)
541 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
547 load_settings (sessions
[n
],
548 !!strcmp(sessions
[n
], "Default Settings"));
549 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
550 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
551 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
552 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
554 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
555 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
558 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
560 * A double-click on a saved session should
561 * actually start the session, not just load it.
562 * Unless it's Default Settings or some other
563 * host-less set of saved settings.
572 if (HIWORD(wParam
) == BN_CLICKED
||
573 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
574 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
576 if (n
== LB_ERR
|| n
== 0) {
580 del_session(sessions
[n
]);
581 get_sesslist (FALSE
);
583 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
585 for (i
= 0; i
< nsessions
; i
++)
586 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
587 0, (LPARAM
) (sessions
[i
]));
588 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
593 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
596 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
597 WPARAM wParam
, LPARAM lParam
) {
600 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
601 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
602 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
603 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
604 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
605 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
606 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
607 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
608 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPAPPLIC
,
609 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
612 if (HIWORD(wParam
) == BN_CLICKED
||
613 HIWORD(wParam
) == BN_DOUBLECLICKED
)
614 switch (LOWORD(wParam
)) {
617 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
621 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
625 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
629 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
633 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
637 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
640 static void fmtfont (char *buf
) {
641 sprintf (buf
, "Font: %s, ", cfg
.font
);
643 strcat(buf
, "bold, ");
644 if (cfg
.fontheight
== 0)
645 strcat (buf
, "default height");
647 sprintf (buf
+strlen(buf
), "%d-%s",
648 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
649 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
652 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
653 WPARAM wParam
, LPARAM lParam
) {
656 char fontstatic
[256];
660 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
661 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
662 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
663 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
664 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
665 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
666 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
667 fmtfont (fontstatic
);
668 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
669 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
670 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
671 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
672 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
676 switch (LOWORD(wParam
)) {
678 if (HIWORD(wParam
) == BN_CLICKED
||
679 HIWORD(wParam
) == BN_DOUBLECLICKED
)
680 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
683 if (HIWORD(wParam
) == BN_CLICKED
||
684 HIWORD(wParam
) == BN_DOUBLECLICKED
)
685 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
688 if (HIWORD(wParam
) == BN_CLICKED
||
689 HIWORD(wParam
) == BN_DOUBLECLICKED
)
690 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
693 if (HIWORD(wParam
) == BN_CLICKED
||
694 HIWORD(wParam
) == BN_DOUBLECLICKED
)
695 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
698 if (HIWORD(wParam
) == EN_CHANGE
)
699 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
702 if (HIWORD(wParam
) == EN_CHANGE
)
703 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
706 if (HIWORD(wParam
) == EN_CHANGE
)
707 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
709 case IDC2_CHOOSEFONT
:
710 lf
.lfHeight
= cfg
.fontheight
;
711 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
712 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
713 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
714 lf
.lfCharSet
= ANSI_CHARSET
;
715 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
716 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
717 lf
.lfQuality
= DEFAULT_QUALITY
;
718 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
719 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
720 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
722 cf
.lStructSize
= sizeof(cf
);
725 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
726 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
728 if (ChooseFont (&cf
)) {
729 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
730 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
731 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
732 cfg
.fontheight
= lf
.lfHeight
;
733 fmtfont (fontstatic
);
734 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
737 case IDC2_VTXWINDOWS
:
742 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
743 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
744 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
750 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
753 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
754 WPARAM wParam
, LPARAM lParam
) {
759 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
760 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
761 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
763 char *p
= cfg
.environmt
;
765 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
770 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
771 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
774 switch (LOWORD(wParam
)) {
776 if (HIWORD(wParam
) == EN_CHANGE
)
777 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
778 sizeof(cfg
.termtype
)-1);
781 if (HIWORD(wParam
) == EN_CHANGE
)
782 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
783 sizeof(cfg
.termspeed
)-1);
786 if (HIWORD(wParam
) == EN_CHANGE
)
787 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
788 sizeof(cfg
.username
)-1);
792 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
795 if (HIWORD(wParam
) == BN_CLICKED
||
796 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
797 char str
[sizeof(cfg
.environmt
)];
799 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
804 p
= str
+ strlen(str
);
806 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
816 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
818 p
[strlen(str
)+1] = '\0';
819 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
821 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
822 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
824 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
825 MB_OK
| MB_ICONERROR
);
830 if (HIWORD(wParam
) != BN_CLICKED
&&
831 HIWORD(wParam
) != BN_DOUBLECLICKED
)
833 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
839 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
866 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
869 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
870 WPARAM wParam
, LPARAM lParam
) {
873 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
874 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
875 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
876 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERBLOWF
,
877 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
881 switch (LOWORD(wParam
)) {
883 if (HIWORD(wParam
) == EN_CHANGE
)
884 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
885 sizeof(cfg
.termtype
)-1);
888 if (HIWORD(wParam
) == EN_CHANGE
)
889 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
890 sizeof(cfg
.username
)-1);
893 if (HIWORD(wParam
) == BN_CLICKED
||
894 HIWORD(wParam
) == BN_DOUBLECLICKED
)
895 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
897 case IDC3_CIPHER3DES
:
898 case IDC3_CIPHERBLOWF
:
899 if (HIWORD(wParam
) == BN_CLICKED
||
900 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
901 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
902 cfg
.cipher
= CIPHER_3DES
;
903 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
904 cfg
.cipher
= CIPHER_BLOWFISH
;
910 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
913 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
914 WPARAM wParam
, LPARAM lParam
) {
919 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
920 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
922 static int tabs
[4] = {25, 61, 96, 128};
923 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
926 for (i
=0; i
<256; i
++) {
928 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
929 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
931 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
936 switch (LOWORD(wParam
)) {
939 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
945 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
950 for (i
=0; i
<256; i
++)
951 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
955 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
956 LB_DELETESTRING
, i
, 0);
957 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
958 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
960 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
970 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
973 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
974 WPARAM wParam
, LPARAM lParam
) {
975 static const char *const colours
[] = {
976 "Default Foreground", "Default Bold Foreground",
977 "Default Background", "Default Bold Background",
978 "Cursor Text", "Cursor Colour",
979 "ANSI Black", "ANSI Black Bold",
980 "ANSI Red", "ANSI Red Bold",
981 "ANSI Green", "ANSI Green Bold",
982 "ANSI Yellow", "ANSI Yellow Bold",
983 "ANSI Blue", "ANSI Blue Bold",
984 "ANSI Magenta", "ANSI Magenta Bold",
985 "ANSI Cyan", "ANSI Cyan Bold",
986 "ANSI White", "ANSI White Bold"
988 static const int permanent
[] = {
989 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
990 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
991 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
995 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
996 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1000 if (cfg
.bold_colour
|| permanent
[i
])
1001 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1002 (LPARAM
) colours
[i
]);
1004 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1005 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1006 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1007 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1010 switch (LOWORD(wParam
)) {
1011 case IDC5_BOLDCOLOUR
:
1012 if (HIWORD(wParam
) == BN_CLICKED
||
1013 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1015 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1016 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1017 if (cfg
.bold_colour
&& n
!=22) {
1018 for (i
=0; i
<22; i
++)
1020 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1022 (LPARAM
) colours
[i
]);
1023 } else if (!cfg
.bold_colour
&& n
!=12) {
1026 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1027 LB_DELETESTRING
, i
, 0);
1032 if (HIWORD(wParam
) == BN_CLICKED
||
1033 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1034 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1037 if (HIWORD(wParam
) == LBN_DBLCLK
||
1038 HIWORD(wParam
) == LBN_SELCHANGE
) {
1039 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1041 if (!cfg
.bold_colour
)
1042 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1043 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1044 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1045 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1049 if (HIWORD(wParam
) == BN_CLICKED
||
1050 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1051 static CHOOSECOLOR cc
;
1052 static DWORD custom
[16] = {0}; /* zero initialisers */
1053 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1055 if (!cfg
.bold_colour
)
1056 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1057 cc
.lStructSize
= sizeof(cc
);
1058 cc
.hwndOwner
= hwnd
;
1059 cc
.hInstance
= hinst
;
1060 cc
.lpCustColors
= custom
;
1061 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1063 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1064 if (ChooseColor(&cc
)) {
1066 (unsigned char) (cc
.rgbResult
& 0xFF);
1068 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1070 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1071 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1073 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1075 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1083 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1086 static DLGPROC panelproc
[NPANELS
] = {
1087 ConnectionProc
, KeyboardProc
, TerminalProc
,
1088 TelnetProc
, SshProc
, SelectionProc
, ColourProc
1090 static char *panelids
[NPANELS
] = {
1091 MAKEINTRESOURCE(IDD_PANEL0
),
1092 MAKEINTRESOURCE(IDD_PANEL1
),
1093 MAKEINTRESOURCE(IDD_PANEL2
),
1094 MAKEINTRESOURCE(IDD_PANEL3
),
1095 MAKEINTRESOURCE(IDD_PANEL35
),
1096 MAKEINTRESOURCE(IDD_PANEL4
),
1097 MAKEINTRESOURCE(IDD_PANEL5
)
1099 static char *names
[NPANELS
] = {
1100 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1103 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6 };
1104 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6 };
1106 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1107 WPARAM wParam
, LPARAM lParam
,
1108 int npanels
, int *panelnums
, HWND
*page
) {
1113 { /* centre the window */
1116 hw
= GetDesktopWindow();
1117 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1118 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1119 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1120 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1123 { /* initialise the tab control */
1127 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1128 for (i
=0; i
<npanels
; i
++) {
1129 tab
.mask
= TCIF_TEXT
;
1130 tab
.pszText
= names
[panelnums
[i
]];
1131 TabCtrl_InsertItem (hw
, i
, &tab
);
1133 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1134 hwnd, panelproc[panelnums[0]]);*/
1135 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1136 hwnd
, panelproc
[panelnums
[0]]);
1137 SetWindowLong (*page
, GWL_EXSTYLE
,
1138 GetWindowLong (*page
, GWL_EXSTYLE
) |
1139 WS_EX_CONTROLPARENT
);
1144 if (LOWORD(wParam
) == IDC_TAB
&&
1145 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1146 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1148 DestroyWindow (*page
);
1149 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1150 hwnd, panelproc[panelnums[i]]);*/
1151 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1152 hwnd
, panelproc
[panelnums
[i
]]);
1153 SetWindowLong (*page
, GWL_EXSTYLE
,
1154 GetWindowLong (*page
, GWL_EXSTYLE
) |
1155 WS_EX_CONTROLPARENT
);
1156 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1160 /* case WM_CTLCOLORDLG: */
1161 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1163 switch (LOWORD(wParam
)) {
1166 EndDialog (hwnd
, 1);
1171 EndDialog (hwnd
, 0);
1176 EndDialog (hwnd
, 0);
1182 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1183 WPARAM wParam
, LPARAM lParam
) {
1188 static HWND page
= NULL
;
1190 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1193 * If the Connection panel is active and the Session List
1194 * box is selected, we treat a press of Open to have an
1195 * implicit press of Load preceding it.
1197 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1198 i
= TabCtrl_GetCurSel(hw
);
1199 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1200 page
&& implicit_load_ok
) {
1201 SendMessage (page
, WM_COMMAND
,
1202 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1206 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1207 EnableWindow(hwnd
, 0);
1208 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1209 GetParent(hwnd
), AboutProc
);
1210 EnableWindow(hwnd
, 1);
1212 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1213 MAIN_NPANELS
, mainp
, &page
);
1216 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1217 WPARAM wParam
, LPARAM lParam
) {
1219 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1220 RECONF_NPANELS
, reconfp
, &page
);
1223 static void get_sesslist(int allocate
) {
1224 static char *buffer
;
1225 int buflen
, bufsize
, i
, ret
;
1226 char otherbuf
[2048];
1231 if (RegCreateKey(HKEY_CURRENT_USER
,
1232 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1235 buflen
= bufsize
= 0;
1239 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1240 if (ret
== ERROR_SUCCESS
) {
1241 bufsize
= buflen
+ 2048;
1242 buffer
= srealloc(buffer
, bufsize
);
1243 unmungestr(otherbuf
, buffer
+buflen
);
1244 buflen
+= strlen(buffer
+buflen
)+1;
1246 } while (ret
== ERROR_SUCCESS
);
1247 buffer
= srealloc(buffer
, buflen
+1);
1248 buffer
[buflen
] = '\0';
1251 nsessions
= 1; /* "Default Settings" counts as one */
1253 if (strcmp(p
, "Default Settings"))
1259 sessions
= smalloc(nsessions
* sizeof(char *));
1260 sessions
[0] = "Default Settings";
1264 if (strcmp(p
, "Default Settings"))
1275 int do_config (void) {
1279 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1280 get_sesslist(FALSE
);
1285 int do_reconfig (HWND hwnd
) {
1289 backup_cfg
= cfg
; /* structure copy */
1290 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1292 cfg
= backup_cfg
; /* structure copy */
1296 void do_defaults (char *session
) {
1298 load_settings (session
, TRUE
);
1300 load_settings ("Default Settings", FALSE
);
1303 void lognegot (char *string
) {
1304 if (nnegots
>= negsize
) {
1306 negots
= srealloc (negots
, negsize
* sizeof(*negots
));
1308 negots
[nnegots
] = smalloc(1+strlen(string
));
1309 strcpy (negots
[nnegots
], string
);
1312 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1316 void shownegot (HWND hwnd
) {
1318 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1320 ShowWindow (logbox
, SW_SHOWNORMAL
);
1324 void showabout (HWND hwnd
) {
1326 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1328 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1332 void verify_ssh_host_key(char *host
, struct RSAKey
*key
) {
1333 char *keystr
, *otherstr
, *mungedhost
;
1338 * Format the key into a string.
1340 len
= rsastr_len(key
);
1341 keystr
= malloc(len
);
1343 fatalbox("Out of memory");
1344 rsastr_fmt(keystr
, key
);
1347 * Now read a saved key in from the registry and see what it
1350 otherstr
= malloc(len
);
1351 mungedhost
= malloc(3*strlen(host
)+1);
1352 if (!otherstr
|| !mungedhost
)
1353 fatalbox("Out of memory");
1355 mungestr(host
, mungedhost
);
1357 if (RegCreateKey(HKEY_CURRENT_USER
, PUTTY_REG_POS
"\\SshHostKeys",
1358 &rkey
) != ERROR_SUCCESS
) {
1359 if (MessageBox(NULL
, "PuTTY was unable to open the host key cache\n"
1360 "in the registry. There is thus no way to tell\n"
1361 "if the remote host is what you think it is.\n"
1362 "Connect anyway?", "PuTTY Problem",
1363 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1366 DWORD readlen
= len
;
1370 ret
= RegQueryValueEx(rkey
, mungedhost
, NULL
,
1371 &type
, otherstr
, &readlen
);
1373 if (ret
== ERROR_MORE_DATA
||
1374 (ret
== ERROR_SUCCESS
&& type
== REG_SZ
&&
1375 strcmp(otherstr
, keystr
))) {
1376 if (MessageBox(NULL
,
1377 "This host's host key is different from the\n"
1378 "one cached in the registry! Someone may be\n"
1379 "impersonating this host for malicious reasons;\n"
1380 "alternatively, the host key may have changed\n"
1381 "due to sloppy system administration.\n"
1382 "Replace key in registry and connect?",
1383 "PuTTY: Security Warning",
1384 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1386 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,
1388 } else if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) {
1389 if (MessageBox(NULL
,
1390 "This host's host key is not cached in the\n"
1391 "registry. Do you want to add it to the cache\n"
1392 "and carry on connecting?",
1394 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1396 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,