13 #define MAIN_NPANELS 7
14 #define RECONF_NPANELS 4
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" : "telnet");
121 wppi (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
122 wpps (sesskey
, "TerminalType", cfg
.termtype
);
123 wpps (sesskey
, "TerminalSpeed", cfg
.termspeed
);
125 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
131 if (c
== '=' || c
== ',' || c
== '\\')
141 wpps (sesskey
, "Environment", buf
);
143 wpps (sesskey
, "UserName", cfg
.username
);
144 wppi (sesskey
, "NoPTY", cfg
.nopty
);
145 wpps (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
146 cfg
.cipher
== CIPHER_DES ?
"des" : "3des");
147 wppi (sesskey
, "RFCEnviron", cfg
.rfc_environ
);
148 wppi (sesskey
, "BackspaceIsDelete", cfg
.bksp_is_delete
);
149 wppi (sesskey
, "RXVTHomeEnd", cfg
.rxvt_homeend
);
150 wppi (sesskey
, "LinuxFunctionKeys", cfg
.linux_funkeys
);
151 wppi (sesskey
, "ApplicationCursorKeys", cfg
.app_cursor
);
152 wppi (sesskey
, "ApplicationKeypad", cfg
.app_keypad
);
153 wppi (sesskey
, "ScrollbackLines", cfg
.savelines
);
154 wppi (sesskey
, "DECOriginMode", cfg
.dec_om
);
155 wppi (sesskey
, "AutoWrapMode", cfg
.wrap_mode
);
156 wppi (sesskey
, "LFImpliesCR", cfg
.lfhascr
);
157 wppi (sesskey
, "WinNameAlways", cfg
.win_name_always
);
158 wppi (sesskey
, "TermWidth", cfg
.width
);
159 wppi (sesskey
, "TermHeight", cfg
.height
);
160 wpps (sesskey
, "Font", cfg
.font
);
161 wppi (sesskey
, "FontIsBold", cfg
.fontisbold
);
162 wppi (sesskey
, "FontHeight", cfg
.fontheight
);
163 wppi (sesskey
, "FontVTMode", cfg
.vtmode
);
164 wppi (sesskey
, "TryPalette", cfg
.try_palette
);
165 wppi (sesskey
, "BoldAsColour", cfg
.bold_colour
);
166 for (i
=0; i
<22; i
++) {
167 char buf
[20], buf2
[30];
168 sprintf(buf
, "Colour%d", i
);
169 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
170 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
171 wpps (sesskey
, buf
, buf2
);
173 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
174 for (i
=0; i
<256; i
+=32) {
175 char buf
[20], buf2
[256];
177 sprintf(buf
, "Wordness%d", i
);
179 for (j
=i
; j
<i
+32; j
++) {
180 sprintf(buf2
+strlen(buf2
), "%s%d",
181 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
183 wpps (sesskey
, buf
, buf2
);
186 RegCloseKey(sesskey
);
189 static void del_session (char *section
) {
193 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
)
196 p
= malloc(3*strlen(section
)+1);
197 mungestr(section
, p
);
198 RegDeleteKey(subkey1
, p
);
201 RegCloseKey(subkey1
);
204 static void load_settings (char *section
, int do_host
) {
206 HKEY subkey1
, sesskey
;
210 p
= malloc(3*strlen(section
)+1);
211 mungestr(section
, p
);
213 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
216 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
219 RegCloseKey(subkey1
);
224 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
225 gppi (sesskey
, "PortNumber", default_port
, &cfg
.port
);
226 gpps (sesskey
, "Protocol", "default", prot
, 10);
227 if (!strcmp(prot
, "ssh"))
228 cfg
.protocol
= PROT_SSH
;
229 else if (!strcmp(prot
, "telnet"))
230 cfg
.protocol
= PROT_TELNET
;
232 cfg
.protocol
= default_protocol
;
234 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
235 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
236 sizeof(cfg
.termtype
));
237 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
238 sizeof(cfg
.termspeed
));
240 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
241 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
245 while (*p
&& *p
!= ',') {
258 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
259 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
262 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
263 if (!strcmp(cipher
, "blowfish"))
264 cfg
.cipher
= CIPHER_BLOWFISH
;
265 else if (!strcmp(cipher
, "des"))
266 cfg
.cipher
= CIPHER_DES
;
268 cfg
.cipher
= CIPHER_3DES
;
270 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
271 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
272 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
273 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.linux_funkeys
);
274 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
275 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
276 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
277 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
278 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
279 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
280 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
281 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
282 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
283 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
284 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
285 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
286 gppi (sesskey
, "FontVTMode", VT_POORMAN
, &cfg
.vtmode
);
287 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
288 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
289 for (i
=0; i
<22; i
++) {
290 static char *defaults
[] = {
291 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
292 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
293 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
294 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
295 "85,255,255", "187,187,187", "255,255,255"
297 char buf
[20], buf2
[30];
298 sprintf(buf
, "Colour%d", i
);
299 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
300 sscanf(buf2
, "%d,%d,%d", &cfg
.colours
[i
][0],
301 &cfg
.colours
[i
][1], &cfg
.colours
[i
][2]);
303 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
304 for (i
=0; i
<256; i
+=32) {
305 static char *defaults
[] = {
306 "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",
307 "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",
308 "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",
309 "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",
310 "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",
311 "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",
312 "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",
313 "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"
315 char buf
[20], buf2
[256], *p
;
317 sprintf(buf
, "Wordness%d", i
);
318 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
320 for (j
=i
; j
<i
+32; j
++) {
322 while (*p
&& *p
!= ',') p
++;
323 if (*p
== ',') *p
++ = '\0';
324 cfg
.wordness
[j
] = atoi(q
);
327 RegCloseKey(sesskey
);
330 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
333 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
338 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
339 WPARAM wParam
, LPARAM lParam
) {
344 for (i
=0; i
<nnegots
; i
++)
345 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
346 0, (LPARAM
)negots
[i
]);
348 /* case WM_CTLCOLORDLG: */
349 /* return (int) GetStockObject (LTGRAY_BRUSH); */
351 switch (LOWORD(wParam
)) {
354 DestroyWindow (hwnd
);
360 DestroyWindow (hwnd
);
366 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
367 WPARAM wParam
, LPARAM lParam
) {
372 switch (LOWORD(wParam
)) {
375 DestroyWindow (hwnd
);
381 DestroyWindow (hwnd
);
387 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
388 WPARAM wParam
, LPARAM lParam
) {
391 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
393 /* case WM_CTLCOLORDLG: */
394 /* return (int) GetStockObject (LTGRAY_BRUSH); */
395 /* case WM_CTLCOLORSTATIC: */
396 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
397 /* return (int) GetStockObject (LTGRAY_BRUSH); */
399 switch (LOWORD(wParam
)) {
402 DestroyWindow (hwnd
);
405 EnableWindow(hwnd
, 0);
406 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
408 EnableWindow(hwnd
, 1);
414 DestroyWindow (hwnd
);
420 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
421 WPARAM wParam
, LPARAM lParam
) {
424 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
426 /* case WM_CTLCOLORDLG: */
427 /* return (int) GetStockObject (LTGRAY_BRUSH); */
428 /* case WM_CTLCOLORSTATIC: */
429 /* case WM_CTLCOLORBTN: */
430 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
431 /* return (int) GetStockObject (LTGRAY_BRUSH); */
433 DestroyWindow (hwnd
);
439 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
440 WPARAM wParam
, LPARAM lParam
) {
445 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
446 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
447 for (i
= 0; i
< nsessions
; i
++)
448 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
449 0, (LPARAM
) (sessions
[i
]));
450 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
451 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
: IDC0_PROTTELNET
);
452 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
456 * Button release should trigger WM_OK if there was a
457 * previous double click on the session list.
461 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
464 switch (LOWORD(wParam
)) {
465 case IDC0_PROTTELNET
:
467 if (HIWORD(wParam
) == BN_CLICKED
||
468 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
469 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
470 cfg
.protocol
= i ? PROT_SSH
: PROT_TELNET
;
471 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
472 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
473 cfg
.port
= i ?
22 : 23;
474 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
479 if (HIWORD(wParam
) == EN_CHANGE
)
480 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
484 if (HIWORD(wParam
) == EN_CHANGE
)
485 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
488 if (HIWORD(wParam
) == BN_CLICKED
||
489 HIWORD(wParam
) == BN_DOUBLECLICKED
)
490 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
493 if (HIWORD(wParam
) == EN_CHANGE
)
494 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
498 if (HIWORD(wParam
) == BN_CLICKED
||
499 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
504 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
506 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
512 strcpy (str
, sessions
[n
]);
514 save_settings (str
, !!strcmp(str
, "Default Settings"));
515 get_sesslist (FALSE
);
517 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
519 for (i
= 0; i
< nsessions
; i
++)
520 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
521 0, (LPARAM
) (sessions
[i
]));
522 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
528 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
529 HIWORD(wParam
) != BN_CLICKED
&&
530 HIWORD(wParam
) != BN_DOUBLECLICKED
)
532 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
533 HIWORD(wParam
) != LBN_DBLCLK
)
536 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
542 load_settings (sessions
[n
],
543 !!strcmp(sessions
[n
], "Default Settings"));
544 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
545 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
546 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
547 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
549 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
550 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
553 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
555 * A double-click on a saved session should
556 * actually start the session, not just load it.
557 * Unless it's Default Settings or some other
558 * host-less set of saved settings.
567 if (HIWORD(wParam
) == BN_CLICKED
||
568 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
569 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
571 if (n
== LB_ERR
|| n
== 0) {
575 del_session(sessions
[n
]);
576 get_sesslist (FALSE
);
578 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
580 for (i
= 0; i
< nsessions
; i
++)
581 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
582 0, (LPARAM
) (sessions
[i
]));
583 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
588 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
591 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
592 WPARAM wParam
, LPARAM lParam
) {
595 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
596 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
597 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
598 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
599 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
600 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
601 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
602 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
603 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPAPPLIC
,
604 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
607 if (HIWORD(wParam
) == BN_CLICKED
||
608 HIWORD(wParam
) == BN_DOUBLECLICKED
)
609 switch (LOWORD(wParam
)) {
612 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
616 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
620 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
624 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
628 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
632 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
635 static void fmtfont (char *buf
) {
636 sprintf (buf
, "Font: %s, ", cfg
.font
);
638 strcat(buf
, "bold, ");
639 if (cfg
.fontheight
== 0)
640 strcat (buf
, "default height");
642 sprintf (buf
+strlen(buf
), "%d-%s",
643 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
644 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
647 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
648 WPARAM wParam
, LPARAM lParam
) {
651 char fontstatic
[256];
655 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
656 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
657 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
658 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
659 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
660 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
661 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
662 fmtfont (fontstatic
);
663 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
664 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
665 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
666 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
667 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
671 switch (LOWORD(wParam
)) {
673 if (HIWORD(wParam
) == BN_CLICKED
||
674 HIWORD(wParam
) == BN_DOUBLECLICKED
)
675 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
678 if (HIWORD(wParam
) == BN_CLICKED
||
679 HIWORD(wParam
) == BN_DOUBLECLICKED
)
680 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
683 if (HIWORD(wParam
) == BN_CLICKED
||
684 HIWORD(wParam
) == BN_DOUBLECLICKED
)
685 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
688 if (HIWORD(wParam
) == BN_CLICKED
||
689 HIWORD(wParam
) == BN_DOUBLECLICKED
)
690 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
693 if (HIWORD(wParam
) == EN_CHANGE
)
694 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
697 if (HIWORD(wParam
) == EN_CHANGE
)
698 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
701 if (HIWORD(wParam
) == EN_CHANGE
)
702 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
704 case IDC2_CHOOSEFONT
:
705 lf
.lfHeight
= cfg
.fontheight
;
706 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
707 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
708 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
709 lf
.lfCharSet
= ANSI_CHARSET
;
710 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
711 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
712 lf
.lfQuality
= DEFAULT_QUALITY
;
713 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
714 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
715 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
717 cf
.lStructSize
= sizeof(cf
);
720 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
721 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
723 if (ChooseFont (&cf
)) {
724 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
725 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
726 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
727 cfg
.fontheight
= lf
.lfHeight
;
728 fmtfont (fontstatic
);
729 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
732 case IDC2_VTXWINDOWS
:
737 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
738 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
739 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
745 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
748 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
749 WPARAM wParam
, LPARAM lParam
) {
754 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
755 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
756 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
758 char *p
= cfg
.environmt
;
760 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
765 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
766 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
769 switch (LOWORD(wParam
)) {
771 if (HIWORD(wParam
) == EN_CHANGE
)
772 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
773 sizeof(cfg
.termtype
)-1);
776 if (HIWORD(wParam
) == EN_CHANGE
)
777 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
778 sizeof(cfg
.termspeed
)-1);
781 if (HIWORD(wParam
) == EN_CHANGE
)
782 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
783 sizeof(cfg
.username
)-1);
787 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
790 if (HIWORD(wParam
) == BN_CLICKED
||
791 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
792 char str
[sizeof(cfg
.environmt
)];
794 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
799 p
= str
+ strlen(str
);
801 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
811 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
813 p
[strlen(str
)+1] = '\0';
814 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
816 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
817 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
819 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
820 MB_OK
| MB_ICONERROR
);
825 if (HIWORD(wParam
) != BN_CLICKED
&&
826 HIWORD(wParam
) != BN_DOUBLECLICKED
)
828 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
834 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
861 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
864 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
865 WPARAM wParam
, LPARAM lParam
) {
868 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
869 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
870 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
871 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERDES
,
872 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
873 cfg
.cipher
== CIPHER_DES ? IDC3_CIPHERDES
:
878 switch (LOWORD(wParam
)) {
880 if (HIWORD(wParam
) == EN_CHANGE
)
881 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
882 sizeof(cfg
.termtype
)-1);
885 if (HIWORD(wParam
) == EN_CHANGE
)
886 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
887 sizeof(cfg
.username
)-1);
890 if (HIWORD(wParam
) == BN_CLICKED
||
891 HIWORD(wParam
) == BN_DOUBLECLICKED
)
892 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
894 case IDC3_CIPHER3DES
:
895 case IDC3_CIPHERBLOWF
:
897 if (HIWORD(wParam
) == BN_CLICKED
||
898 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
899 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
900 cfg
.cipher
= CIPHER_3DES
;
901 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
902 cfg
.cipher
= CIPHER_BLOWFISH
;
903 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERDES
))
904 cfg
.cipher
= CIPHER_DES
;
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 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
,