13 #define MAIN_NPANELS 7
14 #define RECONF_NPANELS 4
16 static const char *const puttystr
= PUTTY_REG_POS
"\\Sessions";
18 static void get_sesslist(int allocate
);
20 static char **negots
= NULL
;
21 static int nnegots
= 0, negsize
= 0;
22 static HWND logbox
= NULL
, abtbox
= NULL
;
24 static char hex
[16] = "0123456789ABCDEF";
26 static void mungestr(char *in
, char *out
) {
30 if (*in
== ' ' || *in
== '\\' || *in
== '*' || *in
== '?' ||
31 *in
== '%' || *in
< ' ' || *in
> '~' || (*in
== '.' && !candot
)) {
33 *out
++ = hex
[((unsigned char)*in
) >> 4];
34 *out
++ = hex
[((unsigned char)*in
) & 15];
44 static void unmungestr(char *in
, char *out
) {
46 if (*in
== '%' && in
[1] && in
[2]) {
49 i
= in
[1] - '0'; i
-= (i
> 9 ?
7 : 0);
50 j
= in
[2] - '0'; j
-= (j
> 9 ?
7 : 0);
61 static void wpps(HKEY key
, LPCTSTR name
, LPCTSTR value
) {
62 RegSetValueEx(key
, name
, 0, REG_SZ
, value
, 1+strlen(value
));
65 static void wppi(HKEY key
, LPCTSTR name
, int value
) {
66 RegSetValueEx(key
, name
, 0, REG_DWORD
,
67 (CONST BYTE
*)&value
, sizeof(value
));
70 static void gpps(HKEY key
, LPCTSTR name
, LPCTSTR def
,
71 LPTSTR val
, int len
) {
76 RegQueryValueEx(key
, name
, 0, &type
, val
, &size
) != ERROR_SUCCESS
||
78 strncpy(val
, def
, len
);
83 static void gppi(HKEY key
, LPCTSTR name
, int def
, int *i
) {
84 DWORD type
, val
, size
;
88 RegQueryValueEx(key
, name
, 0, &type
,
89 (BYTE
*)&val
, &size
) != ERROR_SUCCESS
||
90 size
!= sizeof(val
) || type
!= REG_DWORD
)
96 static HINSTANCE hinst
;
98 static char **sessions
;
101 static int readytogo
;
103 static void save_settings (char *section
, int do_host
) {
105 HKEY subkey1
, sesskey
;
108 p
= malloc(3*strlen(section
)+1);
109 mungestr(section
, p
);
111 if (RegCreateKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
)!=ERROR_SUCCESS
||
112 RegCreateKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
117 RegCloseKey(subkey1
);
119 wppi (sesskey
, "Present", 1);
121 wpps (sesskey
, "HostName", cfg
.host
);
122 wppi (sesskey
, "PortNumber", cfg
.port
);
123 wpps (sesskey
, "Protocol",
124 cfg
.protocol
== PROT_SSH ?
"ssh" : "telnet");
126 wppi (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
127 wpps (sesskey
, "TerminalType", cfg
.termtype
);
128 wpps (sesskey
, "TerminalSpeed", cfg
.termspeed
);
130 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
136 if (c
== '=' || c
== ',' || c
== '\\')
146 wpps (sesskey
, "Environment", buf
);
148 wpps (sesskey
, "UserName", cfg
.username
);
149 wppi (sesskey
, "NoPTY", cfg
.nopty
);
150 wpps (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
152 wppi (sesskey
, "RFCEnviron", cfg
.rfc_environ
);
153 wppi (sesskey
, "BackspaceIsDelete", cfg
.bksp_is_delete
);
154 wppi (sesskey
, "RXVTHomeEnd", cfg
.rxvt_homeend
);
155 wppi (sesskey
, "LinuxFunctionKeys", cfg
.linux_funkeys
);
156 wppi (sesskey
, "ApplicationCursorKeys", cfg
.app_cursor
);
157 wppi (sesskey
, "ApplicationKeypad", cfg
.app_keypad
);
158 wppi (sesskey
, "ScrollbackLines", cfg
.savelines
);
159 wppi (sesskey
, "DECOriginMode", cfg
.dec_om
);
160 wppi (sesskey
, "AutoWrapMode", cfg
.wrap_mode
);
161 wppi (sesskey
, "LFImpliesCR", cfg
.lfhascr
);
162 wppi (sesskey
, "WinNameAlways", cfg
.win_name_always
);
163 wppi (sesskey
, "TermWidth", cfg
.width
);
164 wppi (sesskey
, "TermHeight", cfg
.height
);
165 wpps (sesskey
, "Font", cfg
.font
);
166 wppi (sesskey
, "FontIsBold", cfg
.fontisbold
);
167 wppi (sesskey
, "FontHeight", cfg
.fontheight
);
168 wppi (sesskey
, "FontVTMode", cfg
.vtmode
);
169 wppi (sesskey
, "TryPalette", cfg
.try_palette
);
170 wppi (sesskey
, "BoldAsColour", cfg
.bold_colour
);
171 for (i
=0; i
<22; i
++) {
172 char buf
[20], buf2
[30];
173 sprintf(buf
, "Colour%d", i
);
174 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
175 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
176 wpps (sesskey
, buf
, buf2
);
178 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
179 for (i
=0; i
<256; i
+=32) {
180 char buf
[20], buf2
[256];
182 sprintf(buf
, "Wordness%d", i
);
184 for (j
=i
; j
<i
+32; j
++) {
185 sprintf(buf2
+strlen(buf2
), "%s%d",
186 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
188 wpps (sesskey
, buf
, buf2
);
191 RegCloseKey(sesskey
);
194 static void del_session (char *section
) {
198 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
)
201 p
= malloc(3*strlen(section
)+1);
202 mungestr(section
, p
);
203 RegDeleteKey(subkey1
, p
);
206 RegCloseKey(subkey1
);
209 static void load_settings (char *section
, int do_host
) {
211 HKEY subkey1
, sesskey
;
214 p
= malloc(3*strlen(section
)+1);
215 mungestr(section
, p
);
217 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
220 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
223 RegCloseKey(subkey1
);
230 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
231 gppi (sesskey
, "PortNumber", 23, &cfg
.port
);
232 gpps (sesskey
, "Protocol", "telnet", prot
, 10);
233 if (!strcmp(prot
, "ssh"))
234 cfg
.protocol
= PROT_SSH
;
236 cfg
.protocol
= PROT_TELNET
;
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
;
274 cfg
.cipher
= CIPHER_3DES
;
276 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
277 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
278 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
279 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.linux_funkeys
);
280 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
281 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
282 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
283 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
284 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
285 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
286 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
287 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
288 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
289 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
290 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
291 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
292 gppi (sesskey
, "FontVTMode", VT_POORMAN
, &cfg
.vtmode
);
293 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
294 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
295 for (i
=0; i
<22; i
++) {
296 static char *defaults
[] = {
297 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
298 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
299 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
300 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
301 "85,255,255", "187,187,187", "255,255,255"
303 char buf
[20], buf2
[30];
304 sprintf(buf
, "Colour%d", i
);
305 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
306 sscanf(buf2
, "%d,%d,%d", &cfg
.colours
[i
][0],
307 &cfg
.colours
[i
][1], &cfg
.colours
[i
][2]);
309 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
310 for (i
=0; i
<256; i
+=32) {
311 static char *defaults
[] = {
312 "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",
313 "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",
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,2",
315 "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",
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 "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",
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",
319 "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 char buf
[20], buf2
[256], *p
;
323 sprintf(buf
, "Wordness%d", i
);
324 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
326 for (j
=i
; j
<i
+32; j
++) {
328 while (*p
&& *p
!= ',') p
++;
329 if (*p
== ',') *p
++ = '\0';
330 cfg
.wordness
[j
] = atoi(q
);
333 RegCloseKey(sesskey
);
336 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
339 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
344 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
345 WPARAM wParam
, LPARAM lParam
) {
350 for (i
=0; i
<nnegots
; i
++)
351 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
352 0, (LPARAM
)negots
[i
]);
354 /* case WM_CTLCOLORDLG: */
355 /* return (int) GetStockObject (LTGRAY_BRUSH); */
357 switch (LOWORD(wParam
)) {
360 DestroyWindow (hwnd
);
366 DestroyWindow (hwnd
);
372 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
373 WPARAM wParam
, LPARAM lParam
) {
378 switch (LOWORD(wParam
)) {
381 DestroyWindow (hwnd
);
387 DestroyWindow (hwnd
);
393 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
394 WPARAM wParam
, LPARAM lParam
) {
397 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
399 /* case WM_CTLCOLORDLG: */
400 /* return (int) GetStockObject (LTGRAY_BRUSH); */
401 /* case WM_CTLCOLORSTATIC: */
402 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
403 /* return (int) GetStockObject (LTGRAY_BRUSH); */
405 switch (LOWORD(wParam
)) {
408 DestroyWindow (hwnd
);
411 EnableWindow(hwnd
, 0);
412 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
414 EnableWindow(hwnd
, 1);
420 DestroyWindow (hwnd
);
426 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
427 WPARAM wParam
, LPARAM lParam
) {
430 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
432 /* case WM_CTLCOLORDLG: */
433 /* return (int) GetStockObject (LTGRAY_BRUSH); */
434 /* case WM_CTLCOLORSTATIC: */
435 /* case WM_CTLCOLORBTN: */
436 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
437 /* return (int) GetStockObject (LTGRAY_BRUSH); */
439 DestroyWindow (hwnd
);
445 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
446 WPARAM wParam
, LPARAM lParam
) {
451 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
452 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
453 for (i
= 0; i
< nsessions
; i
++)
454 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
455 0, (LPARAM
) (sessions
[i
]));
456 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
457 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
: IDC0_PROTTELNET
);
458 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
462 * Button release should trigger WM_OK if there was a
463 * previous double click on the session list.
467 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
470 switch (LOWORD(wParam
)) {
471 case IDC0_PROTTELNET
:
473 if (HIWORD(wParam
) == BN_CLICKED
||
474 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
475 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
476 cfg
.protocol
= i ? PROT_SSH
: PROT_TELNET
;
477 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
478 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
479 cfg
.port
= i ?
22 : 23;
480 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
485 if (HIWORD(wParam
) == EN_CHANGE
)
486 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
490 if (HIWORD(wParam
) == EN_CHANGE
)
491 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
494 if (HIWORD(wParam
) == BN_CLICKED
||
495 HIWORD(wParam
) == BN_DOUBLECLICKED
)
496 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
499 if (HIWORD(wParam
) == EN_CHANGE
)
500 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
504 if (HIWORD(wParam
) == BN_CLICKED
||
505 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
510 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
512 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
518 strcpy (str
, sessions
[n
]);
520 save_settings (str
, !!strcmp(str
, "Default Settings"));
521 get_sesslist (FALSE
);
523 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
525 for (i
= 0; i
< nsessions
; i
++)
526 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
527 0, (LPARAM
) (sessions
[i
]));
528 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
534 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
535 HIWORD(wParam
) != BN_CLICKED
&&
536 HIWORD(wParam
) != BN_DOUBLECLICKED
)
538 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
539 HIWORD(wParam
) != LBN_DBLCLK
)
542 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
548 load_settings (sessions
[n
],
549 !!strcmp(sessions
[n
], "Default Settings"));
550 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
551 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
552 CheckRadioButton (hwnd
, IDC0_PROTTELNET
, IDC0_PROTSSH
,
553 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
555 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
556 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
559 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
561 * A double-click on a saved session should
562 * actually start the session, not just load it.
563 * Unless it's Default Settings or some other
564 * host-less set of saved settings.
573 if (HIWORD(wParam
) == BN_CLICKED
||
574 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
575 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
577 if (n
== LB_ERR
|| n
== 0) {
581 del_session(sessions
[n
]);
582 get_sesslist (FALSE
);
584 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
586 for (i
= 0; i
< nsessions
; i
++)
587 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
588 0, (LPARAM
) (sessions
[i
]));
589 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
594 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
597 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
598 WPARAM wParam
, LPARAM lParam
) {
601 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
602 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
603 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
604 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
605 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
606 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
607 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
608 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
609 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPAPPLIC
,
610 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
613 if (HIWORD(wParam
) == BN_CLICKED
||
614 HIWORD(wParam
) == BN_DOUBLECLICKED
)
615 switch (LOWORD(wParam
)) {
618 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
622 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
626 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
630 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
634 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
638 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
641 static void fmtfont (char *buf
) {
642 sprintf (buf
, "Font: %s, ", cfg
.font
);
644 strcat(buf
, "bold, ");
645 if (cfg
.fontheight
== 0)
646 strcat (buf
, "default height");
648 sprintf (buf
+strlen(buf
), "%d-%s",
649 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
650 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
653 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
654 WPARAM wParam
, LPARAM lParam
) {
657 char fontstatic
[256];
661 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
662 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
663 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
664 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
665 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
666 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
667 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
668 fmtfont (fontstatic
);
669 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
670 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
671 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
672 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
673 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
677 switch (LOWORD(wParam
)) {
679 if (HIWORD(wParam
) == BN_CLICKED
||
680 HIWORD(wParam
) == BN_DOUBLECLICKED
)
681 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
684 if (HIWORD(wParam
) == BN_CLICKED
||
685 HIWORD(wParam
) == BN_DOUBLECLICKED
)
686 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
689 if (HIWORD(wParam
) == BN_CLICKED
||
690 HIWORD(wParam
) == BN_DOUBLECLICKED
)
691 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
694 if (HIWORD(wParam
) == BN_CLICKED
||
695 HIWORD(wParam
) == BN_DOUBLECLICKED
)
696 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
699 if (HIWORD(wParam
) == EN_CHANGE
)
700 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
703 if (HIWORD(wParam
) == EN_CHANGE
)
704 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
707 if (HIWORD(wParam
) == EN_CHANGE
)
708 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
710 case IDC2_CHOOSEFONT
:
711 lf
.lfHeight
= cfg
.fontheight
;
712 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
713 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
714 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
715 lf
.lfCharSet
= ANSI_CHARSET
;
716 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
717 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
718 lf
.lfQuality
= DEFAULT_QUALITY
;
719 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
720 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
721 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
723 cf
.lStructSize
= sizeof(cf
);
726 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
727 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
729 if (ChooseFont (&cf
)) {
730 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
731 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
732 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
733 cfg
.fontheight
= lf
.lfHeight
;
734 fmtfont (fontstatic
);
735 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
738 case IDC2_VTXWINDOWS
:
743 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
744 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
745 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
751 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
754 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
755 WPARAM wParam
, LPARAM lParam
) {
760 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
761 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
762 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
764 char *p
= cfg
.environmt
;
766 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
771 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
772 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
775 switch (LOWORD(wParam
)) {
777 if (HIWORD(wParam
) == EN_CHANGE
)
778 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
779 sizeof(cfg
.termtype
)-1);
782 if (HIWORD(wParam
) == EN_CHANGE
)
783 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
784 sizeof(cfg
.termspeed
)-1);
787 if (HIWORD(wParam
) == EN_CHANGE
)
788 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
789 sizeof(cfg
.username
)-1);
793 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
796 if (HIWORD(wParam
) == BN_CLICKED
||
797 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
798 char str
[sizeof(cfg
.environmt
)];
800 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
805 p
= str
+ strlen(str
);
807 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
817 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
819 p
[strlen(str
)+1] = '\0';
820 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
822 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
823 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
825 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
826 MB_OK
| MB_ICONERROR
);
831 if (HIWORD(wParam
) != BN_CLICKED
&&
832 HIWORD(wParam
) != BN_DOUBLECLICKED
)
834 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
840 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
867 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
870 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
871 WPARAM wParam
, LPARAM lParam
) {
874 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
875 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
876 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
877 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERBLOWF
,
878 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
882 switch (LOWORD(wParam
)) {
884 if (HIWORD(wParam
) == EN_CHANGE
)
885 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
886 sizeof(cfg
.termtype
)-1);
889 if (HIWORD(wParam
) == EN_CHANGE
)
890 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
891 sizeof(cfg
.username
)-1);
894 if (HIWORD(wParam
) == BN_CLICKED
||
895 HIWORD(wParam
) == BN_DOUBLECLICKED
)
896 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
898 case IDC3_CIPHER3DES
:
899 case IDC3_CIPHERBLOWF
:
900 if (HIWORD(wParam
) == BN_CLICKED
||
901 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
902 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
903 cfg
.cipher
= CIPHER_3DES
;
904 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
905 cfg
.cipher
= CIPHER_BLOWFISH
;
911 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
914 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
915 WPARAM wParam
, LPARAM lParam
) {
920 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
921 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
923 static int tabs
[4] = {25, 61, 96, 128};
924 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
927 for (i
=0; i
<256; i
++) {
929 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
930 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
932 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
937 switch (LOWORD(wParam
)) {
940 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
946 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
951 for (i
=0; i
<256; i
++)
952 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
956 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
957 LB_DELETESTRING
, i
, 0);
958 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
959 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
961 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
971 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
974 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
975 WPARAM wParam
, LPARAM lParam
) {
976 static const char *const colours
[] = {
977 "Default Foreground", "Default Bold Foreground",
978 "Default Background", "Default Bold Background",
979 "Cursor Text", "Cursor Colour",
980 "ANSI Black", "ANSI Black Bold",
981 "ANSI Red", "ANSI Red Bold",
982 "ANSI Green", "ANSI Green Bold",
983 "ANSI Yellow", "ANSI Yellow Bold",
984 "ANSI Blue", "ANSI Blue Bold",
985 "ANSI Magenta", "ANSI Magenta Bold",
986 "ANSI Cyan", "ANSI Cyan Bold",
987 "ANSI White", "ANSI White Bold"
989 static const int permanent
[] = {
990 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
991 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
992 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
996 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
997 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1000 for (i
=0; i
<22; i
++)
1001 if (cfg
.bold_colour
|| permanent
[i
])
1002 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1003 (LPARAM
) colours
[i
]);
1005 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1006 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1007 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1008 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1011 switch (LOWORD(wParam
)) {
1012 case IDC5_BOLDCOLOUR
:
1013 if (HIWORD(wParam
) == BN_CLICKED
||
1014 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1016 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1017 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1018 if (cfg
.bold_colour
&& n
!=22) {
1019 for (i
=0; i
<22; i
++)
1021 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1023 (LPARAM
) colours
[i
]);
1024 } else if (!cfg
.bold_colour
&& n
!=12) {
1027 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1028 LB_DELETESTRING
, i
, 0);
1033 if (HIWORD(wParam
) == BN_CLICKED
||
1034 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1035 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1038 if (HIWORD(wParam
) == LBN_DBLCLK
||
1039 HIWORD(wParam
) == LBN_SELCHANGE
) {
1040 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1042 if (!cfg
.bold_colour
)
1043 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1044 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1045 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1046 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1050 if (HIWORD(wParam
) == BN_CLICKED
||
1051 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1052 static CHOOSECOLOR cc
;
1053 static DWORD custom
[16] = {0}; /* zero initialisers */
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 cc
.lStructSize
= sizeof(cc
);
1059 cc
.hwndOwner
= hwnd
;
1060 cc
.hInstance
= hinst
;
1061 cc
.lpCustColors
= custom
;
1062 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1064 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1065 if (ChooseColor(&cc
)) {
1067 (unsigned char) (cc
.rgbResult
& 0xFF);
1069 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1071 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1072 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1074 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1076 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1084 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1087 static DLGPROC panelproc
[NPANELS
] = {
1088 ConnectionProc
, KeyboardProc
, TerminalProc
,
1089 TelnetProc
, SshProc
, SelectionProc
, ColourProc
1091 static char *panelids
[NPANELS
] = {
1092 MAKEINTRESOURCE(IDD_PANEL0
),
1093 MAKEINTRESOURCE(IDD_PANEL1
),
1094 MAKEINTRESOURCE(IDD_PANEL2
),
1095 MAKEINTRESOURCE(IDD_PANEL3
),
1096 MAKEINTRESOURCE(IDD_PANEL35
),
1097 MAKEINTRESOURCE(IDD_PANEL4
),
1098 MAKEINTRESOURCE(IDD_PANEL5
)
1100 static char *names
[NPANELS
] = {
1101 "Connection", "Keyboard", "Terminal", "Telnet", "SSH", "Selection", "Colours"
1104 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6 };
1105 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6 };
1107 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1108 WPARAM wParam
, LPARAM lParam
,
1109 int npanels
, int *panelnums
, HWND
*page
) {
1114 { /* centre the window */
1117 hw
= GetDesktopWindow();
1118 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1119 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1120 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1121 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1124 { /* initialise the tab control */
1128 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1129 for (i
=0; i
<npanels
; i
++) {
1130 tab
.mask
= TCIF_TEXT
;
1131 tab
.pszText
= names
[panelnums
[i
]];
1132 TabCtrl_InsertItem (hw
, i
, &tab
);
1134 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1135 hwnd, panelproc[panelnums[0]]);*/
1136 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1137 hwnd
, panelproc
[panelnums
[0]]);
1138 SetWindowLong (*page
, GWL_EXSTYLE
,
1139 GetWindowLong (*page
, GWL_EXSTYLE
) |
1140 WS_EX_CONTROLPARENT
);
1145 if (LOWORD(wParam
) == IDC_TAB
&&
1146 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1147 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1149 DestroyWindow (*page
);
1150 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1151 hwnd, panelproc[panelnums[i]]);*/
1152 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1153 hwnd
, panelproc
[panelnums
[i
]]);
1154 SetWindowLong (*page
, GWL_EXSTYLE
,
1155 GetWindowLong (*page
, GWL_EXSTYLE
) |
1156 WS_EX_CONTROLPARENT
);
1157 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1161 /* case WM_CTLCOLORDLG: */
1162 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1164 switch (LOWORD(wParam
)) {
1167 EndDialog (hwnd
, 1);
1172 EndDialog (hwnd
, 0);
1177 EndDialog (hwnd
, 0);
1183 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1184 WPARAM wParam
, LPARAM lParam
) {
1189 static HWND page
= NULL
;
1191 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1194 * If the Connection panel is active and the Session List
1195 * box is selected, we treat a press of Open to have an
1196 * implicit press of Load preceding it.
1198 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1199 i
= TabCtrl_GetCurSel(hw
);
1200 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1201 page
&& implicit_load_ok
) {
1202 SendMessage (page
, WM_COMMAND
,
1203 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1207 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1208 EnableWindow(hwnd
, 0);
1209 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1210 GetParent(hwnd
), AboutProc
);
1211 EnableWindow(hwnd
, 1);
1213 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1214 MAIN_NPANELS
, mainp
, &page
);
1217 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1218 WPARAM wParam
, LPARAM lParam
) {
1220 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1221 RECONF_NPANELS
, reconfp
, &page
);
1224 static void get_sesslist(int allocate
) {
1225 static char *buffer
;
1226 int buflen
, bufsize
, i
, ret
;
1227 char otherbuf
[2048];
1232 if (RegCreateKey(HKEY_CURRENT_USER
,
1233 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1236 buflen
= bufsize
= 0;
1240 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1241 if (ret
== ERROR_SUCCESS
) {
1242 bufsize
= buflen
+ 2048;
1243 buffer
= srealloc(buffer
, bufsize
);
1244 unmungestr(otherbuf
, buffer
+buflen
);
1245 buflen
+= strlen(buffer
+buflen
)+1;
1247 } while (ret
== ERROR_SUCCESS
);
1248 buffer
= srealloc(buffer
, buflen
+1);
1249 buffer
[buflen
] = '\0';
1252 nsessions
= 1; /* "Default Settings" counts as one */
1254 if (strcmp(p
, "Default Settings"))
1260 sessions
= smalloc(nsessions
* sizeof(char *));
1261 sessions
[0] = "Default Settings";
1265 if (strcmp(p
, "Default Settings"))
1276 int do_config (void) {
1280 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1281 get_sesslist(FALSE
);
1286 int do_reconfig (HWND hwnd
) {
1290 backup_cfg
= cfg
; /* structure copy */
1291 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1293 cfg
= backup_cfg
; /* structure copy */
1297 void do_defaults (char *session
) {
1299 load_settings (session
, TRUE
);
1301 load_settings ("Default Settings", FALSE
);
1304 void lognegot (char *string
) {
1305 if (nnegots
>= negsize
) {
1307 negots
= srealloc (negots
, negsize
* sizeof(*negots
));
1309 negots
[nnegots
] = smalloc(1+strlen(string
));
1310 strcpy (negots
[nnegots
], string
);
1313 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1317 void shownegot (HWND hwnd
) {
1319 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1321 ShowWindow (logbox
, SW_SHOWNORMAL
);
1325 void showabout (HWND hwnd
) {
1327 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1329 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1333 void verify_ssh_host_key(char *host
, struct RSAKey
*key
) {
1334 char *keystr
, *otherstr
, *mungedhost
;
1339 * Format the key into a string.
1341 len
= rsastr_len(key
);
1342 keystr
= malloc(len
);
1344 fatalbox("Out of memory");
1345 rsastr_fmt(keystr
, key
);
1348 * Now read a saved key in from the registry and see what it
1351 otherstr
= malloc(len
);
1352 mungedhost
= malloc(3*strlen(host
)+1);
1353 if (!otherstr
|| !mungedhost
)
1354 fatalbox("Out of memory");
1356 mungestr(host
, mungedhost
);
1358 if (RegCreateKey(HKEY_CURRENT_USER
, PUTTY_REG_POS
"\\SshHostKeys",
1359 &rkey
) != ERROR_SUCCESS
) {
1360 if (MessageBox(NULL
, "PuTTY was unable to open the host key cache\n"
1361 "in the registry. There is thus no way to tell\n"
1362 "if the remote host is what you think it is.\n"
1363 "Connect anyway?", "PuTTY Problem",
1364 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1367 DWORD readlen
= len
;
1371 ret
= RegQueryValueEx(rkey
, mungedhost
, NULL
,
1372 &type
, otherstr
, &readlen
);
1374 if (ret
== ERROR_MORE_DATA
||
1375 (ret
== ERROR_SUCCESS
&& type
== REG_SZ
&&
1376 strcmp(otherstr
, keystr
))) {
1377 if (MessageBox(NULL
,
1378 "This host's host key is different from the\n"
1379 "one cached in the registry! Someone may be\n"
1380 "impersonating this host for malicious reasons;\n"
1381 "alternatively, the host key may have changed\n"
1382 "due to sloppy system administration.\n"
1383 "Replace key in registry and connect?",
1384 "PuTTY: Security Warning",
1385 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1387 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,
1389 } else if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) {
1390 if (MessageBox(NULL
,
1391 "This host's host key is not cached in the\n"
1392 "registry. Do you want to add it to the cache\n"
1393 "and carry on connecting?",
1395 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1397 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,