]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/window.c
Move sfree inside if.
[PuTTY.git] / windows / window.c
index 6baa45a79e95658bd0c3a2081858b45557c77a41..baed768f10a4c4ae5d181bdf4bd1535ea97c4521 100644 (file)
@@ -19,6 +19,7 @@
 #include "terminal.h"
 #include "storage.h"
 #include "win_res.h"
+#include "winsecur.h"
 
 #ifndef NO_MULTIMON
 #include <multimon.h>
 #define WHEEL_DELTA 120
 #endif
 
+/* VK_PACKET, used to send Unicode characters in WM_KEYDOWNs */
+#ifndef VK_PACKET
+#define VK_PACKET 0xE7
+#endif
+
 static Mouse_Button translate_button(Mouse_Button button);
 static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
@@ -88,7 +94,7 @@ static void another_font(int);
 static void deinit_fonts(void);
 static void set_input_locale(HKL);
 static void update_savedsess_menu(void);
-static void init_flashwindow(void);
+static void init_winfuncs(void);
 
 static int is_full_screen(void);
 static void make_full_screen(void);
@@ -215,8 +221,11 @@ static UINT wm_mousewheel = WM_MOUSEWHEEL;
     (((wch) >= 0x180B && (wch) <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR */ \
      ((wch) >= 0xFE00 && (wch) <= 0xFE0F)) /* VARIATION SELECTOR 1-16 */
 
+const int share_can_be_downstream = TRUE;
+const int share_can_be_upstream = TRUE;
+
 /* Dummy routine, only required in plink. */
-void ldisc_update(void *frontend, int echo, int edit)
+void frontend_echoedit_update(void *frontend, int echo, int edit)
 {
 }
 
@@ -329,7 +338,6 @@ static void close_session(void *ignored_context)
 
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
-    WNDCLASS wndclass;
     MSG msg;
     HRESULT hr;
     int guess_width, guess_height;
@@ -367,7 +375,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
     init_help();
 
-    init_flashwindow();
+    init_winfuncs();
 
     conf = conf_new();
 
@@ -383,6 +391,19 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        return 1;
     }
 
+    /*
+     * Protect our process
+     */
+    {
+#ifndef UNPROTECT
+        char *error = NULL;
+        if (! setprocessacl(error)) {
+           logevent(NULL, "Could not restrict process ACL: %s",
+                    error);
+           sfree(error);
+       }
+#endif
+    }
     /*
      * Process the command line.
      */
@@ -545,8 +566,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
                            q += 2;
                        conf_set_int(conf, CONF_protocol, PROT_TELNET);
                        p = q;
-                       while (*p && *p != ':' && *p != '/')
-                           p++;
+                        p += host_strcspn(p, ":/");
                        c = *p;
                        if (*p)
                            *p++ = '\0';
@@ -611,15 +631,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
             /*
              * Trim a colon suffix off the hostname if it's there. In
-             * order to protect IPv6 address literals against this
-             * treatment, we do not do this if there's _more_ than one
-             * colon.
+             * order to protect unbracketed IPv6 address literals
+             * against this treatment, we do not do this if there's
+             * _more_ than one colon.
              */
             {
-                char *c = strchr(host, ':');
+                char *c = host_strchr(host, ':');
  
                 if (c) {
-                    char *d = strchr(c+1, ':');
+                    char *d = host_strchr(c+1, ':');
                     if (!d)
                         *c = '\0';
                 }
@@ -643,6 +663,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     }
 
     if (!prev) {
+        WNDCLASSW wndclass;
+
        wndclass.style = 0;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
@@ -652,9 +674,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM);
        wndclass.hbrBackground = NULL;
        wndclass.lpszMenuName = NULL;
-       wndclass.lpszClassName = appname;
+       wndclass.lpszClassName = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
 
-       RegisterClass(&wndclass);
+       RegisterClassW(&wndclass);
     }
 
     memset(&ucsdata, 0, sizeof(ucsdata));
@@ -688,6 +710,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     {
        int winmode = WS_OVERLAPPEDWINDOW | WS_VSCROLL;
        int exwinmode = 0;
+        wchar_t *uappname = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
        if (!conf_get_int(conf, CONF_scrollbar))
            winmode &= ~(WS_VSCROLL);
        if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED)
@@ -696,10 +719,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
            exwinmode |= WS_EX_TOPMOST;
        if (conf_get_int(conf, CONF_sunken_edge))
            exwinmode |= WS_EX_CLIENTEDGE;
-       hwnd = CreateWindowEx(exwinmode, appname, appname,
-                             winmode, CW_USEDEFAULT, CW_USEDEFAULT,
-                             guess_width, guess_height,
-                             NULL, NULL, inst, NULL);
+       hwnd = CreateWindowExW(exwinmode, uappname, uappname,
+                               winmode, CW_USEDEFAULT, CW_USEDEFAULT,
+                               guess_width, guess_height,
+                               NULL, NULL, inst, NULL);
+        sfree(uappname);
     }
 
     /*
@@ -849,7 +873,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        int nhandles, n;
         DWORD timeout;
 
-        if (toplevel_callback_pending() || GetQueueStatus(QS_ALLINPUT)) {
+        if (toplevel_callback_pending() ||
+            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
             /*
              * If we have anything we'd like to do immediately, set
              * the timeout for MsgWaitForMultipleObjects to zero so
@@ -885,12 +910,34 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        } else
            sfree(handles);
 
-       if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+       while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT)
                goto finished;         /* two-level break */
 
            if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
-               DispatchMessage(&msg);
+               DispatchMessageW(&msg);
+
+            /*
+             * WM_NETEVENT messages seem to jump ahead of others in
+             * the message queue. I'm not sure why; the docs for
+             * PeekMessage mention that messages are prioritised in
+             * some way, but I'm unclear on which priorities go where.
+             *
+             * Anyway, in practice I observe that WM_NETEVENT seems to
+             * jump to the head of the queue, which means that if we
+             * were to only process one message every time round this
+             * loop, we'd get nothing but NETEVENTs if the server
+             * flooded us with data, and stop responding to any other
+             * kind of window message. So instead, we keep on round
+             * this loop until we've consumed at least one message
+             * that _isn't_ a NETEVENT, or run out of messages
+             * completely (whichever comes first). And we don't go to
+             * run_toplevel_callbacks (which is where the netevents
+             * are actually processed, causing fresh NETEVENT messages
+             * to appear) until we've done this.
+             */
+            if (msg.message != WM_NETEVENT)
+                break;
        }
 
         run_toplevel_callbacks();
@@ -1101,7 +1148,7 @@ void set_raw_mouse_mode(void *frontend, int activate)
 /*
  * Print a message box and close the connection.
  */
-void connection_fatal(void *frontend, char *fmt, ...)
+void connection_fatal(void *frontend, const char *fmt, ...)
 {
     va_list ap;
     char *stuff, morestuff[100];
@@ -1123,7 +1170,7 @@ void connection_fatal(void *frontend, char *fmt, ...)
 /*
  * Report an error at the command-line parsing stage.
  */
-void cmdline_error(char *fmt, ...)
+void cmdline_error(const char *fmt, ...)
 {
     va_list ap;
     char *stuff, morestuff[100];
@@ -2140,7 +2187,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                    unsigned int sessno = ((lParam - IDM_SAVED_MIN)
                                           / MENU_SAVED_STEP) + 1;
                    if (sessno < (unsigned)sesslist.nsessions) {
-                       char *session = sesslist.sessions[sessno];
+                       const char *session = sesslist.sessions[sessno];
                        cl = dupprintf("putty @%s", session);
                        inherit_handles = FALSE;
                        freecl = TRUE;
@@ -2231,9 +2278,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                 * Flush the line discipline's edit buffer in the
                 * case where local editing has just been disabled.
                 */
-               ldisc_configure(ldisc, conf);
-               if (ldisc)
-                   ldisc_send(ldisc, NULL, 0, 0);
+               if (ldisc) {
+                    ldisc_configure(ldisc, conf);
+                   ldisc_echoedit_update(ldisc);
+                }
                if (pal)
                    DeleteObject(pal);
                logpal = NULL;
@@ -2375,7 +2423,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
          case IDM_RESET:
            term_pwron(term, TRUE);
            if (ldisc)
-               ldisc_send(ldisc, NULL, 0, 0);
+               ldisc_echoedit_update(ldisc);
            break;
          case IDM_ABOUT:
            showabout(hwnd);
@@ -3057,7 +3105,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            unsigned char buf[20];
            int len;
 
-           if (wParam == VK_PROCESSKEY) { /* IME PROCESS key */
+           if (wParam == VK_PROCESSKEY || /* IME PROCESS key */
+                wParam == VK_PACKET) {     /* 'this key is a Unicode char' */
                if (message == WM_KEYDOWN) {
                    MSG m;
                    m.hwnd = hwnd;
@@ -3069,7 +3118,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            } else {
                len = TranslateKey(message, wParam, lParam, buf);
                if (len == -1)
-                   return DefWindowProc(hwnd, message, wParam, lParam);
+                   return DefWindowProcW(hwnd, message, wParam, lParam);
 
                if (len != 0) {
                    /*
@@ -3173,10 +3222,21 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
         * we're ready to cope.
         */
        {
-           char c = (unsigned char)wParam;
-           term_seen_key_event(term);
-           if (ldisc)
-               lpage_send(ldisc, CP_ACP, &c, 1, 1);
+            static wchar_t pending_surrogate = 0;
+           wchar_t c = wParam;
+
+            if (IS_HIGH_SURROGATE(c)) {
+                pending_surrogate = c;
+            } else if (IS_SURROGATE_PAIR(pending_surrogate, c)) {
+                wchar_t pair[2];
+                pair[0] = pending_surrogate;
+                pair[1] = c;
+                term_seen_key_event(term);
+                luni_send(ldisc, pair, 2, 1);
+            } else if (!IS_SURROGATE(c)) {
+                term_seen_key_event(term);
+                luni_send(ldisc, &c, 1, 1);
+            }
        }
        return 0;
       case WM_SYSCOLORCHANGE:
@@ -3245,10 +3305,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                                   TO_CHR_X(p.x),
                                   TO_CHR_Y(p.y), shift_pressed,
                                   control_pressed, is_alt_pressed());
-                       term_mouse(term, b, translate_button(b),
-                                  MA_RELEASE, TO_CHR_X(p.x),
-                                  TO_CHR_Y(p.y), shift_pressed,
-                                  control_pressed, is_alt_pressed());
                    } /* else: not sure when this can fail */
                } else {
                    /* trigger a scroll */
@@ -3265,7 +3321,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
      * Any messages we don't process completely above are passed through to
      * DefWindowProc() for default processing.
      */
-    return DefWindowProc(hwnd, message, wParam, lParam);
+    return DefWindowProcW(hwnd, message, wParam, lParam);
 }
 
 /*
@@ -3880,6 +3936,17 @@ int char_width(Context ctx, int uc) {
     return ibuf;
 }
 
+DECL_WINDOWS_FUNCTION(static, BOOL, FlashWindowEx, (PFLASHWINFO));
+DECL_WINDOWS_FUNCTION(static, BOOL, ToUnicodeEx,
+                      (UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL));
+
+static void init_winfuncs(void)
+{
+    HMODULE user32_module = load_system32_dll("user32.dll");
+    GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
+    GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx);
+}
+
 /*
  * Translate a WM_(SYS)?KEY(UP|DOWN) message into a string of ASCII
  * codes. Returns number of bytes used, zero to drop the message,
@@ -4573,9 +4640,9 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
        /* XXX how do we know what the max size of the keys array should
         * be is? There's indication on MS' website of an Inquire/InquireEx
         * functioning returning a KBINFO structure which tells us. */
-       if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-           r = ToUnicodeEx(wParam, scan, keystate, keys_unicode,
-                            lenof(keys_unicode), 0, kbd_layout);
+       if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT && p_ToUnicodeEx) {
+           r = p_ToUnicodeEx(wParam, scan, keystate, keys_unicode,
+                              lenof(keys_unicode), 0, kbd_layout);
        } else {
            /* XXX 'keys' parameter is declared in MSDN documentation as
             * 'LPWORD lpChar'.
@@ -5312,7 +5379,7 @@ void optimised_move(void *frontend, int to, int from, int lines)
 /*
  * Print a message box and perform a fatal exit.
  */
-void fatalbox(char *fmt, ...)
+void fatalbox(const char *fmt, ...)
 {
     va_list ap;
     char *stuff, morestuff[100];
@@ -5329,7 +5396,7 @@ void fatalbox(char *fmt, ...)
 /*
  * 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 *stuff, morestuff[100];
@@ -5347,7 +5414,7 @@ void modalfatalbox(char *fmt, ...)
 /*
  * Print a message box and don't close the connection.
  */
-void nonfatal(char *fmt, ...)
+void nonfatal(const char *fmt, ...)
 {
     va_list ap;
     char *stuff, morestuff[100];
@@ -5360,14 +5427,6 @@ void nonfatal(char *fmt, ...)
     sfree(stuff);
 }
 
-DECL_WINDOWS_FUNCTION(static, BOOL, FlashWindowEx, (PFLASHWINFO));
-
-static void init_flashwindow(void)
-{
-    HMODULE user32_module = load_system32_dll("user32.dll");
-    GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
-}
-
 static BOOL flash_window_ex(DWORD dwFlags, UINT uCount, DWORD dwTimeout)
 {
     if (p_FlashWindowEx) {
@@ -5762,7 +5821,7 @@ int from_backend_eof(void *frontend)
     return TRUE;   /* do respond to incoming EOF with outgoing */
 }
 
-int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
+int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen)
 {
     int ret;
     ret = cmdline_get_passwd_input(p, in, inlen);