char *help_path;
static char *putty_path;
+/* CWD for "add key" file requester. */
+static filereq *keypath = NULL;
+
#define IDM_PUTTY 0x0060
#define IDM_SESSIONS_BASE 0x1000
#define IDM_SESSIONS_MAX 0x2000
static void prompt_add_keyfile(void)
{
OPENFILENAME of;
- char filename[FILENAME_MAX];
char *filelist = snewn(8192, char);
- char *filewalker;
- int n, dirlen;
+ if (!keypath) keypath = filereq_new();
memset(&of, 0, sizeof(of));
-#ifdef OPENFILENAME_SIZE_VERSION_400
- of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
- of.lStructSize = sizeof(of);
-#endif
of.hwndOwner = main_hwnd;
- of.lpstrFilter = "PuTTY Private Key Files (*.ppk)\0*.ppk\0"
- "All Files (*.*)\0*\0\0\0";
+ of.lpstrFilter = FILTER_KEY_FILES;
of.lpstrCustomFilter = NULL;
of.nFilterIndex = 1;
of.lpstrFile = filelist;
*filelist = '\0';
- of.nMaxFile = FILENAME_MAX;
+ of.nMaxFile = 8192;
of.lpstrFileTitle = NULL;
- of.lpstrInitialDir = NULL;
of.lpstrTitle = "Select Private Key File";
of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
- if (GetOpenFileName(&of)) {
+ if (request_file(keypath, &of, TRUE, FALSE)) {
if(strlen(filelist) > of.nFileOffset)
/* Only one filename returned? */
add_keyfile(filename_from_str(filelist));
* rest the filenames. terminated with an
* empty string.
*/
- filewalker = filelist;
- dirlen = strlen(filewalker);
- if(dirlen > FILENAME_MAX - 8) return;
- memcpy(filename, filewalker, dirlen);
-
- filewalker += dirlen + 1;
- filename[dirlen++] = '\\';
-
- /* then go over names one by one */
- for(;;) {
- n = strlen(filewalker) + 1;
- /* end of the list */
- if(n == 1)
- break;
- /* too big, shouldn't happen */
- if(n + dirlen > FILENAME_MAX)
- break;
-
- memcpy(filename + dirlen, filewalker, n);
- filewalker += n;
-
+ char *dir = filelist;
+ char *filewalker = filelist + strlen(dir) + 1;
+ while (*filewalker != '\0') {
+ char *filename = dupcat(dir, "\\", filewalker, NULL);
add_keyfile(filename_from_str(filename));
+ sfree(filename);
+ filewalker += strlen(filewalker) + 1;
}
}
DestroyMenu(systray_menu);
}
+ if (keypath) filereq_free(keypath);
+
if (advapi)
FreeLibrary(advapi);
return msg.wParam;
/*
* Exports from winutils.c.
*/
+typedef struct filereq_tag filereq; /* cwd for file requester */
+BOOL request_file(filereq *state, OPENFILENAME *of, int preserve, int save);
+filereq *filereq_new(void);
+void filereq_free(filereq *state);
void split_into_argv(char *, int *, char ***, char ***);
/*
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+#include <limits.h>
+#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);
+}
+
+/*
* 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,