X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=windows%2Fwindow.c;h=bc89195579f94da84cf248a3b1500e50cfffbba8;hb=1472aa2a265dfbfe7225729862ea21b5fb2da22f;hp=0ae88cc10e7c963335592fc8655cc541813198f1;hpb=5e2c794424f84ad1b48bb2069723e57813543aa7;p=PuTTY.git diff --git a/windows/window.c b/windows/window.c index 0ae88cc1..bc891955 100644 --- a/windows/window.c +++ b/windows/window.c @@ -104,10 +104,6 @@ static int offset_width, offset_height; static int was_zoomed = 0; static int prev_rows, prev_cols; -static int pending_netevent = 0; -static WPARAM pend_netevent_wParam = 0; -static LPARAM pend_netevent_lParam = 0; -static void enact_pending_netevent(void); static void flash_window(int mode); static void sys_cursor_update(void); static int get_fullscreen_rect(RECT * ss); @@ -121,7 +117,7 @@ static Backend *back; static void *backhandle; static struct unicode_data ucsdata; -static int must_close_session, session_closed; +static int session_closed; static int reconfiguring = FALSE; static const struct telnet_special *specials = NULL; @@ -140,6 +136,12 @@ static struct { enum { SYSMENU, CTXMENU }; static HMENU savedsess_menu; +struct wm_netevent_params { + /* Used to pass data to wm_netevent_callback */ + WPARAM wParam; + LPARAM lParam; +}; + Conf *conf; /* exported to windlg.c */ static void conf_cache_data(void); @@ -289,11 +291,10 @@ static void start_backend(void) DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); } - must_close_session = FALSE; session_closed = FALSE; } -static void close_session(void) +static void close_session(void *ignored_context) { char morestuff[100]; int i; @@ -324,15 +325,6 @@ static void close_session(void) InsertMenu(popup_menus[i].menu, IDM_DUPSESS, MF_BYCOMMAND | MF_ENABLED, IDM_RESTART, "&Restart Session"); } - - /* - * Unset the 'must_close_session' flag, or else we'll come - * straight back here the next time we go round the main message - * loop - which, worse still, will be immediately (without - * blocking) because we've just triggered a WM_SETTEXT by the - * window title change above. - */ - must_close_session = FALSE; } int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) @@ -617,10 +609,21 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } } - /* - * Trim off a colon suffix if it's there. - */ - host[strcspn(host, ":")] = '\0'; + /* + * 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. + */ + { + char *c = strchr(host, ':'); + + if (c) { + char *d = strchr(c+1, ':'); + if (!d) + *c = '\0'; + } + } /* * Remove any remaining whitespace. @@ -853,34 +856,23 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); sfree(handles); - if (must_close_session) - close_session(); } else sfree(handles); + run_toplevel_callbacks(); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) goto finished; /* two-level break */ if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg))) DispatchMessage(&msg); - /* Send the paste buffer if there's anything to send */ - term_paste(term); - /* If there's nothing new in the queue then we can do everything - * we've delayed, reading the socket, writing, and repainting - * the window. - */ - if (must_close_session) - close_session(); + + run_toplevel_callbacks(); } /* The messages seem unreliable; especially if we're being tricky */ term_set_focus(term, GetForegroundWindow() == hwnd); - - if (pending_netevent) - enact_pending_netevent(); - - net_pending_errors(); } finished: @@ -1103,7 +1095,7 @@ void connection_fatal(void *frontend, char *fmt, ...) if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON) PostQuitMessage(1); else { - must_close_session = TRUE; + queue_toplevel_callback(close_session, NULL); } } @@ -1127,19 +1119,11 @@ void cmdline_error(char *fmt, ...) /* * Actually do the job requested by a WM_NETEVENT */ -static void enact_pending_netevent(void) +static void wm_netevent_callback(void *vctx) { - static int reentering = 0; - extern int select_result(WPARAM, LPARAM); - - if (reentering) - return; /* don't unpend the pending */ - - pending_netevent = FALSE; - - reentering = 1; - select_result(pend_netevent_wParam, pend_netevent_lParam); - reentering = 0; + struct wm_netevent_params *params = (struct wm_netevent_params *)vctx; + select_result(params->wParam, params->lParam); + sfree(vctx); } /* @@ -2000,7 +1984,7 @@ void notify_remote_exit(void *fe) (close_on_exit == AUTO && exitcode != INT_MAX)) { PostQuitMessage(0); } else { - must_close_session = TRUE; + queue_toplevel_callback(close_session, NULL); session_closed = TRUE; /* exitcode == INT_MAX indicates that the connection was closed * by a fatal error, so an error box will be coming our way and @@ -2354,7 +2338,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, InvalidateRect(hwnd, NULL, TRUE); reset_window(init_lvl); - net_pending_errors(); conf_free(prev_conf); } @@ -2417,7 +2400,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; if (back) back->special(backhandle, specials[i].code); - net_pending_errors(); } } break; @@ -2697,20 +2679,20 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } return 0; case WM_NETEVENT: - /* Notice we can get multiple netevents, FD_READ, FD_WRITE etc - * but the only one that's likely to try to overload us is FD_READ. - * This means buffering just one is fine. - */ - if (pending_netevent) - enact_pending_netevent(); - - pending_netevent = TRUE; - pend_netevent_wParam = wParam; - pend_netevent_lParam = lParam; - if (WSAGETSELECTEVENT(lParam) != FD_READ) - enact_pending_netevent(); - - net_pending_errors(); + { + /* + * To protect against re-entrancy when Windows's recv() + * immediately triggers a new WSAAsyncSelect window + * message, we don't call select_result directly from this + * handler but instead wait until we're back out at the + * top level of the message loop. + */ + struct wm_netevent_params *params = + snew(struct wm_netevent_params); + params->wParam = wParam; + params->lParam = lParam; + queue_toplevel_callback(wm_netevent_callback, params); + } return 0; case WM_SETFOCUS: term_set_focus(term, TRUE); @@ -3069,14 +3051,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return DefWindowProc(hwnd, message, wParam, lParam); if (len != 0) { - /* - * Interrupt an ongoing paste. I'm not sure - * this is sensible, but for the moment it's - * preferable to having to faff about buffering - * things. - */ - term_nopaste(term); - /* * We need not bother about stdin backlogs * here, because in GUI PuTTY we can't do @@ -3092,7 +3066,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } } } - net_pending_errors(); return 0; case WM_INPUTLANGCHANGE: /* wParam == Font number */ @@ -4627,13 +4600,6 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, if (r > 0) { WCHAR keybuf; - /* - * Interrupt an ongoing paste. I'm not sure this is - * sensible, but for the moment it's preferable to - * having to faff about buffering things. - */ - term_nopaste(term); - p = output; for (i = 0; i < r; i++) { wchar_t wch = keys_unicode[i];