X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d4352f813a0703cc7f7a873525131b272ef0c105..13c8f29ce361e3aad71cf2b44e76d5cfdaf7dda3:/src/w32fns.c diff --git a/src/w32fns.c b/src/w32fns.c index d92352a980..b9002bae77 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1,13 +1,13 @@ /* Graphical user interface functions for the Microsoft Windows API. -Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc. +Copyright (C) 1989, 1992-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -55,6 +55,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include @@ -1665,10 +1666,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) FRAME_MENU_BAR_LINES (f) = 0; FRAME_MENU_BAR_HEIGHT (f) = 0; if (nlines) - { - FRAME_EXTERNAL_MENU_BAR (f) = 1; - windows_or_buffers_changed = 23; - } + FRAME_EXTERNAL_MENU_BAR (f) = 1; else { if (FRAME_EXTERNAL_MENU_BAR (f) == 1) @@ -4619,8 +4617,7 @@ my_create_tip_window (struct frame *f) rect.right = FRAME_PIXEL_WIDTH (f); rect.bottom = FRAME_PIXEL_HEIGHT (f); - AdjustWindowRect (&rect, f->output_data.w32->dwStyle, - FRAME_EXTERNAL_MENU_BAR (f)); + AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false); tip_window = FRAME_W32_WINDOW (f) = CreateWindow (EMACS_CLASS, @@ -5210,7 +5207,7 @@ x_get_focus_frame (struct frame *frame) DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, doc: /* Internal function called by `color-defined-p', which see. -(Note that the Nextstep version of this function ignores FRAME.) */) +\(Note that the Nextstep version of this function ignores FRAME.) */) (Lisp_Object color, Lisp_Object frame) { XColor foo; @@ -5352,7 +5349,7 @@ If omitted or nil, that stands for the selected frame's display. */) DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0, doc: /* Return the "vendor ID" string of the GUI software on TERMINAL. -(Labeling every distributor as a "vendor" embodies the false assumption +\(Labeling every distributor as a "vendor" embodies the false assumption that operating systems cannot be developed and distributed noncommercially.) For GNU and Unix systems, this queries the X server software; for @@ -5754,7 +5751,7 @@ DISPLAY is the name of the display to connect to. Optional second arg XRM-STRING is a string of resources in xrdb format. If the optional third arg MUST-SUCCEED is non-nil, terminate Emacs if we can't open the connection. -(In the Nextstep version, the last two arguments are currently ignored.) */) +\(In the Nextstep version, the last two arguments are currently ignored.) */) (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed) { char *xrm_option; @@ -6380,7 +6377,7 @@ compute_tip_xy (struct frame *f, if (INTEGERP (left)) *root_x = XINT (left); else if (INTEGERP (right)) - *root_y = XINT (right) - width; + *root_x = XINT (right) - width; else if (*root_x + XINT (dx) <= min_x) *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XINT (dx) + width <= max_x) @@ -6680,8 +6677,7 @@ Text larger than the specified size is clipped. */) rect.left = rect.top = 0; rect.right = width; rect.bottom = height; - AdjustWindowRect (&rect, f->output_data.w32->dwStyle, - FRAME_EXTERNAL_MENU_BAR (f)); + AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false); /* Position and size tooltip, and put it in the topmost group. The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a @@ -6988,12 +6984,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0) report_file_error ("filename too long", default_filename); } - len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (prompt), -1, NULL, 0); if (len > 32768) len = 32768; prompt_w = alloca (len * sizeof (wchar_t)); - pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (prompt), -1, prompt_w, len); } else @@ -7006,12 +7002,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0) report_file_error ("filename too long", default_filename); } - len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (prompt), -1, NULL, 0); if (len > 32768) len = 32768; prompt_w = alloca (len * sizeof (wchar_t)); - pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (prompt), -1, prompt_w, len); len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL); if (len > 32768) @@ -7493,10 +7489,10 @@ a ShowWindow flag: current_dir = ENCODE_FILE (current_dir); /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could be a URL that is not limited to MAX_PATH chararcters. */ - doclen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (document), -1, NULL, 0); doc_w = xmalloc (doclen * sizeof (wchar_t)); - pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (document), -1, doc_w, doclen); if (use_unicode) { @@ -7511,12 +7507,12 @@ a ShowWindow flag: int len; parameters = ENCODE_SYSTEM (parameters); - len = pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, + len = pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags, SSDATA (parameters), -1, NULL, 0); if (len > 32768) len = 32768; params_w = alloca (len * sizeof (wchar_t)); - pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, + pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags, SSDATA (parameters), -1, params_w, len); params_w[len - 1] = 0; } @@ -8094,14 +8090,25 @@ DEFUN ("w32-set-mouse-absolute-pixel-position", Fw32_set_mouse_absolute_pixel_po Sw32_set_mouse_absolute_pixel_position, 2, 2, 0, doc: /* Move mouse pointer to absolute pixel position (X, Y). The coordinates X and Y are interpreted in pixels relative to a position -(0, 0) of the selected frame's display. */) +\(0, 0) of the selected frame's display. */) (Lisp_Object x, Lisp_Object y) { + UINT trail_num = 0; + BOOL ret = false; + CHECK_TYPE_RANGED_INTEGER (int, x); CHECK_TYPE_RANGED_INTEGER (int, y); block_input (); + /* When "mouse trails" are in effect, moving the mouse cursor + sometimes leaves behind an annoying "ghost" of the pointer. + Avoid that by momentarily switching off mouse trails. */ + if (os_subtype == OS_NT + && w32_major_version + w32_minor_version >= 6) + ret = SystemParametersInfo (SPI_GETMOUSETRAILS, 0, &trail_num, 0); SetCursorPos (XINT (x), XINT (y)); + if (ret) + SystemParametersInfo (SPI_SETMOUSETRAILS, trail_num, NULL, 0); unblock_input (); return Qnil; @@ -8755,6 +8762,457 @@ Internal use only. */) return menubar_in_use ? Qt : Qnil; } +#if defined WINDOWSNT && !defined HAVE_DBUS + +/*********************************************************************** + Tray notifications + ***********************************************************************/ +/* A private struct declaration to avoid compile-time limits. */ +typedef struct MY_NOTIFYICONDATAW { + DWORD cbSize; + HWND hWnd; + UINT uID; + UINT uFlags; + UINT uCallbackMessage; + HICON hIcon; + WCHAR szTip[128]; + DWORD dwState; + DWORD dwStateMask; + WCHAR szInfo[256]; + _ANONYMOUS_UNION union { + UINT uTimeout; + UINT uVersion; + } DUMMYUNIONNAME; + WCHAR szInfoTitle[64]; + DWORD dwInfoFlags; + GUID guidItem; + HICON hBalloonIcon; +} MY_NOTIFYICONDATAW; + +#define MYNOTIFYICONDATAW_V1_SIZE offsetof (MY_NOTIFYICONDATAW, szTip[64]) +#define MYNOTIFYICONDATAW_V2_SIZE offsetof (MY_NOTIFYICONDATAW, guidItem) +#define MYNOTIFYICONDATAW_V3_SIZE offsetof (MY_NOTIFYICONDATAW, hBalloonIcon) +#ifndef NIF_INFO +# define NIF_INFO 0x00000010 +#endif +#ifndef NIIF_NONE +# define NIIF_NONE 0x00000000 +#endif +#ifndef NIIF_INFO +# define NIIF_INFO 0x00000001 +#endif +#ifndef NIIF_WARNING +# define NIIF_WARNING 0x00000002 +#endif +#ifndef NIIF_ERROR +# define NIIF_ERROR 0x00000003 +#endif + + +#define EMACS_TRAY_NOTIFICATION_ID 42 /* arbitrary */ +#define EMACS_NOTIFICATION_MSG (WM_APP + 1) + +enum NI_Severity { + Ni_None, + Ni_Info, + Ni_Warn, + Ni_Err +}; + +/* Report the version of a DLL given by its name. The return value is + constructed using MAKEDLLVERULL. */ +static ULONGLONG +get_dll_version (const char *dll_name) +{ + ULONGLONG version = 0; + HINSTANCE hdll = LoadLibrary (dll_name); + + if (hdll) + { + DLLGETVERSIONPROC pDllGetVersion + = (DLLGETVERSIONPROC) GetProcAddress (hdll, "DllGetVersion"); + + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + HRESULT result; + + memset (&dvi, 0, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + result = pDllGetVersion (&dvi); + if (SUCCEEDED (result)) + version = MAKEDLLVERULL (dvi.dwMajorVersion, dvi.dwMinorVersion, + 0, 0); + } + FreeLibrary (hdll); + } + + return version; +} + +/* Return the number of bytes in UTF-8 encoded string STR that + corresponds to at most LIM characters. If STR ends before LIM + characters, return the number of bytes in STR including the + terminating null byte. */ +static int +utf8_mbslen_lim (const char *str, int lim) +{ + const char *p = str; + int mblen = 0, nchars = 0; + + while (*p && nchars < lim) + { + int nbytes = CHAR_BYTES (*p); + + mblen += nbytes; + nchars++; + p += nbytes; + } + + if (!*p && nchars < lim) + mblen++; + + return mblen; +} + +/* Low-level subroutine to show tray notifications. All strings are + supposed to be unibyte UTF-8 encoded by the caller. */ +static EMACS_INT +add_tray_notification (struct frame *f, const char *icon, const char *tip, + enum NI_Severity severity, unsigned timeout, + const char *title, const char *msg) +{ + EMACS_INT retval = EMACS_TRAY_NOTIFICATION_ID; + + if (FRAME_W32_P (f)) + { + MY_NOTIFYICONDATAW nidw; + ULONGLONG shell_dll_version = get_dll_version ("Shell32.dll"); + wchar_t tipw[128], msgw[256], titlew[64]; + int tiplen; + + memset (&nidw, 0, sizeof(nidw)); + + /* MSDN says the full struct is supported since Vista, whose + Shell32.dll version is said to be 6.0.6. But DllGetVersion + cannot report the 3rd field value, it reports "build number" + instead, which is something else. So we use the Windows 7's + version 6.1 as cutoff, and Vista loses. (Actually, the loss + is not a real one, since we don't expose the hBalloonIcon + member of the struct to Lisp.) */ + if (shell_dll_version >= MAKEDLLVERULL (6, 1, 0, 0)) /* >= Windows 7 */ + nidw.cbSize = sizeof (nidw); + else if (shell_dll_version >= MAKEDLLVERULL (6, 0, 0, 0)) /* XP */ + nidw.cbSize = MYNOTIFYICONDATAW_V3_SIZE; + else if (shell_dll_version >= MAKEDLLVERULL (5, 0, 0, 0)) /* W2K */ + nidw.cbSize = MYNOTIFYICONDATAW_V2_SIZE; + else + nidw.cbSize = MYNOTIFYICONDATAW_V1_SIZE; /* < W2K */ + nidw.hWnd = FRAME_W32_WINDOW (f); + nidw.uID = EMACS_TRAY_NOTIFICATION_ID; + nidw.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO; + nidw.uCallbackMessage = EMACS_NOTIFICATION_MSG; + if (!*icon) + nidw.hIcon = LoadIcon (hinst, EMACS_CLASS); + else + { + if (w32_unicode_filenames) + { + wchar_t icon_w[MAX_PATH]; + + if (filename_to_utf16 (icon, icon_w) != 0) + { + errno = ENOENT; + return -1; + } + nidw.hIcon = LoadImageW (NULL, icon_w, IMAGE_ICON, 0, 0, + LR_DEFAULTSIZE | LR_LOADFROMFILE); + } + else + { + char icon_a[MAX_PATH]; + + if (filename_to_ansi (icon, icon_a) != 0) + { + errno = ENOENT; + return -1; + } + nidw.hIcon = LoadImageA (NULL, icon_a, IMAGE_ICON, 0, 0, + LR_DEFAULTSIZE | LR_LOADFROMFILE); + } + } + if (!nidw.hIcon) + { + switch (GetLastError ()) + { + case ERROR_FILE_NOT_FOUND: + errno = ENOENT; + break; + default: + errno = ENOMEM; + break; + } + return -1; + } + + /* Windows 9X and NT4 support only 64 characters in the Tip, + later versions support up to 128. */ + if (nidw.cbSize == MYNOTIFYICONDATAW_V1_SIZE) + { + tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, + tip, utf8_mbslen_lim (tip, 63), + tipw, 64); + if (tiplen >= 63) + tipw[63] = 0; + } + else + { + tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, + tip, utf8_mbslen_lim (tip, 127), + tipw, 128); + if (tiplen >= 127) + tipw[127] = 0; + } + if (tiplen == 0) + { + errno = EINVAL; + retval = -1; + goto done; + } + wcscpy (nidw.szTip, tipw); + + /* The rest of the structure is only supported since Windows 2000. */ + if (nidw.cbSize > MYNOTIFYICONDATAW_V1_SIZE) + { + int slen; + + slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, + msg, utf8_mbslen_lim (msg, 255), + msgw, 256); + if (slen >= 255) + msgw[255] = 0; + else if (slen == 0) + { + errno = EINVAL; + retval = -1; + goto done; + } + wcscpy (nidw.szInfo, msgw); + nidw.uTimeout = timeout; + slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, + title, utf8_mbslen_lim (title, 63), + titlew, 64); + if (slen >= 63) + titlew[63] = 0; + else if (slen == 0) + { + errno = EINVAL; + retval = -1; + goto done; + } + wcscpy (nidw.szInfoTitle, titlew); + + switch (severity) + { + case Ni_None: + nidw.dwInfoFlags = NIIF_NONE; + break; + case Ni_Info: + default: + nidw.dwInfoFlags = NIIF_INFO; + break; + case Ni_Warn: + nidw.dwInfoFlags = NIIF_WARNING; + break; + case Ni_Err: + nidw.dwInfoFlags = NIIF_ERROR; + break; + } + } + + if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) + { + /* GetLastError returns meaningless results when + Shell_NotifyIcon fails. */ + DebPrint (("Shell_NotifyIcon ADD failed (err=%d)\n", + GetLastError ())); + errno = EINVAL; + retval = -1; + } + done: + if (*icon && !DestroyIcon (nidw.hIcon)) + DebPrint (("DestroyIcon failed (err=%d)\n", GetLastError ())); + } + return retval; +} + +/* Low-level subroutine to remove a tray notification. Note: we only + pass the minimum data about the notification: its ID and the handle + of the window to which it sends messages. MSDN doesn't say this is + enough, but it works in practice. This allows us to avoid keeping + the notification data around after we show the notification. */ +static void +delete_tray_notification (struct frame *f, int id) +{ + if (FRAME_W32_P (f)) + { + MY_NOTIFYICONDATAW nidw; + + memset (&nidw, 0, sizeof(nidw)); + nidw.hWnd = FRAME_W32_WINDOW (f); + nidw.uID = id; + + if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) + { + /* GetLastError returns meaningless results when + Shell_NotifyIcon fails. */ + DebPrint (("Shell_NotifyIcon DELETE failed\n")); + errno = EINVAL; + return; + } + } + return; +} + +DEFUN ("w32-notification-notify", + Fw32_notification_notify, Sw32_notification_notify, + 0, MANY, 0, + doc: /* Display an MS-Windows tray notification as specified by PARAMS. + +Value is the integer unique ID of the notification that can be used +to remove the notification using `w32-notification-close', which see. +If the function fails, the return value is nil. + +Tray notifications, a.k.a. \"taskbar messages\", are messages that +inform the user about events unrelated to the current user activity, +such as a significant system event, by briefly displaying informative +text in a balloon from an icon in the notification area of the taskbar. + +Parameters in PARAMS are specified as keyword/value pairs. All the +parameters are optional, but if no parameters are specified, the +function will do nothing and return nil. + +The following parameters are supported: + +:icon ICON -- Display ICON in the system tray. If ICON is a string, + it should specify a file name from which to load the + icon; the specified file should be a .ico Windows icon + file. If ICON is not a string, or if this parameter + is not specified, the standard Emacs icon will be used. + +:tip TIP -- Use TIP as the tooltip for the notification. If TIP + is a string, this is the text of a tooltip that will + be shown when the mouse pointer hovers over the tray + icon added by the notification. If TIP is not a + string, or if this parameter is not specified, the + default tooltip text is \"Emacs notification\". The + tooltip text can be up to 127 characters long (63 + on Windows versions before W2K). Longer strings + will be truncated. + +:level LEVEL -- Notification severity level, one of `info', + `warning', or `error'. If given, the value + determines the icon displayed to the left of the + notification title, but only if the `:title' + parameter (see below) is also specified and is a + string. + +:title TITLE -- The title of the notification. If TITLE is a string, + it is displayed in a larger font immediately above + the body text. The title text can be up to 63 + characters long; longer text will be truncated. + +:body BODY -- The body of the notification. If BODY is a string, + it specifies the text of the notification message. + Use embedded newlines to control how the text is + broken into lines. The body text can be up to 255 + characters long, and will be truncated if it's longer. + +Note that versions of Windows before W2K support only `:icon' and `:tip'. +You can pass the other parameters, but they will be ignored on those +old systems. + +There can be at most one active notification at any given time. An +active notification must be removed by calling `w32-notification-close' +before a new one can be shown. + +usage: (w32-notification-notify &rest PARAMS) */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + struct frame *f = SELECTED_FRAME (); + Lisp_Object arg_plist, lres; + EMACS_INT retval; + char *icon, *tip, *title, *msg; + enum NI_Severity severity; + unsigned timeout; + + if (nargs == 0) + return Qnil; + + arg_plist = Flist (nargs, args); + + /* Icon. */ + lres = Fplist_get (arg_plist, QCicon); + if (STRINGP (lres)) + icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil))); + else + icon = ""; + + /* Tip. */ + lres = Fplist_get (arg_plist, QCtip); + if (STRINGP (lres)) + tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); + else + tip = "Emacs notification"; + + /* Severity. */ + lres = Fplist_get (arg_plist, QClevel); + if (NILP (lres)) + severity = Ni_None; + else if (EQ (lres, Qinfo)) + severity = Ni_Info; + else if (EQ (lres, Qwarning)) + severity = Ni_Warn; + else if (EQ (lres, Qerror)) + severity = Ni_Err; + else + severity = Ni_Info; + + /* Title. */ + lres = Fplist_get (arg_plist, QCtitle); + if (STRINGP (lres)) + title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); + else + title = ""; + + /* Notification body text. */ + lres = Fplist_get (arg_plist, QCbody); + if (STRINGP (lres)) + msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); + else + msg = ""; + + /* Do it! */ + retval = add_tray_notification (f, icon, tip, severity, timeout, title, msg); + return (retval < 0 ? Qnil : make_number (retval)); +} + +DEFUN ("w32-notification-close", + Fw32_notification_close, Sw32_notification_close, + 1, 1, 0, + doc: /* Remove the MS-Windows tray notification specified by its ID. */) + (Lisp_Object id) +{ + struct frame *f = SELECTED_FRAME (); + + if (INTEGERP (id)) + delete_tray_notification (f, XINT (id)); + + return Qnil; +} + +#endif /* WINDOWSNT && !HAVE_DBUS */ + /*********************************************************************** Initialization @@ -8828,6 +9286,15 @@ syms_of_w32fns (void) DEFSYM (Qframes, "frames"); DEFSYM (Qtip_frame, "tip-frame"); DEFSYM (Qunicode_sip, "unicode-sip"); +#if defined WINDOWSNT && !defined HAVE_DBUS + DEFSYM (QCicon, ":icon"); + DEFSYM (QCtip, ":tip"); + DEFSYM (QClevel, ":level"); + DEFSYM (Qinfo, "info"); + DEFSYM (Qwarning, "warning"); + DEFSYM (QCtitle, ":title"); + DEFSYM (QCbody, ":body"); +#endif /* Symbols used elsewhere, but only in MS-Windows-specific code. */ DEFSYM (Qgnutls_dll, "gnutls"); @@ -9161,6 +9628,10 @@ This variable has effect only on Windows Vista and later. */); defsubr (&Sw32_window_exists_p); defsubr (&Sw32_battery_status); defsubr (&Sw32__menu_bar_in_use); +#if defined WINDOWSNT && !defined HAVE_DBUS + defsubr (&Sw32_notification_notify); + defsubr (&Sw32_notification_close); +#endif #ifdef WINDOWSNT defsubr (&Sfile_system_info); @@ -9199,6 +9670,12 @@ static PVOID except_addr; /* Stack overflow recovery. */ +/* MinGW headers don't declare this (should be in malloc.h). Also, + the function is not present pre-W2K, so make the call through + a function pointer. */ +typedef int (__cdecl *_resetstkoflw_proc) (void); +static _resetstkoflw_proc resetstkoflw; + /* Re-establish the guard page at stack limit. This is needed because when a stack overflow is detected, Windows removes the guard bit from the guard page, so if we don't re-establish that protection, @@ -9206,12 +9683,14 @@ static PVOID except_addr; void w32_reset_stack_overflow_guard (void) { - /* MinGW headers don't declare this (should be in malloc.h). */ - _CRTIMP int __cdecl _resetstkoflw (void); - + if (resetstkoflw == NULL) + resetstkoflw = + (_resetstkoflw_proc)GetProcAddress (GetModuleHandle ("msvcrt.dll"), + "_resetstkoflw"); /* We ignore the return value. If _resetstkoflw fails, the next stack overflow will crash the program. */ - (void)_resetstkoflw (); + if (resetstkoflw != NULL) + (void)resetstkoflw (); } static void @@ -9442,6 +9921,7 @@ globals_of_w32fns (void) except_addr = 0; #ifndef CYGWIN prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler); + resetstkoflw = NULL; #endif DEFVAR_INT ("w32-ansi-code-page", @@ -9460,10 +9940,6 @@ globals_of_w32fns (void) InitCommonControls (); syms_of_w32uniscribe (); - - /* Needed for recovery from C stack overflows in batch mode. */ - if (noninteractive) - dwMainThreadId = GetCurrentThreadId (); } #ifdef NTGUI_UNICODE