]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Fix for `pageant-dirhandle': a new wrapper functions `request_file()' maintains
authorJacob Nevins <jacobn@chiark.greenend.org.uk>
Mon, 28 Feb 2005 02:40:43 +0000 (02:40 +0000)
committerJacob Nevins <jacobn@chiark.greenend.org.uk>
Mon, 28 Feb 2005 02:40:43 +0000 (02:40 +0000)
a separate CWD for the file requester, so that when the Open File box is not
open Pageant should stay where it was started.
(Also some other minor cleanups in this area of Pageant.)

[originally from svn r5413]
[this svn revision also touched putty-wishlist]

windows/winpgnt.c
windows/winstuff.h
windows/winutils.c

index 49cd311fb9cfb100d9774c0743ff00fb785c69ab..0786f7a6df12de047805d92b683f4ca8ca89c673 100644 (file)
@@ -59,6 +59,9 @@ static int requested_help;
 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
@@ -1410,30 +1413,21 @@ static int cmpkeys_ssh2_asymm(void *av, void *bv)
 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));
@@ -1443,28 +1437,13 @@ static void prompt_add_keyfile(void)
             * 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;
            }
        }
 
@@ -2223,6 +2202,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        DestroyMenu(systray_menu);
     }
 
+    if (keypath) filereq_free(keypath);
+
     if (advapi)
        FreeLibrary(advapi);
     return msg.wParam;
index a6b22a8da291fe22298ac127800829423980799a..f6fae661119c29b8795807a4210073d0c695bf7d 100644 (file)
@@ -173,6 +173,10 @@ struct ctlpos {
 /*
  * 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 ***);
 
 /*
index b292124569ad4194af834374ae7fb277636937bb..2e91d8bb3a130738e678cb817cee4833ab982593 100644 (file)
@@ -5,16 +5,89 @@
 #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