X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/aca589d972c5c12706d57322e89f9dec2b2a3a00..939395a800652e2164a5426d3ba2ba3322eb8526:/windows/windlg.c diff --git a/windows/windlg.c b/windows/windlg.c index 3bad7c32..5aa20d2c 100644 --- a/windows/windlg.c +++ b/windows/windlg.c @@ -229,6 +229,57 @@ static int CALLBACK AboutProc(HWND hwnd, UINT msg, return 0; } +static int SaneDialogBox(HINSTANCE hinst, + LPCTSTR tmpl, + HWND hwndparent, + DLGPROC lpDialogFunc) +{ + WNDCLASS wc; + HWND hwnd; + MSG msg; + int flags; + int ret; + int gm; + + wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW; + wc.lpfnWndProc = DefDlgProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = DLGWINDOWEXTRA + 8; + wc.hInstance = hinst; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND +1); + wc.lpszMenuName = NULL; + wc.lpszClassName = "PuTTYConfigBox"; + RegisterClass(&wc); + + hwnd = CreateDialog(hinst, tmpl, hwndparent, lpDialogFunc); + + SetWindowLong(hwnd, BOXFLAGS, 0); /* flags */ + SetWindowLong(hwnd, BOXRESULT, 0); /* result from SaneEndDialog */ + + while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) { + flags=GetWindowLong(hwnd, BOXFLAGS); + if (!(flags & DF_END) && !IsDialogMessage(hwnd, &msg)) + DispatchMessage(&msg); + if (flags & DF_END) + break; + } + + if (gm == 0) + PostQuitMessage(msg.wParam); /* We got a WM_QUIT, pass it on */ + + ret=GetWindowLong(hwnd, BOXRESULT); + DestroyWindow(hwnd); + return ret; +} + +static void SaneEndDialog(HWND hwnd, int ret) +{ + SetWindowLong(hwnd, BOXRESULT, ret); + SetWindowLong(hwnd, BOXFLAGS, DF_END); +} + /* * Null dialog procedure. */ @@ -701,8 +752,31 @@ void showabout(HWND hwnd) DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc); } -void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, - char *keystr, char *fingerprint) +/* Helper function for verify_ssh_host_key(). */ +static VOID CALLBACK verify_ssh_host_key_help(LPHELPINFO lpHelpInfo) +{ + if (help_path) { + char *context = NULL; +#define CHECK_CTX(name) \ + do { \ + if (lpHelpInfo->dwContextId == WINHELP_CTXID_ ## name) \ + context = WINHELP_CTX_ ## name; \ + } while (0) + CHECK_CTX(errors_hostkey_absent); + CHECK_CTX(errors_hostkey_changed); +#undef CHECK_CTX + if (context) { + char *cmd = dupprintf("JI(`',`%s')", context); + WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd); + sfree(cmd); + requested_help = TRUE; + } + } +} + +int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, + char *keystr, char *fingerprint, + void (*callback)(void *ctx, int result), void *ctx) { int ret; @@ -738,40 +812,65 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, static const char mbtitle[] = "%s Security Alert"; + UINT help_button = 0; + MSGBOXPARAMS mbox; + + /* + * We use MessageBoxIndirect() because it allows us to specify a + * callback function for the Help button. + */ + mbox.cbSize = sizeof(mbox); + mbox.hInstance = hinst; + mbox.hwndOwner = hwnd; + mbox.lpfnMsgBoxCallback = &verify_ssh_host_key_help; + mbox.dwLanguageId = LANG_NEUTRAL; + + /* Do we have a help file? */ + if (help_path) + help_button = MB_HELP; + /* * Verify the key against the registry. */ ret = verify_host_key(host, port, keytype, keystr); if (ret == 0) /* success - key matched OK */ - return; + return 1; if (ret == 2) { /* key was different */ int mbret; - char *message, *title; - message = dupprintf(wrongmsg, appname, keytype, fingerprint, appname); - title = dupprintf(mbtitle, appname); - mbret = MessageBox(NULL, message, title, - MB_ICONWARNING | MB_YESNOCANCEL); - sfree(message); - sfree(title); - if (mbret == IDYES) + mbox.lpszText = dupprintf(wrongmsg, appname, keytype, fingerprint, + appname); + mbox.lpszCaption = dupprintf(mbtitle, appname); + mbox.dwContextHelpId = HELPCTXID(errors_hostkey_changed); + mbox.dwStyle = MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON3 | + help_button; + mbret = MessageBoxIndirect(&mbox); + assert(mbret==IDYES || mbret==IDNO || mbret==IDCANCEL); + sfree((void *)mbox.lpszText); + sfree((void *)mbox.lpszCaption); + if (mbret == IDYES) { store_host_key(host, port, keytype, keystr); - if (mbret == IDCANCEL) - cleanup_exit(0); + return 1; + } else if (mbret == IDNO) + return 1; + return 0; } if (ret == 1) { /* key was absent */ int mbret; - char *message, *title; - message = dupprintf(absentmsg, keytype, fingerprint, appname); - title = dupprintf(mbtitle, appname); - mbret = MessageBox(NULL, message, title, - MB_ICONWARNING | MB_YESNOCANCEL); - sfree(message); - sfree(title); + mbox.lpszText = dupprintf(absentmsg, keytype, fingerprint, appname); + mbox.lpszCaption = dupprintf(mbtitle, appname); + mbox.dwContextHelpId = HELPCTXID(errors_hostkey_absent); + mbox.dwStyle = MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON3 | + help_button; + mbret = MessageBoxIndirect(&mbox); + assert(mbret==IDYES || mbret==IDNO || mbret==IDCANCEL); + sfree((void *)mbox.lpszText); + sfree((void *)mbox.lpszCaption); if (mbret == IDYES) store_host_key(host, port, keytype, keystr); - if (mbret == IDCANCEL) - cleanup_exit(0); + if (mbret == IDNO) + return 1; + return 0; } } @@ -779,7 +878,8 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, * Ask whether the selected algorithm is acceptable (since it was * below the configured 'warn' threshold). */ -void askalg(void *frontend, const char *algtype, const char *algname) +int askalg(void *frontend, const char *algtype, const char *algname, + void (*callback)(void *ctx, int result), void *ctx) { static const char mbtitle[] = "%s Security Alert"; static const char msg[] = @@ -793,20 +893,21 @@ void askalg(void *frontend, const char *algtype, const char *algname) message = dupprintf(msg, algtype, algname); title = dupprintf(mbtitle, appname); mbret = MessageBox(NULL, message, title, - MB_ICONWARNING | MB_YESNO); + MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); sfree(message); sfree(title); if (mbret == IDYES) - return; + return 1; else - cleanup_exit(0); + return 0; } /* * Ask whether to wipe a session log file before writing to it. * Returns 2 for wipe, 1 for append, 0 for cancel (don't log). */ -int askappend(void *frontend, Filename filename) +int askappend(void *frontend, Filename filename, + void (*callback)(void *ctx, int result), void *ctx) { static const char msgtemplate[] = "The session log file \"%.*s\" already exists.\n" @@ -823,7 +924,7 @@ int askappend(void *frontend, Filename filename) mbtitle = dupprintf("%s Log to File", appname); mbret = MessageBox(NULL, message, mbtitle, - MB_ICONQUESTION | MB_YESNOCANCEL); + MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON3); sfree(message); sfree(mbtitle);