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" :
151 cfg
.cipher
== CIPHER_DES ?
"des" : "3des");
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
;
238 cfg
.protocol
= PROT_TELNET
;
242 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
243 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
244 sizeof(cfg
.termtype
));
245 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
246 sizeof(cfg
.termspeed
));
248 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
249 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
253 while (*p
&& *p
!= ',') {
266 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
267 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
270 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
271 if (!strcmp(cipher
, "blowfish"))
272 cfg
.cipher
= CIPHER_BLOWFISH
;
273 else if (!strcmp(cipher
, "des"))
274 cfg
.cipher
= CIPHER_DES
;
276 cfg
.cipher
= CIPHER_3DES
;
278 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
279 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
280 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
281 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.linux_funkeys
);
282 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
283 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
284 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
285 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
286 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
287 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
288 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
289 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
290 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
291 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
292 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
293 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
294 gppi (sesskey
, "FontVTMode", VT_POORMAN
, &cfg
.vtmode
);
295 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
296 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
297 for (i
=0; i
<22; i
++) {
298 static char *defaults
[] = {
299 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
300 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
301 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
302 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
303 "85,255,255", "187,187,187", "255,255,255"
305 char buf
[20], buf2
[30];
306 sprintf(buf
, "Colour%d", i
);
307 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
308 sscanf(buf2
, "%d,%d,%d", &cfg
.colours
[i
][0],
309 &cfg
.colours
[i
][1], &cfg
.colours
[i
][2]);
311 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
312 for (i
=0; i
<256; i
+=32) {
313 static char *defaults
[] = {
314 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
315 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
316 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
317 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
318 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
319 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
320 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
321 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
323 char buf
[20], buf2
[256], *p
;
325 sprintf(buf
, "Wordness%d", i
);
326 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
328 for (j
=i
; j
<i
+32; j
++) {
330 while (*p
&& *p
!= ',') p
++;
331 if (*p
== ',') *p
++ = '\0';
332 cfg
.wordness
[j
] = atoi(q
);
335 RegCloseKey(sesskey
);
338 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
341 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
346 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
347 WPARAM wParam
, LPARAM lParam
) {
352 for (i
=0; i
<nnegots
; i
++)
353 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
354 0, (LPARAM
)negots
[i
]);
356 /* case WM_CTLCOLORDLG: */
357 /* return (int) GetStockObject (LTGRAY_BRUSH); */
359 switch (LOWORD(wParam
)) {
362 DestroyWindow (hwnd
);
368 DestroyWindow (hwnd
);
374 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
375 WPARAM wParam
, LPARAM lParam
) {
380 switch (LOWORD(wParam
)) {
383 DestroyWindow (hwnd
);
389 DestroyWindow (hwnd
);
395 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
396 WPARAM wParam
, LPARAM lParam
) {
399 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
401 /* case WM_CTLCOLORDLG: */
402 /* return (int) GetStockObject (LTGRAY_BRUSH); */
403 /* case WM_CTLCOLORSTATIC: */
404 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
405 /* return (int) GetStockObject (LTGRAY_BRUSH); */
407 switch (LOWORD(wParam
)) {
410 DestroyWindow (hwnd
);
413 EnableWindow(hwnd
, 0);
414 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
416 EnableWindow(hwnd
, 1);
422 DestroyWindow (hwnd
);
428 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
429 WPARAM wParam
, LPARAM lParam
) {
432 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
434 /* case WM_CTLCOLORDLG: */
435 /* return (int) GetStockObject (LTGRAY_BRUSH); */
436 /* case WM_CTLCOLORSTATIC: */
437 /* case WM_CTLCOLORBTN: */
438 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
439 /* return (int) GetStockObject (LTGRAY_BRUSH); */
441 DestroyWindow (hwnd
);
447 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
448 WPARAM wParam
, LPARAM lParam
) {
453 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
454 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
455 for (i
= 0; i
< nsessions
; i
++)
456 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
457 0, (LPARAM
) (sessions
[i
]));
458 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
459 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
: IDC0_PROTTELNET
);
460 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
464 * Button release should trigger WM_OK if there was a
465 * previous double click on the session list.
469 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
472 switch (LOWORD(wParam
)) {
473 case IDC0_PROTTELNET
:
475 if (HIWORD(wParam
) == BN_CLICKED
||
476 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
477 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
478 cfg
.protocol
= i ? PROT_SSH
: PROT_TELNET
;
479 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
480 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
481 cfg
.port
= i ?
22 : 23;
482 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
487 if (HIWORD(wParam
) == EN_CHANGE
)
488 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
492 if (HIWORD(wParam
) == EN_CHANGE
)
493 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
496 if (HIWORD(wParam
) == BN_CLICKED
||
497 HIWORD(wParam
) == BN_DOUBLECLICKED
)
498 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
501 if (HIWORD(wParam
) == EN_CHANGE
)
502 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
506 if (HIWORD(wParam
) == BN_CLICKED
||
507 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
512 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
514 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
520 strcpy (str
, sessions
[n
]);
522 save_settings (str
, !!strcmp(str
, "Default Settings"));
523 get_sesslist (FALSE
);
525 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
527 for (i
= 0; i
< nsessions
; i
++)
528 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
529 0, (LPARAM
) (sessions
[i
]));
530 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
536 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
537 HIWORD(wParam
) != BN_CLICKED
&&
538 HIWORD(wParam
) != BN_DOUBLECLICKED
)
540 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
541 HIWORD(wParam
) != LBN_DBLCLK
)
544 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
550 load_settings (sessions
[n
],
551 !!strcmp(sessions
[n
], "Default Settings"));
552 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
553 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
554 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
555 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
557 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
558 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
561 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
563 * A double-click on a saved session should
564 * actually start the session, not just load it.
565 * Unless it's Default Settings or some other
566 * host-less set of saved settings.
575 if (HIWORD(wParam
) == BN_CLICKED
||
576 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
577 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
579 if (n
== LB_ERR
|| n
== 0) {
583 del_session(sessions
[n
]);
584 get_sesslist (FALSE
);
586 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
588 for (i
= 0; i
< nsessions
; i
++)
589 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
590 0, (LPARAM
) (sessions
[i
]));
591 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
596 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
599 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
600 WPARAM wParam
, LPARAM lParam
) {
603 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
604 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
605 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
606 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
607 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
608 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
609 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
610 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
611 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPAPPLIC
,
612 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
615 if (HIWORD(wParam
) == BN_CLICKED
||
616 HIWORD(wParam
) == BN_DOUBLECLICKED
)
617 switch (LOWORD(wParam
)) {
620 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
624 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
628 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
632 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
636 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
640 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
643 static void fmtfont (char *buf
) {
644 sprintf (buf
, "Font: %s, ", cfg
.font
);
646 strcat(buf
, "bold, ");
647 if (cfg
.fontheight
== 0)
648 strcat (buf
, "default height");
650 sprintf (buf
+strlen(buf
), "%d-%s",
651 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
652 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
655 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
656 WPARAM wParam
, LPARAM lParam
) {
659 char fontstatic
[256];
663 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
664 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
665 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
666 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
667 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
668 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
669 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
670 fmtfont (fontstatic
);
671 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
672 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
673 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
674 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
675 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
679 switch (LOWORD(wParam
)) {
681 if (HIWORD(wParam
) == BN_CLICKED
||
682 HIWORD(wParam
) == BN_DOUBLECLICKED
)
683 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
686 if (HIWORD(wParam
) == BN_CLICKED
||
687 HIWORD(wParam
) == BN_DOUBLECLICKED
)
688 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
691 if (HIWORD(wParam
) == BN_CLICKED
||
692 HIWORD(wParam
) == BN_DOUBLECLICKED
)
693 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
696 if (HIWORD(wParam
) == BN_CLICKED
||
697 HIWORD(wParam
) == BN_DOUBLECLICKED
)
698 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
701 if (HIWORD(wParam
) == EN_CHANGE
)
702 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
705 if (HIWORD(wParam
) == EN_CHANGE
)
706 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
709 if (HIWORD(wParam
) == EN_CHANGE
)
710 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
712 case IDC2_CHOOSEFONT
:
713 lf
.lfHeight
= cfg
.fontheight
;
714 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
715 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
716 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
717 lf
.lfCharSet
= ANSI_CHARSET
;
718 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
719 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
720 lf
.lfQuality
= DEFAULT_QUALITY
;
721 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
722 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
723 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
725 cf
.lStructSize
= sizeof(cf
);
728 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
729 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
731 if (ChooseFont (&cf
)) {
732 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
733 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
734 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
735 cfg
.fontheight
= lf
.lfHeight
;
736 fmtfont (fontstatic
);
737 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
740 case IDC2_VTXWINDOWS
:
745 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
746 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
747 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
753 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
756 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
757 WPARAM wParam
, LPARAM lParam
) {
762 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
763 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
764 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
766 char *p
= cfg
.environmt
;
768 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
773 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
774 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
777 switch (LOWORD(wParam
)) {
779 if (HIWORD(wParam
) == EN_CHANGE
)
780 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
781 sizeof(cfg
.termtype
)-1);
784 if (HIWORD(wParam
) == EN_CHANGE
)
785 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
786 sizeof(cfg
.termspeed
)-1);
789 if (HIWORD(wParam
) == EN_CHANGE
)
790 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
791 sizeof(cfg
.username
)-1);
795 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
798 if (HIWORD(wParam
) == BN_CLICKED
||
799 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
800 char str
[sizeof(cfg
.environmt
)];
802 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
807 p
= str
+ strlen(str
);
809 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
819 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
821 p
[strlen(str
)+1] = '\0';
822 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
824 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
825 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
827 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
828 MB_OK
| MB_ICONERROR
);
833 if (HIWORD(wParam
) != BN_CLICKED
&&
834 HIWORD(wParam
) != BN_DOUBLECLICKED
)
836 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
842 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
869 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
872 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
873 WPARAM wParam
, LPARAM lParam
) {
876 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
877 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
878 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
879 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERDES
,
880 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
881 cfg
.cipher
== CIPHER_DES ? IDC3_CIPHERDES
:
886 switch (LOWORD(wParam
)) {
888 if (HIWORD(wParam
) == EN_CHANGE
)
889 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
890 sizeof(cfg
.termtype
)-1);
893 if (HIWORD(wParam
) == EN_CHANGE
)
894 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
895 sizeof(cfg
.username
)-1);
898 if (HIWORD(wParam
) == BN_CLICKED
||
899 HIWORD(wParam
) == BN_DOUBLECLICKED
)
900 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
902 case IDC3_CIPHER3DES
:
903 case IDC3_CIPHERBLOWF
:
905 if (HIWORD(wParam
) == BN_CLICKED
||
906 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
907 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
908 cfg
.cipher
= CIPHER_3DES
;
909 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
910 cfg
.cipher
= CIPHER_BLOWFISH
;
911 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERDES
))
912 cfg
.cipher
= CIPHER_DES
;
918 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
921 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
922 WPARAM wParam
, LPARAM lParam
) {
927 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
928 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
930 static int tabs
[4] = {25, 61, 96, 128};
931 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
934 for (i
=0; i
<256; i
++) {
936 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
937 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
939 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
944 switch (LOWORD(wParam
)) {
947 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
953 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
958 for (i
=0; i
<256; i
++)
959 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
963 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
964 LB_DELETESTRING
, i
, 0);
965 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
966 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
968 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
978 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
981 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
982 WPARAM wParam
, LPARAM lParam
) {
983 static const char *const colours
[] = {
984 "Default Foreground", "Default Bold Foreground",
985 "Default Background", "Default Bold Background",
986 "Cursor Text", "Cursor Colour",
987 "ANSI Black", "ANSI Black Bold",
988 "ANSI Red", "ANSI Red Bold",
989 "ANSI Green", "ANSI Green Bold",
990 "ANSI Yellow", "ANSI Yellow Bold",
991 "ANSI Blue", "ANSI Blue Bold",
992 "ANSI Magenta", "ANSI Magenta Bold",
993 "ANSI Cyan", "ANSI Cyan Bold",
994 "ANSI White", "ANSI White Bold"
996 static const int permanent
[] = {
997 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
998 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
999 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1003 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
1004 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1007 for (i
=0; i
<22; i
++)
1008 if (cfg
.bold_colour
|| permanent
[i
])
1009 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1010 (LPARAM
) colours
[i
]);
1012 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1013 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1014 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1015 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1018 switch (LOWORD(wParam
)) {
1019 case IDC5_BOLDCOLOUR
:
1020 if (HIWORD(wParam
) == BN_CLICKED
||
1021 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1023 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1024 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1025 if (cfg
.bold_colour
&& n
!=22) {
1026 for (i
=0; i
<22; i
++)
1028 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1030 (LPARAM
) colours
[i
]);
1031 } else if (!cfg
.bold_colour
&& n
!=12) {
1034 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1035 LB_DELETESTRING
, i
, 0);
1040 if (HIWORD(wParam
) == BN_CLICKED
||
1041 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1042 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1045 if (HIWORD(wParam
) == LBN_DBLCLK
||
1046 HIWORD(wParam
) == LBN_SELCHANGE
) {
1047 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1049 if (!cfg
.bold_colour
)
1050 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1051 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1052 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1053 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1057 if (HIWORD(wParam
) == BN_CLICKED
||
1058 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1059 static CHOOSECOLOR cc
;
1060 static DWORD custom
[16] = {0}; /* zero initialisers */
1061 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1063 if (!cfg
.bold_colour
)
1064 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1065 cc
.lStructSize
= sizeof(cc
);
1066 cc
.hwndOwner
= hwnd
;
1067 cc
.hInstance
= hinst
;
1068 cc
.lpCustColors
= custom
;
1069 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1071 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1072 if (ChooseColor(&cc
)) {
1074 (unsigned char) (cc
.rgbResult
& 0xFF);
1076 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1078 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1079 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1081 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1083 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1091 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1094 static DLGPROC panelproc
[NPANELS
] = {
1095 ConnectionProc
, KeyboardProc
, TerminalProc
,
1096 TelnetProc
, SshProc
, SelectionProc
, ColourProc
1098 static char *panelids
[NPANELS
] = {
1099 MAKEINTRESOURCE(IDD_PANEL0
),
1100 MAKEINTRESOURCE(IDD_PANEL1
),
1101 MAKEINTRESOURCE(IDD_PANEL2
),
1102 MAKEINTRESOURCE(IDD_PANEL3
),
1103 MAKEINTRESOURCE(IDD_PANEL35
),
1104 MAKEINTRESOURCE(IDD_PANEL4
),
1105 MAKEINTRESOURCE(IDD_PANEL5
)
1107 static char *names
[NPANELS
] = {
1108 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1111 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6 };
1112 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6 };
1114 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1115 WPARAM wParam
, LPARAM lParam
,
1116 int npanels
, int *panelnums
, HWND
*page
) {
1121 { /* centre the window */
1124 hw
= GetDesktopWindow();
1125 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1126 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1127 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1128 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1131 { /* initialise the tab control */
1135 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1136 for (i
=0; i
<npanels
; i
++) {
1137 tab
.mask
= TCIF_TEXT
;
1138 tab
.pszText
= names
[panelnums
[i
]];
1139 TabCtrl_InsertItem (hw
, i
, &tab
);
1141 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1142 hwnd, panelproc[panelnums[0]]);*/
1143 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1144 hwnd
, panelproc
[panelnums
[0]]);
1145 SetWindowLong (*page
, GWL_EXSTYLE
,
1146 GetWindowLong (*page
, GWL_EXSTYLE
) |
1147 WS_EX_CONTROLPARENT
);
1152 if (LOWORD(wParam
) == IDC_TAB
&&
1153 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1154 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1156 DestroyWindow (*page
);
1157 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1158 hwnd, panelproc[panelnums[i]]);*/
1159 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1160 hwnd
, panelproc
[panelnums
[i
]]);
1161 SetWindowLong (*page
, GWL_EXSTYLE
,
1162 GetWindowLong (*page
, GWL_EXSTYLE
) |
1163 WS_EX_CONTROLPARENT
);
1164 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1168 /* case WM_CTLCOLORDLG: */
1169 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1171 switch (LOWORD(wParam
)) {
1174 EndDialog (hwnd
, 1);
1179 EndDialog (hwnd
, 0);
1184 EndDialog (hwnd
, 0);
1190 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1191 WPARAM wParam
, LPARAM lParam
) {
1196 static HWND page
= NULL
;
1198 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1201 * If the Connection panel is active and the Session List
1202 * box is selected, we treat a press of Open to have an
1203 * implicit press of Load preceding it.
1205 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1206 i
= TabCtrl_GetCurSel(hw
);
1207 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1208 page
&& implicit_load_ok
) {
1209 SendMessage (page
, WM_COMMAND
,
1210 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1214 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1215 EnableWindow(hwnd
, 0);
1216 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1217 GetParent(hwnd
), AboutProc
);
1218 EnableWindow(hwnd
, 1);
1220 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1221 MAIN_NPANELS
, mainp
, &page
);
1224 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1225 WPARAM wParam
, LPARAM lParam
) {
1227 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1228 RECONF_NPANELS
, reconfp
, &page
);
1231 static void get_sesslist(int allocate
) {
1232 static char *buffer
;
1233 int buflen
, bufsize
, i
, ret
;
1234 char otherbuf
[2048];
1239 if (RegCreateKey(HKEY_CURRENT_USER
,
1240 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1243 buflen
= bufsize
= 0;
1247 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1248 if (ret
== ERROR_SUCCESS
) {
1249 bufsize
= buflen
+ 2048;
1250 buffer
= srealloc(buffer
, bufsize
);
1251 unmungestr(otherbuf
, buffer
+buflen
);
1252 buflen
+= strlen(buffer
+buflen
)+1;
1254 } while (ret
== ERROR_SUCCESS
);
1255 buffer
= srealloc(buffer
, buflen
+1);
1256 buffer
[buflen
] = '\0';
1259 nsessions
= 1; /* "Default Settings" counts as one */
1261 if (strcmp(p
, "Default Settings"))
1267 sessions
= smalloc(nsessions
* sizeof(char *));
1268 sessions
[0] = "Default Settings";
1272 if (strcmp(p
, "Default Settings"))
1283 int do_config (void) {
1287 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1288 get_sesslist(FALSE
);
1293 int do_reconfig (HWND hwnd
) {
1297 backup_cfg
= cfg
; /* structure copy */
1298 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1300 cfg
= backup_cfg
; /* structure copy */
1304 void do_defaults (char *session
) {
1306 load_settings (session
, TRUE
);
1308 load_settings ("Default Settings", FALSE
);
1311 void lognegot (char *string
) {
1312 if (nnegots
>= negsize
) {
1314 negots
= srealloc (negots
, negsize
* sizeof(*negots
));
1316 negots
[nnegots
] = smalloc(1+strlen(string
));
1317 strcpy (negots
[nnegots
], string
);
1320 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1324 void shownegot (HWND hwnd
) {
1326 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1328 ShowWindow (logbox
, SW_SHOWNORMAL
);
1332 void showabout (HWND hwnd
) {
1334 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1336 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1340 void verify_ssh_host_key(char *host
, struct RSAKey
*key
) {
1341 char *keystr
, *otherstr
, *mungedhost
;
1346 * Format the key into a string.
1348 len
= rsastr_len(key
);
1349 keystr
= malloc(len
);
1351 fatalbox("Out of memory");
1352 rsastr_fmt(keystr
, key
);
1355 * Now read a saved key in from the registry and see what it
1358 otherstr
= malloc(len
);
1359 mungedhost
= malloc(3*strlen(host
)+1);
1360 if (!otherstr
|| !mungedhost
)
1361 fatalbox("Out of memory");
1363 mungestr(host
, mungedhost
);
1365 if (RegCreateKey(HKEY_CURRENT_USER
, PUTTY_REG_POS
"\\SshHostKeys",
1366 &rkey
) != ERROR_SUCCESS
) {
1367 if (MessageBox(NULL
, "PuTTY was unable to open the host key cache\n"
1368 "in the registry. There is thus no way to tell\n"
1369 "if the remote host is what you think it is.\n"
1370 "Connect anyway?", "PuTTY Problem",
1371 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1374 DWORD readlen
= len
;
1378 ret
= RegQueryValueEx(rkey
, mungedhost
, NULL
,
1379 &type
, otherstr
, &readlen
);
1381 if (ret
== ERROR_MORE_DATA
||
1382 (ret
== ERROR_SUCCESS
&& type
== REG_SZ
&&
1383 strcmp(otherstr
, keystr
))) {
1384 if (MessageBox(NULL
,
1385 "This host's host key is different from the\n"
1386 "one cached in the registry! Someone may be\n"
1387 "impersonating this host for malicious reasons;\n"
1388 "alternatively, the host key may have changed\n"
1389 "due to sloppy system administration.\n"
1390 "Replace key in registry and connect?",
1391 "PuTTY: Security Warning",
1392 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1394 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,
1396 } else if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) {
1397 if (MessageBox(NULL
,
1398 "This host's host key is not cached in the\n"
1399 "registry. Do you want to add it to the cache\n"
1400 "and carry on connecting?",
1402 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1404 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,