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" :
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
, "FontHeight", cfg
.fontheight
);
165 wppi (sesskey
, "FontVTMode", cfg
.vtmode
);
166 wppi (sesskey
, "TryPalette", cfg
.try_palette
);
167 wppi (sesskey
, "BoldAsColour", cfg
.bold_colour
);
168 for (i
=0; i
<22; i
++) {
169 char buf
[20], buf2
[30];
170 sprintf(buf
, "Colour%d", i
);
171 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
172 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
173 wpps (sesskey
, buf
, buf2
);
175 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
176 for (i
=0; i
<256; i
+=32) {
177 char buf
[20], buf2
[256];
179 sprintf(buf
, "Wordness%d", i
);
181 for (j
=i
; j
<i
+32; j
++) {
182 sprintf(buf2
+strlen(buf2
), "%s%d",
183 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
185 wpps (sesskey
, buf
, buf2
);
188 RegCloseKey(sesskey
);
191 static void del_session (char *section
) {
195 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
)
198 p
= malloc(3*strlen(section
)+1);
199 mungestr(section
, p
);
200 RegDeleteKey(subkey1
, p
);
203 RegCloseKey(subkey1
);
206 static void load_settings (char *section
, int do_host
) {
208 HKEY subkey1
, sesskey
;
212 p
= malloc(3*strlen(section
)+1);
213 mungestr(section
, p
);
215 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
218 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
221 RegCloseKey(subkey1
);
226 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
227 gppi (sesskey
, "PortNumber", default_port
, &cfg
.port
);
228 gpps (sesskey
, "Protocol", "default", prot
, 10);
229 if (!strcmp(prot
, "ssh"))
230 cfg
.protocol
= PROT_SSH
;
231 else if (!strcmp(prot
, "telnet"))
232 cfg
.protocol
= PROT_TELNET
;
233 else if (!strcmp(prot
, "raw"))
234 cfg
.protocol
= PROT_RAW
;
236 cfg
.protocol
= default_protocol
;
238 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
239 gppi (sesskey
, "WarnOnClose", 1, &cfg
.warn_on_close
);
240 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
241 sizeof(cfg
.termtype
));
242 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
243 sizeof(cfg
.termspeed
));
245 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
246 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
250 while (*p
&& *p
!= ',') {
263 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
264 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
267 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
268 if (!strcmp(cipher
, "blowfish"))
269 cfg
.cipher
= CIPHER_BLOWFISH
;
270 else if (!strcmp(cipher
, "des"))
271 cfg
.cipher
= CIPHER_DES
;
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_PROTRAW
, IDC0_PROTSSH
,
456 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
457 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
);
458 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
459 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
463 * Button release should trigger WM_OK if there was a
464 * previous double click on the session list.
468 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
471 switch (LOWORD(wParam
)) {
472 case IDC0_PROTTELNET
:
475 if (HIWORD(wParam
) == BN_CLICKED
||
476 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
477 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
478 int j
= IsDlgButtonChecked (hwnd
, IDC0_PROTTELNET
);
479 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
480 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
481 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
482 cfg
.port
= i ?
22 : 23;
483 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
488 if (HIWORD(wParam
) == EN_CHANGE
)
489 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
493 if (HIWORD(wParam
) == EN_CHANGE
)
494 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
497 if (HIWORD(wParam
) == BN_CLICKED
||
498 HIWORD(wParam
) == BN_DOUBLECLICKED
)
499 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
502 if (HIWORD(wParam
) == BN_CLICKED
||
503 HIWORD(wParam
) == BN_DOUBLECLICKED
)
504 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEWARN
);
507 if (HIWORD(wParam
) == EN_CHANGE
)
508 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
512 if (HIWORD(wParam
) == BN_CLICKED
||
513 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
518 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
520 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
526 strcpy (str
, sessions
[n
]);
528 save_settings (str
, !!strcmp(str
, "Default Settings"));
529 get_sesslist (FALSE
);
531 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
533 for (i
= 0; i
< nsessions
; i
++)
534 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
535 0, (LPARAM
) (sessions
[i
]));
536 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
542 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
543 HIWORD(wParam
) != BN_CLICKED
&&
544 HIWORD(wParam
) != BN_DOUBLECLICKED
)
546 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
547 HIWORD(wParam
) != LBN_DBLCLK
)
550 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
556 load_settings (sessions
[n
],
557 !!strcmp(sessions
[n
], "Default Settings"));
558 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
559 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
560 CheckRadioButton (hwnd
, IDC0_PROTRAW
, IDC0_PROTSSH
,
561 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
562 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
));
563 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
564 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
565 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
568 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
570 * A double-click on a saved session should
571 * actually start the session, not just load it.
572 * Unless it's Default Settings or some other
573 * host-less set of saved settings.
582 if (HIWORD(wParam
) == BN_CLICKED
||
583 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
584 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
586 if (n
== LB_ERR
|| n
== 0) {
590 del_session(sessions
[n
]);
591 get_sesslist (FALSE
);
593 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
595 for (i
= 0; i
< nsessions
; i
++)
596 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
597 0, (LPARAM
) (sessions
[i
]));
598 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
603 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
606 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
607 WPARAM wParam
, LPARAM lParam
) {
610 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
611 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
612 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
613 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
614 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
615 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
616 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
617 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
618 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPAPPLIC
,
619 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
622 if (HIWORD(wParam
) == BN_CLICKED
||
623 HIWORD(wParam
) == BN_DOUBLECLICKED
)
624 switch (LOWORD(wParam
)) {
627 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
631 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
635 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
639 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
643 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
647 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
650 static void fmtfont (char *buf
) {
651 sprintf (buf
, "Font: %s, ", cfg
.font
);
653 strcat(buf
, "bold, ");
654 if (cfg
.fontheight
== 0)
655 strcat (buf
, "default height");
657 sprintf (buf
+strlen(buf
), "%d-%s",
658 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
659 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
662 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
663 WPARAM wParam
, LPARAM lParam
) {
666 char fontstatic
[256];
670 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
671 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
672 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
673 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
674 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
675 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
676 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
677 fmtfont (fontstatic
);
678 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
679 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
680 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
681 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
682 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
686 switch (LOWORD(wParam
)) {
688 if (HIWORD(wParam
) == BN_CLICKED
||
689 HIWORD(wParam
) == BN_DOUBLECLICKED
)
690 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
693 if (HIWORD(wParam
) == BN_CLICKED
||
694 HIWORD(wParam
) == BN_DOUBLECLICKED
)
695 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
698 if (HIWORD(wParam
) == BN_CLICKED
||
699 HIWORD(wParam
) == BN_DOUBLECLICKED
)
700 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
703 if (HIWORD(wParam
) == BN_CLICKED
||
704 HIWORD(wParam
) == BN_DOUBLECLICKED
)
705 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
708 if (HIWORD(wParam
) == EN_CHANGE
)
709 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
712 if (HIWORD(wParam
) == EN_CHANGE
)
713 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
716 if (HIWORD(wParam
) == EN_CHANGE
)
717 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
719 case IDC2_CHOOSEFONT
:
720 lf
.lfHeight
= cfg
.fontheight
;
721 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
722 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
723 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
724 lf
.lfCharSet
= ANSI_CHARSET
;
725 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
726 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
727 lf
.lfQuality
= DEFAULT_QUALITY
;
728 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
729 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
730 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
732 cf
.lStructSize
= sizeof(cf
);
735 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
736 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
738 if (ChooseFont (&cf
)) {
739 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
740 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
741 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
742 cfg
.fontheight
= lf
.lfHeight
;
743 fmtfont (fontstatic
);
744 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
747 case IDC2_VTXWINDOWS
:
752 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
753 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
754 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
760 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
763 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
764 WPARAM wParam
, LPARAM lParam
) {
769 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
770 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
771 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
773 char *p
= cfg
.environmt
;
775 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
780 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
781 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
784 switch (LOWORD(wParam
)) {
786 if (HIWORD(wParam
) == EN_CHANGE
)
787 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
788 sizeof(cfg
.termtype
)-1);
791 if (HIWORD(wParam
) == EN_CHANGE
)
792 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
793 sizeof(cfg
.termspeed
)-1);
796 if (HIWORD(wParam
) == EN_CHANGE
)
797 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
798 sizeof(cfg
.username
)-1);
802 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
805 if (HIWORD(wParam
) == BN_CLICKED
||
806 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
807 char str
[sizeof(cfg
.environmt
)];
809 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
814 p
= str
+ strlen(str
);
816 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
826 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
828 p
[strlen(str
)+1] = '\0';
829 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
831 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
832 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
834 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
835 MB_OK
| MB_ICONERROR
);
840 if (HIWORD(wParam
) != BN_CLICKED
&&
841 HIWORD(wParam
) != BN_DOUBLECLICKED
)
843 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
849 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
876 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
879 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
880 WPARAM wParam
, LPARAM lParam
) {
883 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
884 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
885 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
886 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERDES
,
887 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
888 cfg
.cipher
== CIPHER_DES ? IDC3_CIPHERDES
:
893 switch (LOWORD(wParam
)) {
895 if (HIWORD(wParam
) == EN_CHANGE
)
896 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
897 sizeof(cfg
.termtype
)-1);
900 if (HIWORD(wParam
) == EN_CHANGE
)
901 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
902 sizeof(cfg
.username
)-1);
905 if (HIWORD(wParam
) == BN_CLICKED
||
906 HIWORD(wParam
) == BN_DOUBLECLICKED
)
907 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
909 case IDC3_CIPHER3DES
:
910 case IDC3_CIPHERBLOWF
:
912 if (HIWORD(wParam
) == BN_CLICKED
||
913 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
914 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
915 cfg
.cipher
= CIPHER_3DES
;
916 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
917 cfg
.cipher
= CIPHER_BLOWFISH
;
918 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERDES
))
919 cfg
.cipher
= CIPHER_DES
;
925 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
928 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
929 WPARAM wParam
, LPARAM lParam
) {
934 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
935 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
937 static int tabs
[4] = {25, 61, 96, 128};
938 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
941 for (i
=0; i
<256; i
++) {
943 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
944 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
946 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
951 switch (LOWORD(wParam
)) {
954 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
960 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
965 for (i
=0; i
<256; i
++)
966 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
970 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
971 LB_DELETESTRING
, i
, 0);
972 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
973 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
975 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
985 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
988 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
989 WPARAM wParam
, LPARAM lParam
) {
990 static const char *const colours
[] = {
991 "Default Foreground", "Default Bold Foreground",
992 "Default Background", "Default Bold Background",
993 "Cursor Text", "Cursor Colour",
994 "ANSI Black", "ANSI Black Bold",
995 "ANSI Red", "ANSI Red Bold",
996 "ANSI Green", "ANSI Green Bold",
997 "ANSI Yellow", "ANSI Yellow Bold",
998 "ANSI Blue", "ANSI Blue Bold",
999 "ANSI Magenta", "ANSI Magenta Bold",
1000 "ANSI Cyan", "ANSI Cyan Bold",
1001 "ANSI White", "ANSI White Bold"
1003 static const int permanent
[] = {
1004 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1005 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1006 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1010 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
1011 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1014 for (i
=0; i
<22; i
++)
1015 if (cfg
.bold_colour
|| permanent
[i
])
1016 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1017 (LPARAM
) colours
[i
]);
1019 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1020 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1021 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1022 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1025 switch (LOWORD(wParam
)) {
1026 case IDC5_BOLDCOLOUR
:
1027 if (HIWORD(wParam
) == BN_CLICKED
||
1028 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1030 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1031 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1032 if (cfg
.bold_colour
&& n
!=22) {
1033 for (i
=0; i
<22; i
++)
1035 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1037 (LPARAM
) colours
[i
]);
1038 } else if (!cfg
.bold_colour
&& n
!=12) {
1041 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1042 LB_DELETESTRING
, i
, 0);
1047 if (HIWORD(wParam
) == BN_CLICKED
||
1048 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1049 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1052 if (HIWORD(wParam
) == LBN_DBLCLK
||
1053 HIWORD(wParam
) == LBN_SELCHANGE
) {
1054 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1056 if (!cfg
.bold_colour
)
1057 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1058 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1059 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1060 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1064 if (HIWORD(wParam
) == BN_CLICKED
||
1065 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1066 static CHOOSECOLOR cc
;
1067 static DWORD custom
[16] = {0}; /* zero initialisers */
1068 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1070 if (!cfg
.bold_colour
)
1071 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1072 cc
.lStructSize
= sizeof(cc
);
1073 cc
.hwndOwner
= hwnd
;
1074 cc
.hInstance
= hinst
;
1075 cc
.lpCustColors
= custom
;
1076 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1078 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1079 if (ChooseColor(&cc
)) {
1081 (unsigned char) (cc
.rgbResult
& 0xFF);
1083 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1085 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1086 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1088 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1090 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1098 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1101 static DLGPROC panelproc
[NPANELS
] = {
1102 ConnectionProc
, KeyboardProc
, TerminalProc
,
1103 TelnetProc
, SshProc
, SelectionProc
, ColourProc
1105 static char *panelids
[NPANELS
] = {
1106 MAKEINTRESOURCE(IDD_PANEL0
),
1107 MAKEINTRESOURCE(IDD_PANEL1
),
1108 MAKEINTRESOURCE(IDD_PANEL2
),
1109 MAKEINTRESOURCE(IDD_PANEL3
),
1110 MAKEINTRESOURCE(IDD_PANEL35
),
1111 MAKEINTRESOURCE(IDD_PANEL4
),
1112 MAKEINTRESOURCE(IDD_PANEL5
)
1114 static char *names
[NPANELS
] = {
1115 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1118 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6 };
1119 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6 };
1121 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1122 WPARAM wParam
, LPARAM lParam
,
1123 int npanels
, int *panelnums
, HWND
*page
) {
1128 { /* centre the window */
1131 hw
= GetDesktopWindow();
1132 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1133 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1134 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1135 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1138 { /* initialise the tab control */
1142 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1143 for (i
=0; i
<npanels
; i
++) {
1144 tab
.mask
= TCIF_TEXT
;
1145 tab
.pszText
= names
[panelnums
[i
]];
1146 TabCtrl_InsertItem (hw
, i
, &tab
);
1148 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1149 hwnd, panelproc[panelnums[0]]);*/
1150 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1151 hwnd
, panelproc
[panelnums
[0]]);
1152 SetWindowLong (*page
, GWL_EXSTYLE
,
1153 GetWindowLong (*page
, GWL_EXSTYLE
) |
1154 WS_EX_CONTROLPARENT
);
1159 if (LOWORD(wParam
) == IDC_TAB
&&
1160 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1161 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1163 DestroyWindow (*page
);
1164 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1165 hwnd, panelproc[panelnums[i]]);*/
1166 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1167 hwnd
, panelproc
[panelnums
[i
]]);
1168 SetWindowLong (*page
, GWL_EXSTYLE
,
1169 GetWindowLong (*page
, GWL_EXSTYLE
) |
1170 WS_EX_CONTROLPARENT
);
1171 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1175 /* case WM_CTLCOLORDLG: */
1176 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1178 switch (LOWORD(wParam
)) {
1181 EndDialog (hwnd
, 1);
1186 EndDialog (hwnd
, 0);
1191 EndDialog (hwnd
, 0);
1197 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1198 WPARAM wParam
, LPARAM lParam
) {
1203 static HWND page
= NULL
;
1205 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1208 * If the Connection panel is active and the Session List
1209 * box is selected, we treat a press of Open to have an
1210 * implicit press of Load preceding it.
1212 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1213 i
= TabCtrl_GetCurSel(hw
);
1214 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1215 page
&& implicit_load_ok
) {
1216 SendMessage (page
, WM_COMMAND
,
1217 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1221 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1222 EnableWindow(hwnd
, 0);
1223 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1224 GetParent(hwnd
), AboutProc
);
1225 EnableWindow(hwnd
, 1);
1227 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1228 MAIN_NPANELS
, mainp
, &page
);
1231 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1232 WPARAM wParam
, LPARAM lParam
) {
1234 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1235 RECONF_NPANELS
, reconfp
, &page
);
1238 void get_sesslist(int allocate
) {
1239 static char *buffer
;
1240 int buflen
, bufsize
, i
, ret
;
1241 char otherbuf
[2048];
1246 if (RegCreateKey(HKEY_CURRENT_USER
,
1247 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1250 buflen
= bufsize
= 0;
1254 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1255 if (ret
== ERROR_SUCCESS
) {
1256 bufsize
= buflen
+ 2048;
1257 buffer
= srealloc(buffer
, bufsize
);
1258 unmungestr(otherbuf
, buffer
+buflen
);
1259 buflen
+= strlen(buffer
+buflen
)+1;
1261 } while (ret
== ERROR_SUCCESS
);
1262 buffer
= srealloc(buffer
, buflen
+1);
1263 buffer
[buflen
] = '\0';
1266 nsessions
= 1; /* "Default Settings" counts as one */
1268 if (strcmp(p
, "Default Settings"))
1274 sessions
= smalloc(nsessions
* sizeof(char *));
1275 sessions
[0] = "Default Settings";
1279 if (strcmp(p
, "Default Settings"))
1290 int do_config (void) {
1294 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1295 get_sesslist(FALSE
);
1300 int do_reconfig (HWND hwnd
) {
1304 backup_cfg
= cfg
; /* structure copy */
1305 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1307 cfg
= backup_cfg
; /* structure copy */
1311 void do_defaults (char *session
) {
1313 load_settings (session
, TRUE
);
1315 load_settings ("Default Settings", FALSE
);
1318 void lognegot (char *string
) {
1319 if (nnegots
>= negsize
) {
1321 negots
= srealloc (negots
, negsize
* sizeof(*negots
));
1323 negots
[nnegots
] = smalloc(1+strlen(string
));
1324 strcpy (negots
[nnegots
], string
);
1327 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1331 void shownegot (HWND hwnd
) {
1333 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1335 ShowWindow (logbox
, SW_SHOWNORMAL
);
1339 void showabout (HWND hwnd
) {
1341 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1343 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1347 void verify_ssh_host_key(char *host
, struct RSAKey
*key
) {
1348 char *keystr
, *otherstr
, *mungedhost
;
1353 * Format the key into a string.
1355 len
= rsastr_len(key
);
1356 keystr
= malloc(len
);
1358 fatalbox("Out of memory");
1359 rsastr_fmt(keystr
, key
);
1362 * Now read a saved key in from the registry and see what it
1365 otherstr
= malloc(len
);
1366 mungedhost
= malloc(3*strlen(host
)+1);
1367 if (!otherstr
|| !mungedhost
)
1368 fatalbox("Out of memory");
1370 mungestr(host
, mungedhost
);
1372 if (RegCreateKey(HKEY_CURRENT_USER
, PUTTY_REG_POS
"\\SshHostKeys",
1373 &rkey
) != ERROR_SUCCESS
) {
1374 if (MessageBox(NULL
, "PuTTY was unable to open the host key cache\n"
1375 "in the registry. There is thus no way to tell\n"
1376 "if the remote host is what you think it is.\n"
1377 "Connect anyway?", "PuTTY Problem",
1378 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1381 DWORD readlen
= len
;
1385 ret
= RegQueryValueEx(rkey
, mungedhost
, NULL
,
1386 &type
, otherstr
, &readlen
);
1388 if (ret
== ERROR_MORE_DATA
||
1389 (ret
== ERROR_SUCCESS
&& type
== REG_SZ
&&
1390 strcmp(otherstr
, keystr
))) {
1391 if (MessageBox(NULL
,
1392 "This host's host key is different from the\n"
1393 "one cached in the registry! Someone may be\n"
1394 "impersonating this host for malicious reasons;\n"
1395 "alternatively, the host key may have changed\n"
1396 "due to sloppy system administration.\n"
1397 "Replace key in registry and connect?",
1398 "PuTTY: Security Warning",
1399 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1401 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,
1403 } else if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) {
1404 if (MessageBox(NULL
,
1405 "This host's host key is not cached in the\n"
1406 "registry. Do you want to add it to the cache\n"
1407 "and carry on connecting?",
1409 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1411 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,