X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/6da411554bfe4c2a8ddfbb0616b0030ea5e813f5..2833957974b5c33f4470ef8772efd6ba746d205b:/windows/winutils.c diff --git a/windows/winutils.c b/windows/winutils.c index b2921245..450c030e 100644 --- a/windows/winutils.c +++ b/windows/winutils.c @@ -5,17 +5,142 @@ #include #include #include +#include +#include "winstuff.h" #include "misc.h" #ifdef TESTMODE -/* Definitions to allow this module to be compiled standalone for testing. */ +/* Definitions to allow this module to be compiled standalone for testing + * split_into_argv(). */ #define smalloc malloc #define srealloc realloc #define sfree free #endif /* + * GetOpenFileName/GetSaveFileName tend to muck around with the process' + * working directory on at least some versions of Windows. + * Here's a wrapper that gives more control over this, and hides a little + * bit of other grottiness. + */ + +struct filereq_tag { + TCHAR cwd[PATH_MAX]; +}; + +/* + * `of' is expected to be initialised with most interesting fields, but + * this function does some administrivia. (assume `of' was memset to 0) + * save==1 -> GetSaveFileName; save==0 -> GetOpenFileName + * `state' is optional. + */ +BOOL request_file(filereq *state, OPENFILENAME *of, int preserve, int save) +{ + TCHAR cwd[PATH_MAX]; /* process CWD */ + BOOL ret; + + /* Get process CWD */ + if (preserve) { + DWORD r = GetCurrentDirectory(lenof(cwd), cwd); + if (r == 0 || r >= lenof(cwd)) + /* Didn't work, oh well. Stop trying to be clever. */ + preserve = 0; + } + + /* Open the file requester, maybe setting lpstrInitialDir */ + { +#ifdef OPENFILENAME_SIZE_VERSION_400 + of->lStructSize = OPENFILENAME_SIZE_VERSION_400; +#else + of->lStructSize = sizeof(*of); +#endif + of->lpstrInitialDir = (state && state->cwd[0]) ? state->cwd : NULL; + /* Actually put up the requester. */ + ret = save ? GetSaveFileName(of) : GetOpenFileName(of); + } + + /* Get CWD left by requester */ + if (state) { + DWORD r = GetCurrentDirectory(lenof(state->cwd), state->cwd); + if (r == 0 || r >= lenof(state->cwd)) + /* Didn't work, oh well. */ + state->cwd[0] = '\0'; + } + + /* Restore process CWD */ + if (preserve) + /* If it fails, there's not much we can do. */ + (void) SetCurrentDirectory(cwd); + + return ret; +} + +filereq *filereq_new(void) +{ + filereq *ret = snew(filereq); + ret->cwd[0] = '\0'; + return ret; +} + +void filereq_free(filereq *state) +{ + sfree(state); +} + +/* + * Message box with optional context help. + */ + +/* Callback function to launch context help. */ +static VOID CALLBACK message_box_help_callback(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); + CHECK_CTX(errors_cantloadkey); + CHECK_CTX(option_cleanup); +#undef CHECK_CTX + if (context) { + /* We avoid using malloc, in case we're in a situation where + * it would be awkward to do so. */ + char cmd[WINHELP_CTX_MAXLEN+10]; + sprintf(cmd, "JI(`',`%.*s')", WINHELP_CTX_MAXLEN, context); + WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd); + requested_help = TRUE; + } + } +} + +int message_box(LPCTSTR text, LPCTSTR caption, DWORD style, DWORD helpctxid) +{ + MSGBOXPARAMS mbox; + + /* + * We use MessageBoxIndirect() because it allows us to specify a + * callback function for the Help button. + */ + mbox.cbSize = sizeof(mbox); + /* Assumes the globals `hinst' and `hwnd' have sensible values. */ + mbox.hInstance = hinst; + mbox.hwndOwner = hwnd; + mbox.lpfnMsgBoxCallback = &message_box_help_callback; + mbox.dwLanguageId = LANG_NEUTRAL; + mbox.lpszText = text; + mbox.lpszCaption = caption; + mbox.dwContextHelpId = helpctxid; + mbox.dwStyle = style; + if (helpctxid != 0 && help_path) mbox.dwStyle |= MB_HELP; + return MessageBoxIndirect(&mbox); +} + +/* * Split a complete command line into argc/argv, attempting to do * it exactly the same way Windows itself would do it (so that * console utilities, which receive argc and argv from Windows,