]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winpgnt.c
Turn off Windows process ACL restriction by default.
[PuTTY.git] / windows / winpgnt.c
index 2aa9886081da7d0727b5639d17673a65f6abe41f..fe0822e4889f4f10706cbe7b63cae9d53e783252 100644 (file)
@@ -16,6 +16,7 @@
 #include "tree234.h"
 #include "winsecur.h"
 #include "pageant.h"
+#include "licence.h"
 
 #include <shellapi.h>
 
@@ -48,7 +49,7 @@
 
 #define APPNAME "Pageant"
 
-extern char ver[];
+extern const char ver[];
 
 static HWND keylist;
 static HWND aboutbox;
@@ -70,7 +71,7 @@ static int initial_menuitems_count;
 /*
  * Print a modal (Really Bad) message box and perform a fatal exit.
  */
-void modalfatalbox(char *fmt, ...)
+void modalfatalbox(const char *fmt, ...)
 {
     va_list ap;
     char *buf;
@@ -112,41 +113,20 @@ static void unmungestr(char *in, char *out, int outlen)
 
 static int has_security;
 
-/*
- * Forward references
- */
-static void *get_keylist1(int *length);
-static void *get_keylist2(int *length);
-
 struct PassphraseProcStruct {
     char **passphrase;
     char *comment;
 };
 
-static tree234 *passphrases = NULL;
-
-/* 
- * After processing a list of filenames, we want to forget the
- * passphrases.
- */
-static void forget_passphrases(void)
-{
-    while (count234(passphrases) > 0) {
-       char *pp = index234(passphrases, 0);
-       smemclr(pp, strlen(pp));
-       delpos234(passphrases, 0);
-       free(pp);
-    }
-}
-
 /*
  * Dialog-box function for the Licence box.
  */
-static int CALLBACK LicenceProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK LicenceProc(HWND hwnd, UINT msg,
                                WPARAM wParam, LPARAM lParam)
 {
     switch (msg) {
       case WM_INITDIALOG:
+        SetDlgItemText(hwnd, 1000, LICENCE_TEXT("\r\n\r\n"));
        return 1;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
@@ -166,12 +146,21 @@ static int CALLBACK LicenceProc(HWND hwnd, UINT msg,
 /*
  * Dialog-box function for the About box.
  */
-static int CALLBACK AboutProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
                              WPARAM wParam, LPARAM lParam)
 {
     switch (msg) {
       case WM_INITDIALOG:
-       SetDlgItemText(hwnd, 100, ver);
+        {
+            char *buildinfo_text = buildinfo("\r\n");
+            char *text = dupprintf
+                ("Pageant\r\n\r\n%s\r\n\r\n%s\r\n\r\n%s",
+                 ver, buildinfo_text,
+                 "\251 " SHORT_COPYRIGHT_DETAILS ". All rights reserved.");
+            sfree(buildinfo_text);
+            SetDlgItemText(hwnd, 1000, text);
+            sfree(text);
+        }
        return 1;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
@@ -201,7 +190,7 @@ static HWND passphrase_box;
 /*
  * Dialog-box function for the passphrase box.
  */
-static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK PassphraseProc(HWND hwnd, UINT msg,
                                   WPARAM wParam, LPARAM lParam)
 {
     static char **passphrase = NULL;
@@ -313,24 +302,64 @@ void keylist_update(void)
        }
        for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) {
            char *listentry, *p;
-           int pos, fp_len;
-           /*
-            * Replace spaces with tabs in the fingerprint prefix, for
-            * nice alignment in the list box, until we encounter a :
-            * meaning we're into the fingerprint proper.
-            */
-           p = skey->alg->fingerprint(skey->data);
+           int pos;
+
+            /*
+             * For nice alignment in the list box, we would ideally
+             * want every entry to align to the tab stop settings, and
+             * have a column for algorithm name, one for bit count,
+             * one for hex fingerprint, and one for key comment.
+             *
+             * Unfortunately, some of the algorithm names are so long
+             * that they overflow into the bit-count field.
+             * Fortunately, at the moment, those are _precisely_ the
+             * algorithm names that don't need a bit count displayed
+             * anyway (because for NIST-style ECDSA the bit count is
+             * mentioned in the algorithm name, and for ssh-ed25519
+             * there is only one possible value anyway). So we fudge
+             * this by simply omitting the bit count field in that
+             * situation.
+             *
+             * This is fragile not only in the face of further key
+             * types that don't follow this pattern, but also in the
+             * face of font metrics changes - the Windows semantics
+             * for list box tab stops is that \t aligns to the next
+             * one you haven't already exceeded, so I have to guess
+             * when the key type will overflow past the bit-count tab
+             * stop and leave out a tab character. Urgh.
+             */
+
+           p = ssh2_fingerprint(skey->alg, skey->data);
             listentry = dupprintf("%s\t%s", p, skey->comment);
-            fp_len = strlen(listentry);
             sfree(p);
 
             pos = 0;
             while (1) {
                 pos += strcspn(listentry + pos, " :");
-                if (listentry[pos] == ':')
+                if (listentry[pos] == ':' || !listentry[pos])
                     break;
                 listentry[pos++] = '\t';
             }
+            if (skey->alg != &ssh_dss && skey->alg != &ssh_rsa) {
+                /*
+                 * Remove the bit-count field, which is between the
+                 * first and second \t.
+                 */
+                int outpos;
+                pos = 0;
+                while (listentry[pos] && listentry[pos] != '\t')
+                    pos++;
+                outpos = pos;
+                pos++;
+                while (listentry[pos] && listentry[pos] != '\t')
+                    pos++;
+                while (1) {
+                    if ((listentry[outpos] = listentry[pos]) == '\0')
+                        break;
+                    outpos++;
+                    pos++;
+                }
+            }
 
            SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0,
                               (LPARAM) listentry);
@@ -340,397 +369,6 @@ void keylist_update(void)
     }
 }
 
-/*
- * This function loads a key from a file and adds it.
- */
-static void add_keyfile(Filename *filename)
-{
-    char *passphrase;
-    struct RSAKey *rkey = NULL;
-    struct ssh2_userkey *skey = NULL;
-    int needs_pass;
-    int ret;
-    int attempts;
-    char *comment;
-    const char *error = NULL;
-    int type;
-    int original_pass;
-       
-    type = key_type(filename);
-    if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
-       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;
-    }
-
-    /*
-     * See if the key is already loaded (in the primary Pageant,
-     * which may or may not be us).
-     */
-    {
-       void *blob;
-       unsigned char *keylist, *p;
-       int i, nkeys, bloblen, keylistlen;
-
-       if (type == SSH_KEYTYPE_SSH1) {
-           if (!rsakey_pubblob(filename, &blob, &bloblen, NULL, &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;
-           blob = ssh2_userkey_loadpub(filename, NULL, &bloblen,
-                                       NULL, &error);
-           if (!blob) {
-               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 */
-           blob2 = snewn(bloblen+4, unsigned char);
-           PUT_32BIT(blob2, bloblen);
-           memcpy(blob2 + 4, blob, bloblen);
-           sfree(blob);
-           blob = blob2;
-
-           keylist = get_keylist2(&keylistlen);
-       }
-       if (keylist) {
-           if (keylistlen < 4) {
-               MessageBox(NULL, "Received broken key list?!", APPNAME,
-                          MB_OK | MB_ICONERROR);
-               return;
-           }
-           nkeys = toint(GET_32BIT(keylist));
-           if (nkeys < 0) {
-               MessageBox(NULL, "Received broken key list?!", APPNAME,
-                          MB_OK | MB_ICONERROR);
-               return;
-           }
-           p = keylist + 4;
-           keylistlen -= 4;
-
-           for (i = 0; i < nkeys; i++) {
-               if (!memcmp(blob, p, bloblen)) {
-                   /* Key is already present; we can now leave. */
-                   sfree(keylist);
-                   sfree(blob);
-                   return;
-               }
-               /* Now skip over public blob */
-               if (type == SSH_KEYTYPE_SSH1) {
-                   int n = rsa_public_blob_len(p, keylistlen);
-                   if (n < 0) {
-                       MessageBox(NULL, "Received broken key list?!", APPNAME,
-                                  MB_OK | MB_ICONERROR);
-                       return;
-                   }
-                   p += n;
-                   keylistlen -= n;
-               } else {
-                   int n;
-                   if (keylistlen < 4) {
-                       MessageBox(NULL, "Received broken key list?!", APPNAME,
-                                  MB_OK | MB_ICONERROR);
-                       return;
-                   }
-                   n = toint(4 + GET_32BIT(p));
-                   if (n < 0 || keylistlen < n) {
-                       MessageBox(NULL, "Received broken key list?!", APPNAME,
-                                  MB_OK | MB_ICONERROR);
-                       return;
-                   }
-                   p += n;
-                   keylistlen -= n;
-               }
-               /* Now skip over comment field */
-               {
-                   int n;
-                   if (keylistlen < 4) {
-                       MessageBox(NULL, "Received broken key list?!", APPNAME,
-                                  MB_OK | MB_ICONERROR);
-                       return;
-                   }
-                   n = toint(4 + GET_32BIT(p));
-                   if (n < 0 || keylistlen < n) {
-                       MessageBox(NULL, "Received broken key list?!", APPNAME,
-                                  MB_OK | MB_ICONERROR);
-                       return;
-                   }
-                   p += n;
-                   keylistlen -= n;
-               }
-           }
-
-           sfree(keylist);
-       }
-
-       sfree(blob);
-    }
-
-    error = NULL;
-    if (type == SSH_KEYTYPE_SSH1)
-       needs_pass = rsakey_encrypted(filename, &comment);
-    else
-       needs_pass = ssh2_userkey_encrypted(filename, &comment);
-    attempts = 0;
-    if (type == SSH_KEYTYPE_SSH1)
-       rkey = snew(struct RSAKey);
-    passphrase = NULL;
-    original_pass = 0;
-    do {
-        burnstr(passphrase);
-        passphrase = NULL;
-
-       if (needs_pass) {
-           /* try all the remembered passphrases first */
-           char *pp = index234(passphrases, attempts);
-           if(pp) {
-               passphrase = dupstr(pp);
-           } else {
-               int dlgret;
-                struct PassphraseProcStruct pps;
-
-                pps.passphrase = &passphrase;
-                pps.comment = comment;
-
-               original_pass = 1;
-               dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210),
-                                       NULL, PassphraseProc, (LPARAM) &pps);
-               passphrase_box = NULL;
-               if (!dlgret) {
-                   if (comment)
-                       sfree(comment);
-                   if (type == SSH_KEYTYPE_SSH1)
-                       sfree(rkey);
-                   return;                    /* operation cancelled */
-               }
-
-                assert(passphrase != NULL);
-           }
-       } else
-           passphrase = dupstr("");
-
-       if (type == SSH_KEYTYPE_SSH1)
-           ret = loadrsakey(filename, rkey, passphrase, &error);
-       else {
-           skey = ssh2_load_userkey(filename, passphrase, &error);
-           if (skey == SSH2_WRONG_PASSPHRASE)
-               ret = -1;
-           else if (!skey)
-               ret = 0;
-           else
-               ret = 1;
-       }
-       attempts++;
-    } while (ret == -1);
-
-    if(original_pass && ret) {
-        /* If they typed in an ok passphrase, remember it */
-       addpos234(passphrases, passphrase, 0);
-    } else {
-        /* Otherwise, destroy it */
-        burnstr(passphrase);
-    }
-    passphrase = NULL;
-
-    if (comment)
-       sfree(comment);
-    if (ret == 0) {
-       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) {
-       if (already_running) {
-           unsigned char *request, *response;
-           void *vresponse;
-           int reqlen, clen, resplen, ret;
-
-           clen = strlen(rkey->comment);
-
-           reqlen = 4 + 1 +           /* length, message type */
-               4 +                    /* bit count */
-               ssh1_bignum_length(rkey->modulus) +
-               ssh1_bignum_length(rkey->exponent) +
-               ssh1_bignum_length(rkey->private_exponent) +
-               ssh1_bignum_length(rkey->iqmp) +
-               ssh1_bignum_length(rkey->p) +
-               ssh1_bignum_length(rkey->q) + 4 + clen  /* comment */
-               ;
-
-           request = snewn(reqlen, unsigned char);
-
-           request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
-           reqlen = 5;
-           PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
-           reqlen += 4;
-           reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
-           reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);
-           reqlen +=
-               ssh1_write_bignum(request + reqlen,
-                                 rkey->private_exponent);
-           reqlen += ssh1_write_bignum(request + reqlen, rkey->iqmp);
-           reqlen += ssh1_write_bignum(request + reqlen, rkey->p);
-           reqlen += ssh1_write_bignum(request + reqlen, rkey->q);
-           PUT_32BIT(request + reqlen, clen);
-           memcpy(request + reqlen + 4, rkey->comment, clen);
-           reqlen += 4 + clen;
-           PUT_32BIT(request, reqlen - 4);
-
-           ret = agent_query(request, reqlen, &vresponse, &resplen,
-                             NULL, NULL);
-           assert(ret == 1);
-           response = vresponse;
-           if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS)
-               MessageBox(NULL, "The already running Pageant "
-                          "refused to add the key.", APPNAME,
-                          MB_OK | MB_ICONERROR);
-
-           sfree(request);
-           sfree(response);
-       } else {
-           if (!pageant_add_ssh1_key(rkey))
-               sfree(rkey);           /* already present, don't waste RAM */
-       }
-    } else {
-       if (already_running) {
-           unsigned char *request, *response;
-           void *vresponse;
-           int reqlen, alglen, clen, keybloblen, resplen, ret;
-           alglen = strlen(skey->alg->name);
-           clen = strlen(skey->comment);
-
-           keybloblen = skey->alg->openssh_fmtkey(skey->data, NULL, 0);
-
-           reqlen = 4 + 1 +           /* length, message type */
-               4 + alglen +           /* algorithm name */
-               keybloblen +           /* key data */
-               4 + clen               /* comment */
-               ;
-
-           request = snewn(reqlen, unsigned char);
-
-           request[4] = SSH2_AGENTC_ADD_IDENTITY;
-           reqlen = 5;
-           PUT_32BIT(request + reqlen, alglen);
-           reqlen += 4;
-           memcpy(request + reqlen, skey->alg->name, alglen);
-           reqlen += alglen;
-           reqlen += skey->alg->openssh_fmtkey(skey->data,
-                                               request + reqlen,
-                                               keybloblen);
-           PUT_32BIT(request + reqlen, clen);
-           memcpy(request + reqlen + 4, skey->comment, clen);
-           reqlen += clen + 4;
-           PUT_32BIT(request, reqlen - 4);
-
-           ret = agent_query(request, reqlen, &vresponse, &resplen,
-                             NULL, NULL);
-           assert(ret == 1);
-           response = vresponse;
-           if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS)
-               MessageBox(NULL, "The already running Pageant "
-                          "refused to add the key.", APPNAME,
-                          MB_OK | MB_ICONERROR);
-
-           sfree(request);
-           sfree(response);
-       } else {
-           if (!pageant_add_ssh2_key(skey)) {
-               skey->alg->freekey(skey->data);
-               sfree(skey);           /* already present, don't waste RAM */
-           }
-       }
-    }
-}
-
-/*
- * Acquire a keylist1 from the primary Pageant; this means either
- * calling pageant_make_keylist1 (if that's us) or sending a message
- * to the primary Pageant (if it's not).
- */
-static void *get_keylist1(int *length)
-{
-    void *ret;
-
-    if (already_running) {
-       unsigned char request[5], *response;
-       void *vresponse;
-       int resplen, retval;
-       request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
-       PUT_32BIT(request, 4);
-
-       retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
-       assert(retval == 1);
-       response = vresponse;
-       if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
-            sfree(response);
-           return NULL;
-        }
-
-       ret = snewn(resplen-5, unsigned char);
-       memcpy(ret, response+5, resplen-5);
-       sfree(response);
-
-       if (length)
-           *length = resplen-5;
-    } else {
-       ret = pageant_make_keylist1(length);
-    }
-    return ret;
-}
-
-/*
- * Acquire a keylist2 from the primary Pageant; this means either
- * calling pageant_make_keylist2 (if that's us) or sending a message
- * to the primary Pageant (if it's not).
- */
-static void *get_keylist2(int *length)
-{
-    void *ret;
-
-    if (already_running) {
-       unsigned char request[5], *response;
-       void *vresponse;
-       int resplen, retval;
-
-       request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
-       PUT_32BIT(request, 4);
-
-       retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
-       assert(retval == 1);
-       response = vresponse;
-       if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
-            sfree(response);
-           return NULL;
-        }
-
-       ret = snewn(resplen-5, unsigned char);
-       memcpy(ret, response+5, resplen-5);
-       sfree(response);
-
-       if (length)
-           *length = resplen-5;
-    } else {
-       ret = pageant_make_keylist2(length);
-    }
-    return ret;
-}
-
 static void answer_msg(void *msgv)
 {
     unsigned char *msg = (unsigned char *)msgv;
@@ -759,6 +397,69 @@ static void answer_msg(void *msgv)
     sfree(reply);
 }
 
+static void win_add_keyfile(Filename *filename)
+{
+    char *err;
+    int ret;
+    char *passphrase = NULL;
+
+    /*
+     * Try loading the key without a passphrase. (Or rather, without a
+     * _new_ passphrase; pageant_add_keyfile will take care of trying
+     * all the passphrases we've already stored.)
+     */
+    ret = pageant_add_keyfile(filename, NULL, &err);
+    if (ret == PAGEANT_ACTION_OK) {
+        goto done;
+    } else if (ret == PAGEANT_ACTION_FAILURE) {
+        goto error;
+    }
+
+    /*
+     * OK, a passphrase is needed, and we've been given the key
+     * comment to use in the passphrase prompt.
+     */
+    while (1) {
+        INT_PTR dlgret;
+        struct PassphraseProcStruct pps;
+
+        pps.passphrase = &passphrase;
+        pps.comment = err;
+        dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210),
+                                NULL, PassphraseProc, (LPARAM) &pps);
+        passphrase_box = NULL;
+
+        if (!dlgret)
+            goto done;                /* operation cancelled */
+
+        sfree(err);
+
+        assert(passphrase != NULL);
+
+        ret = pageant_add_keyfile(filename, passphrase, &err);
+        if (ret == PAGEANT_ACTION_OK) {
+            goto done;
+        } else if (ret == PAGEANT_ACTION_FAILURE) {
+            goto error;
+        }
+
+        smemclr(passphrase, strlen(passphrase));
+        sfree(passphrase);
+        passphrase = NULL;
+    }
+
+  error:
+    message_box(err, APPNAME, MB_OK | MB_ICONERROR,
+                HELPCTXID(errors_cantloadkey));
+  done:
+    if (passphrase) {
+        smemclr(passphrase, strlen(passphrase));
+        sfree(passphrase);
+    }
+    sfree(err);
+    return;
+}
+
 /*
  * Prompt for a key file to add, and add it.
  */
@@ -783,7 +484,7 @@ static void prompt_add_keyfile(void)
        if(strlen(filelist) > of.nFileOffset) {
            /* Only one filename returned? */
             Filename *fn = filename_from_str(filelist);
-           add_keyfile(fn);
+           win_add_keyfile(fn);
             filename_free(fn);
         } else {
            /* we are returned a bunch of strings, end to
@@ -796,7 +497,7 @@ static void prompt_add_keyfile(void)
            while (*filewalker != '\0') {
                char *filename = dupcat(dir, "\\", filewalker, NULL);
                 Filename *fn = filename_from_str(filename);
-               add_keyfile(fn);
+               win_add_keyfile(fn);
                 filename_free(fn);
                sfree(filename);
                filewalker += strlen(filewalker) + 1;
@@ -804,7 +505,7 @@ static void prompt_add_keyfile(void)
        }
 
        keylist_update();
-       forget_passphrases();
+       pageant_forget_passphrases();
     }
     sfree(filelist);
 }
@@ -812,7 +513,7 @@ static void prompt_add_keyfile(void)
 /*
  * Dialog-box function for the key list box.
  */
-static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK KeyListProc(HWND hwnd, UINT msg,
                                WPARAM wParam, LPARAM lParam)
 {
     struct RSAKey *rkey;
@@ -944,7 +645,7 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
       case WM_HELP:
         {
             int id = ((LPHELPINFO)lParam)->iCtrlId;
-            char *topic = NULL;
+            const char *topic = NULL;
             switch (id) {
               case 100: topic = WINHELP_CTX_pageant_keylist; break;
               case 101: topic = WINHELP_CTX_pageant_addkey; break;
@@ -1095,7 +796,6 @@ PSID get_default_sid(void)
 static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                                WPARAM wParam, LPARAM lParam)
 {
-    int ret;
     static int menuinprogress;
     static UINT msgTaskbarCreated = 0;
 
@@ -1130,10 +830,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            menuinprogress = 1;
            update_sessions();
            SetForegroundWindow(hwnd);
-           ret = TrackPopupMenu(systray_menu,
-                                TPM_RIGHTALIGN | TPM_BOTTOMALIGN |
-                                TPM_RIGHTBUTTON,
-                                wParam, lParam, 0, hwnd, NULL);
+           TrackPopupMenu(systray_menu,
+                          TPM_RIGHTALIGN | TPM_BOTTOMALIGN |
+                          TPM_RIGHTBUTTON,
+                          wParam, lParam, 0, hwnd, NULL);
            menuinprogress = 0;
        }
        break;
@@ -1141,7 +841,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
       case WM_SYSCOMMAND:
        switch (wParam & ~0xF) {       /* low 4 bits reserved to Windows */
          case IDM_PUTTY:
-           if((int)ShellExecute(hwnd, NULL, putty_path, _T(""), _T(""),
+           if((INT_PTR)ShellExecute(hwnd, NULL, putty_path, _T(""), _T(""),
                                 SW_SHOW) <= 32) {
                MessageBox(NULL, "Unable to execute PuTTY!",
                           "Error", MB_OK | MB_ICONERROR);
@@ -1208,7 +908,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                    GetMenuItemInfo(session_menu, wParam, FALSE, &mii);
                    strcpy(param, "@");
                    strcat(param, mii.dwTypeData);
-                   if((int)ShellExecute(hwnd, NULL, putty_path, param,
+                   if((INT_PTR)ShellExecute(hwnd, NULL, putty_path, param,
                                         _T(""), SW_SHOW) <= 32) {
                        MessageBox(NULL, "Unable to execute PuTTY!", "Error",
                                   MB_OK | MB_ICONERROR);
@@ -1264,7 +964,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                        debug(("couldn't get default SID\n"));
 #endif
                         CloseHandle(filemap);
-                        sfree(ourself);
                        return 0;
                     }
 
@@ -1277,7 +976,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                                rc));
 #endif
                         CloseHandle(filemap);
-                        sfree(ourself);
                         sfree(ourself2);
                        return 0;
                    }
@@ -1298,7 +996,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                         !EqualSid(mapowner, ourself2)) {
                         CloseHandle(filemap);
                         LocalFree(psd);
-                        sfree(ourself);
                         sfree(ourself2);
                        return 0;      /* security ID mismatch! */
                     }
@@ -1306,7 +1003,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                    debug(("security stuff matched\n"));
 #endif
                     LocalFree(psd);
-                    sfree(ourself);
                     sfree(ourself2);
                } else {
 #ifdef DEBUG_IPC
@@ -1339,7 +1035,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
 /*
  * Fork and Exec the command in cmdline. [DBW]
  */
-void spawn_cmd(char *cmdline, char * args, int show)
+void spawn_cmd(const char *cmdline, const char *args, int show)
 {
     if (ShellExecute(NULL, _T("open"), cmdline,
                     args, NULL, show) <= (HINSTANCE) 32) {
@@ -1373,11 +1069,13 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     WNDCLASS wndclass;
     MSG msg;
-    char *command = NULL;
+    const char *command = NULL;
     int added_keys = 0;
     int argc, i;
     char **argv, **argstart;
 
+    dll_hijacking_protection();
+
     hinst = inst;
     hwnd = NULL;
 
@@ -1453,11 +1151,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
         pageant_init();
     }
 
-    /*
-     * Initialise storage for short-term passphrase cache.
-     */
-    passphrases = newtree234(NULL);
-
     /*
      * Process the command line and add keys as listed on it.
      */
@@ -1466,6 +1159,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        if (!strcmp(argv[i], "-pgpfp")) {
            pgp_fingerprints();
            return 1;
+        } else if (!strcmp(argv[i], "-restrict-acl") ||
+                   !strcmp(argv[i], "-restrict_acl") ||
+                   !strcmp(argv[i], "-restrictacl")) {
+            restrict_process_acl();
        } else if (!strcmp(argv[i], "-c")) {
            /*
             * If we see `-c', then the rest of the
@@ -1479,7 +1176,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
            break;
        } else {
             Filename *fn = filename_from_str(argv[i]);
-           add_keyfile(fn);
+           win_add_keyfile(fn);
             filename_free(fn);
            added_keys = TRUE;
        }
@@ -1489,7 +1186,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
      * Forget any passphrase that we retained while going over
      * command line keyfiles.
      */
-    forget_passphrases();
+    pageant_forget_passphrases();
 
     if (command) {
        char *args;
@@ -1548,7 +1245,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        session_menu = CreateMenu();
        AppendMenu(systray_menu, MF_ENABLED, IDM_PUTTY, "&New Session");
        AppendMenu(systray_menu, MF_POPUP | MF_ENABLED,
-                  (UINT) session_menu, "&Saved Sessions");
+                  (UINT_PTR) session_menu, "&Saved Sessions");
        AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
     }
     AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS,