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);
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;
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);
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;
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)
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);
if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
DispatchMessage(&msg);
- 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:
if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON)
PostQuitMessage(1);
else {
- must_close_session = TRUE;
+ queue_toplevel_callback(close_session, NULL);
}
}
/*
* 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);
}
/*
(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
InvalidateRect(hwnd, NULL, TRUE);
reset_window(init_lvl);
- net_pending_errors();
conf_free(prev_conf);
}
break;
if (back)
back->special(backhandle, specials[i].code);
- net_pending_errors();
}
}
break;
}
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);
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
}
}
}
- net_pending_errors();
return 0;
case WM_INPUTLANGCHANGE:
/* wParam == Font number */
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];