Unify GET_32BIT()/PUT_32BIT() et al from numerous source files into misc.h.
[u/mdw/putty] / windows / winpgnt.c
index 1c34d71..b0cd08b 100644 (file)
@@ -8,6 +8,8 @@
 #include <assert.h>
 #include <tchar.h>
 
 #include <assert.h>
 #include <tchar.h>
 
+#define PUTTY_DO_GLOBALS
+
 #include "putty.h"
 #include "ssh.h"
 #include "misc.h"
 #include "putty.h"
 #include "ssh.h"
 #include "misc.h"
 
 extern char ver[];
 
 
 extern char ver[];
 
-static HINSTANCE instance;
-static HWND main_hwnd;
 static HWND keylist;
 static HWND aboutbox;
 static HMENU systray_menu, session_menu;
 static int already_running;
 static HWND keylist;
 static HWND aboutbox;
 static HMENU systray_menu, session_menu;
 static int already_running;
-static int requested_help;
 
 
-char *help_path;
 static char *putty_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
 #define IDM_PUTTY         0x0060
 #define IDM_SESSIONS_BASE 0x1000
 #define IDM_SESSIONS_MAX  0x2000
@@ -77,7 +78,7 @@ void modalfatalbox(char *fmt, ...)
     va_start(ap, fmt);
     buf = dupvprintf(fmt, ap);
     va_end(ap);
     va_start(ap, fmt);
     buf = dupvprintf(fmt, ap);
     va_end(ap);
-    MessageBox(main_hwnd, buf, "Pageant Fatal Error",
+    MessageBox(hwnd, buf, "Pageant Fatal Error",
               MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
     sfree(buf);
     exit(1);
               MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
     sfree(buf);
     exit(1);
@@ -139,14 +140,14 @@ static void *get_keylist2(int *length);
  */
 int random_byte(void)
 {
  */
 int random_byte(void)
 {
-    MessageBox(main_hwnd, "Internal Error", APPNAME, MB_OK | MB_ICONERROR);
+    MessageBox(hwnd, "Internal Error", APPNAME, MB_OK | MB_ICONERROR);
     exit(0);
     /* this line can't be reached but it placates MSVC's warnings :-) */
     return 0;
 }
 
 /*
     exit(0);
     /* this line can't be reached but it placates MSVC's warnings :-) */
     return 0;
 }
 
 /*
- * Blob structure for passing to the asymmetric SSH2 key compare
+ * Blob structure for passing to the asymmetric SSH-2 key compare
  * function, prototyped here.
  */
 struct blob {
  * function, prototyped here.
  */
 struct blob {
@@ -155,18 +156,6 @@ struct blob {
 };
 static int cmpkeys_ssh2_asymm(void *av, void *bv);
 
 };
 static int cmpkeys_ssh2_asymm(void *av, void *bv);
 
-#define GET_32BIT(cp) \
-    (((unsigned long)(unsigned char)(cp)[0] << 24) | \
-    ((unsigned long)(unsigned char)(cp)[1] << 16) | \
-    ((unsigned long)(unsigned char)(cp)[2] << 8) | \
-    ((unsigned long)(unsigned char)(cp)[3]))
-
-#define PUT_32BIT(cp, value) { \
-    (cp)[0] = (unsigned char)((value) >> 24); \
-    (cp)[1] = (unsigned char)((value) >> 16); \
-    (cp)[2] = (unsigned char)((value) >> 8); \
-    (cp)[3] = (unsigned char)(value); }
-
 #define PASSPHRASE_MAXLEN 512
 
 struct PassphraseProcStruct {
 #define PASSPHRASE_MAXLEN 512
 
 struct PassphraseProcStruct {
@@ -233,7 +222,7 @@ static int CALLBACK AboutProc(HWND hwnd, UINT msg,
            return 0;
          case 101:
            EnableWindow(hwnd, 0);
            return 0;
          case 101:
            EnableWindow(hwnd, 0);
-           DialogBox(instance, MAKEINTRESOURCE(214), hwnd, LicenceProc);
+           DialogBox(hinst, MAKEINTRESOURCE(214), hwnd, LicenceProc);
            EnableWindow(hwnd, 1);
            SetActiveWindow(hwnd);
            return 0;
            EnableWindow(hwnd, 1);
            SetActiveWindow(hwnd);
            return 0;
@@ -320,7 +309,7 @@ void old_keyfile_warning(void)
 {
     static const char mbtitle[] = "PuTTY Key File Warning";
     static const char message[] =
 {
     static const char mbtitle[] = "PuTTY Key File Warning";
     static const char message[] =
-       "You are loading an SSH 2 private key which has an\n"
+       "You are loading an SSH-2 private key which has an\n"
        "old version of the file format. This means your key\n"
        "file is not fully tamperproof. Future versions of\n"
        "PuTTY may stop supporting this private key format,\n"
        "old version of the file format. This means your key\n"
        "file is not fully tamperproof. Future versions of\n"
        "PuTTY may stop supporting this private key format,\n"
@@ -402,15 +391,18 @@ static void add_keyfile(Filename filename)
     int ret;
     int attempts;
     char *comment;
     int ret;
     int attempts;
     char *comment;
+    const char *error = NULL;
     struct PassphraseProcStruct pps;
     int type;
     int original_pass;
        
     type = key_type(&filename);
     if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
     struct PassphraseProcStruct pps;
     int type;
     int original_pass;
        
     type = key_type(&filename);
     if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
-       char msg[256];
-       sprintf(msg, "Couldn't load this key (%s)", key_type_to_str(type));
-       MessageBox(NULL, msg, APPNAME, MB_OK | MB_ICONERROR);
+       char *msg = dupprintf("Couldn't load this key (%s)",
+                             key_type_to_str(type));
+       message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
+                   HELPCTXID(errors_cantloadkey));
+       sfree(msg);
        return;
     }
 
        return;
     }
 
@@ -424,18 +416,22 @@ static void add_keyfile(Filename filename)
        int i, nkeys, bloblen, keylistlen;
 
        if (type == SSH_KEYTYPE_SSH1) {
        int i, nkeys, bloblen, keylistlen;
 
        if (type == SSH_KEYTYPE_SSH1) {
-           if (!rsakey_pubblob(&filename, &blob, &bloblen, NULL)) {
-               MessageBox(NULL, "Couldn't load private key.", APPNAME,
-                          MB_OK | MB_ICONERROR);
+           if (!rsakey_pubblob(&filename, &blob, &bloblen, &error)) {
+               char *msg = dupprintf("Couldn't load private key (%s)", error);
+               message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
+                           HELPCTXID(errors_cantloadkey));
+               sfree(msg);
                return;
            }
            keylist = get_keylist1(&keylistlen);
        } else {
            unsigned char *blob2;
                return;
            }
            keylist = get_keylist1(&keylistlen);
        } else {
            unsigned char *blob2;
-           blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen, NULL);
+           blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen, &error);
            if (!blob) {
            if (!blob) {
-               MessageBox(NULL, "Couldn't load private key.", APPNAME,
-                          MB_OK | MB_ICONERROR);
+               char *msg = dupprintf("Couldn't load private key (%s)", error);
+               message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
+                           HELPCTXID(errors_cantloadkey));
+               sfree(msg);
                return;
            }
            /* For our purposes we want the blob prefixed with its length */
                return;
            }
            /* For our purposes we want the blob prefixed with its length */
@@ -515,6 +511,7 @@ static void add_keyfile(Filename filename)
        sfree(blob);
     }
 
        sfree(blob);
     }
 
+    error = NULL;
     if (type == SSH_KEYTYPE_SSH1)
        needs_pass = rsakey_encrypted(&filename, &comment);
     else
     if (type == SSH_KEYTYPE_SSH1)
        needs_pass = rsakey_encrypted(&filename, &comment);
     else
@@ -534,8 +531,8 @@ static void add_keyfile(Filename filename)
            } else {
                int dlgret;
                original_pass = 1;
            } else {
                int dlgret;
                original_pass = 1;
-               dlgret = DialogBoxParam(instance, MAKEINTRESOURCE(210),
-                                       NULL, PassphraseProc, (LPARAM) & pps);
+               dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210),
+                                       NULL, PassphraseProc, (LPARAM) &pps);
                passphrase_box = NULL;
                if (!dlgret) {
                    if (comment)
                passphrase_box = NULL;
                if (!dlgret) {
                    if (comment)
@@ -548,9 +545,9 @@ static void add_keyfile(Filename filename)
        } else
            *passphrase = '\0';
        if (type == SSH_KEYTYPE_SSH1)
        } else
            *passphrase = '\0';
        if (type == SSH_KEYTYPE_SSH1)
-           ret = loadrsakey(&filename, rkey, passphrase, NULL);
+           ret = loadrsakey(&filename, rkey, passphrase, &error);
        else {
        else {
-           skey = ssh2_load_userkey(&filename, passphrase, NULL);
+           skey = ssh2_load_userkey(&filename, passphrase, &error);
            if (skey == SSH2_WRONG_PASSPHRASE)
                ret = -1;
            else if (!skey)
            if (skey == SSH2_WRONG_PASSPHRASE)
                ret = -1;
            else if (!skey)
@@ -570,8 +567,10 @@ static void add_keyfile(Filename filename)
     if (comment)
        sfree(comment);
     if (ret == 0) {
     if (comment)
        sfree(comment);
     if (ret == 0) {
-       MessageBox(NULL, "Couldn't load private key.", APPNAME,
-                  MB_OK | MB_ICONERROR);
+       char *msg = dupprintf("Couldn't load private key (%s)", error);
+       message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
+                   HELPCTXID(errors_cantloadkey));
+       sfree(msg);
        if (type == SSH_KEYTYPE_SSH1)
            sfree(rkey);
        return;
        if (type == SSH_KEYTYPE_SSH1)
            sfree(rkey);
        return;
@@ -681,7 +680,7 @@ static void add_keyfile(Filename filename)
 }
 
 /*
 }
 
 /*
- * Create an SSH1 key list in a malloc'ed buffer; return its
+ * Create an SSH-1 key list in a malloc'ed buffer; return its
  * length.
  */
 static void *make_keylist1(int *length)
  * length.
  */
 static void *make_keylist1(int *length)
@@ -725,7 +724,7 @@ static void *make_keylist1(int *length)
 }
 
 /*
 }
 
 /*
- * Create an SSH2 key list in a malloc'ed buffer; return its
+ * Create an SSH-2 key list in a malloc'ed buffer; return its
  * length.
  */
 static void *make_keylist2(int *length)
  * length.
  */
 static void *make_keylist2(int *length)
@@ -1235,7 +1234,7 @@ static void answer_msg(void *msg)
        break;
       case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
        /*
        break;
       case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
        /*
-        * Remove all SSH1 keys. Always returns success.
+        * Remove all SSH-1 keys. Always returns success.
         */
        {
            struct RSAKey *rkey;
         */
        {
            struct RSAKey *rkey;
@@ -1253,7 +1252,7 @@ static void answer_msg(void *msg)
        break;
       case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
        /*
        break;
       case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
        /*
-        * Remove all SSH2 keys. Always returns success.
+        * Remove all SSH-2 keys. Always returns success.
         */
        {
            struct ssh2_userkey *skey;
         */
        {
            struct ssh2_userkey *skey;
@@ -1321,7 +1320,7 @@ static int cmpkeys_rsa(void *av, void *bv)
 }
 
 /*
 }
 
 /*
- * Key comparison function for the 2-3-4 tree of SSH2 keys.
+ * Key comparison function for the 2-3-4 tree of SSH-2 keys.
  */
 static int cmpkeys_ssh2(void *av, void *bv)
 {
  */
 static int cmpkeys_ssh2(void *av, void *bv)
 {
@@ -1361,7 +1360,7 @@ static int cmpkeys_ssh2(void *av, void *bv)
 
 /*
  * Key comparison function for looking up a blob in the 2-3-4 tree
 
 /*
  * Key comparison function for looking up a blob in the 2-3-4 tree
- * of SSH2 keys.
+ * of SSH-2 keys.
  */
 static int cmpkeys_ssh2_asymm(void *av, void *bv)
 {
  */
 static int cmpkeys_ssh2_asymm(void *av, void *bv)
 {
@@ -1405,30 +1404,21 @@ static int cmpkeys_ssh2_asymm(void *av, void *bv)
 static void prompt_add_keyfile(void)
 {
     OPENFILENAME of;
 static void prompt_add_keyfile(void)
 {
     OPENFILENAME of;
-    char filename[FILENAME_MAX];
     char *filelist = snewn(8192, char);
     char *filelist = snewn(8192, char);
-    char *filewalker;
-    int n, dirlen;
        
        
+    if (!keypath) keypath = filereq_new();
     memset(&of, 0, sizeof(of));
     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.hwndOwner = hwnd;
+    of.lpstrFilter = FILTER_KEY_FILES;
     of.lpstrCustomFilter = NULL;
     of.nFilterIndex = 1;
     of.lpstrFile = filelist;
     *filelist = '\0';
     of.lpstrCustomFilter = NULL;
     of.nFilterIndex = 1;
     of.lpstrFile = filelist;
     *filelist = '\0';
-    of.nMaxFile = FILENAME_MAX;
+    of.nMaxFile = 8192;
     of.lpstrFileTitle = NULL;
     of.lpstrFileTitle = NULL;
-    of.lpstrInitialDir = NULL;
     of.lpstrTitle = "Select Private Key File";
     of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
     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));
        if(strlen(filelist) > of.nFileOffset)
            /* Only one filename returned? */
            add_keyfile(filename_from_str(filelist));
@@ -1438,28 +1428,13 @@ static void prompt_add_keyfile(void)
             * rest the filenames. terminated with an
             * empty string.
             */
             * 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));
                add_keyfile(filename_from_str(filename));
+               sfree(filename);
+               filewalker += strlen(filewalker) + 1;
            }
        }
 
            }
        }
 
@@ -1597,7 +1572,7 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
             if (HIWORD(wParam) == BN_CLICKED ||
                 HIWORD(wParam) == BN_DOUBLECLICKED) {
                 if (help_path) {
             if (HIWORD(wParam) == BN_CLICKED ||
                 HIWORD(wParam) == BN_DOUBLECLICKED) {
                 if (help_path) {
-                    WinHelp(main_hwnd, help_path, HELP_COMMAND,
+                    WinHelp(hwnd, help_path, HELP_COMMAND,
                             (DWORD)"JI(`',`pageant.general')");
                     requested_help = TRUE;
                 }
                             (DWORD)"JI(`',`pageant.general')");
                     requested_help = TRUE;
                 }
@@ -1608,14 +1583,16 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
       case WM_HELP:
         if (help_path) {
             int id = ((LPHELPINFO)lParam)->iCtrlId;
       case WM_HELP:
         if (help_path) {
             int id = ((LPHELPINFO)lParam)->iCtrlId;
-            char *cmd = NULL;
+            char *topic = NULL;
             switch (id) {
             switch (id) {
-              case 100: cmd = "JI(`',`pageant.keylist')"; break;
-              case 101: cmd = "JI(`',`pageant.addkey')"; break;
-              case 102: cmd = "JI(`',`pageant.remkey')"; break;
+              case 100: topic = "pageant.keylist"; break;
+              case 101: topic = "pageant.addkey"; break;
+              case 102: topic = "pageant.remkey"; break;
             }
             }
-            if (cmd) {
-                WinHelp(main_hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
+            if (topic) {
+               char *cmd = dupprintf("JI(`',`%s')", topic);
+                WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
+               sfree(cmd);
                 requested_help = TRUE;
             } else {
                 MessageBeep(0);
                 requested_help = TRUE;
             } else {
                 MessageBeep(0);
@@ -1647,7 +1624,7 @@ static BOOL AddTrayIcon(HWND hwnd)
     tnid.uID = 1;             /* unique within this systray use */
     tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
     tnid.uCallbackMessage = WM_SYSTRAY;
     tnid.uID = 1;             /* unique within this systray use */
     tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
     tnid.uCallbackMessage = WM_SYSTRAY;
-    tnid.hIcon = hicon = LoadIcon(instance, MAKEINTRESOURCE(201));
+    tnid.hIcon = hicon = LoadIcon(hinst, MAKEINTRESOURCE(201));
     strcpy(tnid.szTip, "Pageant (PuTTY authentication agent)");
 
     res = Shell_NotifyIcon(NIM_ADD, &tnid);
     strcpy(tnid.szTip, "Pageant (PuTTY authentication agent)");
 
     res = Shell_NotifyIcon(NIM_ADD, &tnid);
@@ -1737,8 +1714,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            GetCursorPos(&cursorpos);
            PostMessage(hwnd, WM_SYSTRAY2, cursorpos.x, cursorpos.y);
        } else if (lParam == WM_LBUTTONDBLCLK) {
            GetCursorPos(&cursorpos);
            PostMessage(hwnd, WM_SYSTRAY2, cursorpos.x, cursorpos.y);
        } else if (lParam == WM_LBUTTONDBLCLK) {
-           /* Equivalent to IDM_VIEWKEYS. */
-           PostMessage(hwnd, WM_COMMAND, IDM_VIEWKEYS, 0);
+           /* Run the default menu item. */
+           UINT menuitem = GetMenuDefaultItem(systray_menu, FALSE, 0);
+           if (menuitem != -1)
+               PostMessage(hwnd, WM_COMMAND, menuitem, 0);
        }
        break;
       case WM_SYSTRAY2:
        }
        break;
       case WM_SYSTRAY2:
@@ -1770,7 +1749,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            break;
          case IDM_VIEWKEYS:
            if (!keylist) {
            break;
          case IDM_VIEWKEYS:
            if (!keylist) {
-               keylist = CreateDialog(instance, MAKEINTRESOURCE(211),
+               keylist = CreateDialog(hinst, MAKEINTRESOURCE(211),
                                       NULL, KeyListProc);
                ShowWindow(keylist, SW_SHOWNORMAL);
            }
                                       NULL, KeyListProc);
                ShowWindow(keylist, SW_SHOWNORMAL);
            }
@@ -1795,7 +1774,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            break;
          case IDM_ABOUT:
            if (!aboutbox) {
            break;
          case IDM_ABOUT:
            if (!aboutbox) {
-               aboutbox = CreateDialog(instance, MAKEINTRESOURCE(213),
+               aboutbox = CreateDialog(hinst, MAKEINTRESOURCE(213),
                                        NULL, AboutProc);
                ShowWindow(aboutbox, SW_SHOWNORMAL);
                /* 
                                        NULL, AboutProc);
                ShowWindow(aboutbox, SW_SHOWNORMAL);
                /* 
@@ -1809,7 +1788,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            break;
          case IDM_HELP:
             if (help_path) {
            break;
          case IDM_HELP:
             if (help_path) {
-                WinHelp(main_hwnd, help_path, HELP_COMMAND,
+                WinHelp(hwnd, help_path, HELP_COMMAND,
                         (DWORD)"JI(`',`pageant.general')");
                 requested_help = TRUE;
             }
                         (DWORD)"JI(`',`pageant.general')");
                 requested_help = TRUE;
             }
@@ -1840,7 +1819,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        break;
       case WM_DESTROY:
         if (requested_help) {
        break;
       case WM_DESTROY:
         if (requested_help) {
-            WinHelp(main_hwnd, help_path, HELP_QUIT, 0);
+            WinHelp(hwnd, help_path, HELP_QUIT, 0);
             requested_help = FALSE;
         }
        PostQuitMessage(0);
             requested_help = FALSE;
         }
        PostQuitMessage(0);
@@ -1982,6 +1961,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     int argc, i;
     char **argv, **argstart;
 
     int argc, i;
     char **argv, **argstart;
 
+    hinst = inst;
+    hwnd = NULL;
+
     /*
      * Determine whether we're an NT system (should have security
      * APIs) or a non-NT system (don't do security).
     /*
      * Determine whether we're an NT system (should have security
      * APIs) or a non-NT system (don't do security).
@@ -2020,8 +2002,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     } else
        advapi = NULL;
 
     } else
        advapi = NULL;
 
-    instance = inst;
-
     /*
      * See if we can find our Help file.
      */
     /*
      * See if we can find our Help file.
      */
@@ -2034,7 +2014,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
         if (p && p >= r) r = p+1;
         q = strrchr(b, ':');
         if (q && q >= r) r = q+1;
         if (p && p >= r) r = p+1;
         q = strrchr(b, ':');
         if (q && q >= r) r = q+1;
-        strcpy(r, "putty.hlp");
+        strcpy(r, PUTTY_HELP_FILE);
         if ( (fp = fopen(b, "r")) != NULL) {
             help_path = dupstr(b);
             fclose(fp);
         if ( (fp = fopen(b, "r")) != NULL) {
             help_path = dupstr(b);
             fclose(fp);
@@ -2066,64 +2046,14 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     /*
      * Find out if Pageant is already running.
      */
     /*
      * Find out if Pageant is already running.
      */
-    already_running = FALSE;
-    if (agent_exists())
-       already_running = TRUE;
-    else {
-
-       if (!prev) {
-           wndclass.style = 0;
-           wndclass.lpfnWndProc = WndProc;
-           wndclass.cbClsExtra = 0;
-           wndclass.cbWndExtra = 0;
-           wndclass.hInstance = inst;
-           wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
-           wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM);
-           wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
-           wndclass.lpszMenuName = NULL;
-           wndclass.lpszClassName = APPNAME;
-
-           RegisterClass(&wndclass);
-       }
-
-       main_hwnd = keylist = NULL;
-
-       main_hwnd = CreateWindow(APPNAME, APPNAME,
-                                 WS_OVERLAPPEDWINDOW | WS_VSCROLL,
-                                 CW_USEDEFAULT, CW_USEDEFAULT,
-                                 100, 100, NULL, NULL, inst, NULL);
+    already_running = agent_exists();
 
 
-       /* Set up a system tray icon */
-       AddTrayIcon(main_hwnd);
-
-        /* Accelerators used: nsvkxa */
-        systray_menu = CreatePopupMenu();
-       if (putty_path) {
-           session_menu = CreateMenu();
-           AppendMenu(systray_menu, MF_ENABLED, IDM_PUTTY, "&New Session");
-           AppendMenu(systray_menu, MF_POPUP | MF_ENABLED,
-                      (UINT) session_menu, "&Saved Sessions");
-           AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
-       }
-        AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS,
-               "&View Keys");
-        AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key");
-       AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
-        if (help_path)
-            AppendMenu(systray_menu, MF_ENABLED, IDM_HELP, "&Help");
-        AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About");
-       AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
-        AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit");
-       initial_menuitems_count = GetMenuItemCount(session_menu);
-
-       ShowWindow(main_hwnd, SW_HIDE);
-
-       /*
-        * Initialise storage for RSA keys.
-        */
+    /*
+     * Initialise storage for RSA keys.
+     */
+    if (!already_running) {
        rsakeys = newtree234(cmpkeys_rsa);
        ssh2keys = newtree234(cmpkeys_ssh2);
        rsakeys = newtree234(cmpkeys_rsa);
        ssh2keys = newtree234(cmpkeys_ssh2);
-
     }
 
     /*
     }
 
     /*
@@ -2136,7 +2066,12 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
      */
     split_into_argv(cmdline, &argc, &argv, &argstart);
     for (i = 0; i < argc; i++) {
      */
     split_into_argv(cmdline, &argc, &argv, &argstart);
     for (i = 0; i < argc; i++) {
-       if (!strcmp(argv[i], "-c")) {
+       if (!strcmp(argv[i], "-pgpfp")) {
+           pgp_fingerprints();
+           if (advapi)
+               FreeLibrary(advapi);
+           return 1;
+       } else if (!strcmp(argv[i], "-c")) {
            /*
             * If we see `-c', then the rest of the
             * command line should be treated as a
            /*
             * If we see `-c', then the rest of the
             * command line should be treated as a
@@ -2187,6 +2122,56 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        return 0;
     }
 
        return 0;
     }
 
+    if (!prev) {
+       wndclass.style = 0;
+       wndclass.lpfnWndProc = WndProc;
+       wndclass.cbClsExtra = 0;
+       wndclass.cbWndExtra = 0;
+       wndclass.hInstance = inst;
+       wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
+       wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM);
+       wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
+       wndclass.lpszMenuName = NULL;
+       wndclass.lpszClassName = APPNAME;
+
+       RegisterClass(&wndclass);
+    }
+
+    keylist = NULL;
+
+    hwnd = CreateWindow(APPNAME, APPNAME,
+                       WS_OVERLAPPEDWINDOW | WS_VSCROLL,
+                       CW_USEDEFAULT, CW_USEDEFAULT,
+                       100, 100, NULL, NULL, inst, NULL);
+
+    /* Set up a system tray icon */
+    AddTrayIcon(hwnd);
+
+    /* Accelerators used: nsvkxa */
+    systray_menu = CreatePopupMenu();
+    if (putty_path) {
+       session_menu = CreateMenu();
+       AppendMenu(systray_menu, MF_ENABLED, IDM_PUTTY, "&New Session");
+       AppendMenu(systray_menu, MF_POPUP | MF_ENABLED,
+                  (UINT) session_menu, "&Saved Sessions");
+       AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
+    }
+    AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS,
+          "&View Keys");
+    AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key");
+    AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
+    if (help_path)
+       AppendMenu(systray_menu, MF_ENABLED, IDM_HELP, "&Help");
+    AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About");
+    AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
+    AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit");
+    initial_menuitems_count = GetMenuItemCount(session_menu);
+
+    /* Set the default menu item. */
+    SetMenuDefaultItem(systray_menu, IDM_VIEWKEYS, FALSE);
+
+    ShowWindow(hwnd, SW_HIDE);
+
     /*
      * Main message loop.
      */
     /*
      * Main message loop.
      */
@@ -2203,7 +2188,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        NOTIFYICONDATA tnid;
 
        tnid.cbSize = sizeof(NOTIFYICONDATA);
        NOTIFYICONDATA tnid;
 
        tnid.cbSize = sizeof(NOTIFYICONDATA);
-       tnid.hWnd = main_hwnd;
+       tnid.hWnd = hwnd;
        tnid.uID = 1;
 
        Shell_NotifyIcon(NIM_DELETE, &tnid);
        tnid.uID = 1;
 
        Shell_NotifyIcon(NIM_DELETE, &tnid);
@@ -2211,6 +2196,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        DestroyMenu(systray_menu);
     }
 
        DestroyMenu(systray_menu);
     }
 
+    if (keypath) filereq_free(keypath);
+
     if (advapi)
        FreeLibrary(advapi);
     return msg.wParam;
     if (advapi)
        FreeLibrary(advapi);
     return msg.wParam;