+2002-12-17 Ben Key <bkey1@tampabay.rr.com>
+ * Revisited my earlier fix for the following entry in
+ etc/PROBLEMS:
+ "Emacs built on Windows 9x/ME crashes at startup on Windows XP,
+ or Emacs builtpart of on XP crashes at startup on Windows 9x/ME."
+
+ These changes were in part based upon suggestions made by Peter
+ 'Luna' Runestig [peter@runestig.com].
+
+ * w32.c (g_b_init_is_windows_9x, g_b_init_open_process_token,
+ g_b_init_get_token_information, g_b_init_lookup_account_sid,
+ g_b_init_get_sid_identifier_authority ): Added several static
+ global variables.
+
+ * w32.c (globals_of_w32): New function. Used to initialize those
+ global variables that must always be initialized on startup even
+ when the global variable initialized is non zero. Its primary
+ purpose at this time is to set the global variables
+ g_b_init_is_windows_9x, g_b_init_open_process_token,
+ g_b_init_get_token_information, g_b_init_lookup_account_sid, and
+ g_b_init_get_sid_identifier_authority to 0 on startup. Called
+ from main.
+
+ * w32.c (is_windows_9x): Perform initialization only if
+ g_b_init_is_windows_9x is equal to 0. On initialization set
+ g_b_init_is_windows_9x equal to 1.
+
+ * w32.c (open_process_token): Perform initialization only if
+ g_b_init_open_process_token is equal to 0. On initialization set
+ g_b_init_open_process_token equal to 1.
+
+ * w32.c (get_token_information): Perform initialization only if
+ g_b_init_get_token_information is equal to 0. On initialization
+ set g_b_init_get_token_information equal to 1.
+
+ * w32.c (lookup_account_sid): Perform initialization only if
+ g_b_init_lookup_account_sid is equal to 0. On initialization
+ set g_b_init_lookup_account_sid equal to 1.
+
+ * w32.c (get_sid_identifier_authority): Perform initialization
+ only if g_b_init_get_sid_identifier_authority is equal to 0. On
+ initialization set g_b_init_get_sid_identifier_authority equal to
+ 1.
+
+ * w32fns.c (globals_of_w32fns): New function. Used to initialize
+ those global variables that must always be initialized on startup
+ even when the global variable initialized is non zero. Its
+ primary purpose at this time is to initialize the global variable
+ track_mouse_event_fn.
+
+ * w32fns.c (w32_wnd_proc): Remove initialization of
+ track_mouse_event_fn from the handler for the WM_SETFOCUS
+ message.
+
+ * w32fns.c (syms_of_w32fns): Call globals_of_w32fns.
+
+ * w32menu.c (globals_of_w32menu): New function. Used to
+ initialize those global variables that must always be initialized
+ on startup even when the global variable initialized is non zero.
+ Its primary purpose at this time is to initialize the global
+ variables get_menu_item_info and set_menu_item_info.
+
+ * w32menu.c (initialize_frame_menubar): Remove initialization of
+ get_menu_item_info and set_menu_item_info.
+
+ * w32menu.c (syms_of_w32menu): Call globals_of_w32menu.
+
+ * w32.h (globals_of_w32, globals_of_w32fns, globals_of_w32menu):
+ Declare them.
+
+ * emacs.c (main): Call globals_of_w32 prior to calling
+ init_environment if WINDOWSNT is defined. Call globals_of_w32fns
+ and globals_of_w32menu if initialized is non zero and HAVE_NTGUI
+ is defined.
+
+ * w32term.c (x_update_window_begin): Fix Windows API error
+ detected by BoundsChecker. Test to determine if
+ w32_system_caret_hwnd is NULL prior to attempting to use
+ SendMessage to send the WM_EMACS_HIDE_CARET message to it.
+
+ * w32term.c (x_update_window_end): Fix Windows API error
+ detected by BoundsChecker. Test to determine if
+ w32_system_caret_hwnd is NULL prior to attempting to use
+ SendMessage to send the WM_EMACS_SHOW_CARET message to it.
+
2002-12-17 Kenichi Handa <handa@m17n.org>
* coding.c (coding_system_require_warning): New variable.
#endif /* MSDOS */
#ifdef WINDOWSNT
+ globals_of_w32 ();
/* Initialize environment from registry settings. */
init_environment (argv);
init_ntproc (); /* must precede init_editfns. */
keys_of_keymap ();
keys_of_minibuf ();
keys_of_window ();
+ }
+ else
+ {
+ /*
+ Initialization that must be done even if the global variable
+ initialized is non zero
+ */
+#ifdef HAVE_NTGUI
+ globals_of_w32fns ();
+ globals_of_w32menu ();
+#endif /* end #ifdef HAVE_NTGUI */
}
if (!noninteractive)
#include "w32heap.h"
#include "systime.h"
+void globals_of_w32 ();
+
extern Lisp_Object Vw32_downcase_file_names;
extern Lisp_Object Vw32_generate_fake_inodes;
extern Lisp_Object Vw32_get_true_file_attributes;
extern Lisp_Object Vw32_num_mouse_buttons;
\f
+/*
+ Initialization states
+ */
+static BOOL g_b_init_is_windows_9x;
+static BOOL g_b_init_open_process_token;
+static BOOL g_b_init_get_token_information;
+static BOOL g_b_init_lookup_account_sid;
+static BOOL g_b_init_get_sid_identifier_authority;
+
/*
BEGIN: Wrapper functions around OpenProcessToken
and other functions in advapi32.dll that are only
/* ** A utility function ** */
static BOOL is_windows_9x ()
{
- BOOL b_ret=0;
+ static BOOL s_b_ret=0;
OSVERSIONINFO os_ver;
- ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
- os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx (&os_ver))
+ if (g_b_init_is_windows_9x == 0)
{
- b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ g_b_init_is_windows_9x = 1;
+ ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
+ os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx (&os_ver))
+ {
+ s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ }
}
- return b_ret;
+ return s_b_ret;
}
/* ** The wrapper functions ** */
DWORD DesiredAccess,
PHANDLE TokenHandle)
{
- OpenProcessToken_Proc pfn_Open_Process_Token = NULL;
+ static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
return FALSE;
}
- hm_advapi32 = LoadLibrary ("Advapi32.dll");
- pfn_Open_Process_Token =
- (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
- if (pfn_Open_Process_Token == NULL)
+ if (g_b_init_open_process_token == 0)
+ {
+ g_b_init_open_process_token = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Open_Process_Token =
+ (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
+ }
+ if (s_pfn_Open_Process_Token == NULL)
{
return FALSE;
}
return (
- pfn_Open_Process_Token (
+ s_pfn_Open_Process_Token (
ProcessHandle,
DesiredAccess,
TokenHandle)
DWORD TokenInformationLength,
PDWORD ReturnLength)
{
- GetTokenInformation_Proc pfn_Get_Token_Information = NULL;
+ static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
return FALSE;
}
- hm_advapi32 = LoadLibrary ("Advapi32.dll");
- pfn_Get_Token_Information =
- (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
- if (pfn_Get_Token_Information == NULL)
+ if (g_b_init_get_token_information == 0)
+ {
+ g_b_init_get_token_information = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Get_Token_Information =
+ (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
+ }
+ if (s_pfn_Get_Token_Information == NULL)
{
return FALSE;
}
return (
- pfn_Get_Token_Information (
+ s_pfn_Get_Token_Information (
TokenHandle,
TokenInformationClass,
TokenInformation,
LPDWORD cbDomainName,
PSID_NAME_USE peUse)
{
- LookupAccountSid_Proc pfn_Lookup_Account_Sid = NULL;
+ static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
return FALSE;
}
- hm_advapi32 = LoadLibrary ("Advapi32.dll");
- pfn_Lookup_Account_Sid =
- (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
- if (pfn_Lookup_Account_Sid == NULL)
+ if (g_b_init_lookup_account_sid == 0)
+ {
+ g_b_init_lookup_account_sid = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Lookup_Account_Sid =
+ (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
+ }
+ if (s_pfn_Lookup_Account_Sid == NULL)
{
return FALSE;
}
return (
- pfn_Lookup_Account_Sid (
+ s_pfn_Lookup_Account_Sid (
lpSystemName,
Sid,
Name,
PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
PSID pSid)
{
- GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority = NULL;
+ static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
return NULL;
}
- hm_advapi32 = LoadLibrary ("Advapi32.dll");
- pfn_Get_Sid_Identifier_Authority =
- (GetSidIdentifierAuthority_Proc) GetProcAddress (
- hm_advapi32, "GetSidIdentifierAuthority");
- if (pfn_Get_Sid_Identifier_Authority == NULL)
+ if (g_b_init_get_sid_identifier_authority == 0)
+ {
+ g_b_init_get_sid_identifier_authority = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Get_Sid_Identifier_Authority =
+ (GetSidIdentifierAuthority_Proc) GetProcAddress (
+ hm_advapi32, "GetSidIdentifierAuthority");
+ }
+ if (s_pfn_Get_Sid_Identifier_Authority == NULL)
{
return NULL;
}
- return (pfn_Get_Sid_Identifier_Authority (pSid));
+ return (s_pfn_Get_Sid_Identifier_Authority (pSid));
}
/*
check_windows_init_file ();
}
+/*
+ globals_of_w32 is used to initialize those global variables that
+ must always be initialized on startup even when the global variable
+ initialized is non zero (see the function main in emacs.c).
+*/
+void globals_of_w32 ()
+{
+ g_b_init_is_windows_9x = 0;
+ g_b_init_open_process_token = 0;
+ g_b_init_get_token_information = 0;
+ g_b_init_lookup_account_sid = 0;
+ g_b_init_get_sid_identifier_authority = 0;
+}
+
/* end of nt.c */
extern void init_ntproc ();
extern void term_ntproc ();
+extern void globals_of_w32 ();
extern void syms_of_w32term ();
extern void syms_of_w32fns ();
+extern void globals_of_w32fns ();
extern void syms_of_w32select ();
extern void syms_of_w32menu ();
+extern void globals_of_w32menu ();
extern void syms_of_fontset ();
#endif /* EMACS_W32_H */
#include <dlgs.h>
#define FILE_NAME_TEXT_FIELD edt1
+void syms_of_w32fns ();
+void globals_of_w32fns ();
+
extern void free_frame_menubar ();
extern void x_compute_fringe_widths P_ ((struct frame *, int));
extern double atof ();
goto dflt;
case WM_SETFOCUS:
- /*
- Reinitialize the function pointer track_mouse_event_fn here.
- This is required even though it is initialized in syms_of_w32fns
- which is called in main (emacs.c).
- Reinitialize the function pointer track_mouse_event_fn here.
- Even though this function pointer is initialized in
- syms_of_w32fns which is called from main (emacs.c),
- we need to initialize it again here in order to prevent
- a crash that occurs in Windows 9x (possibly only when Emacs
- was built on Windows NT / 2000 / XP?) when handling the
- WM_MOUSEMOVE message.
- The crash occurs when attempting to call the Win32 API
- function TrackMouseEvent through the function pointer.
- It appears as if the function pointer that is obtained when
- syms_of_w32fns is called from main is no longer valid
- (possibly due to DLL relocation?).
- To resolve this issue, I have placed a call to reinitialize
- this function pointer here because this message gets received
- when the Emacs window gains focus.
- */
- track_mouse_event_fn =
- (TrackMouseEvent_Proc) GetProcAddress (
- GetModuleHandle ("user32.dll"),
- "TrackMouseEvent");
dpyinfo->faked_key = 0;
reset_modifiers ();
register_hot_keys (hwnd);
void
syms_of_w32fns ()
{
- HMODULE user32_lib = GetModuleHandle ("user32.dll");
-
- /* This is zero if not using MS-Windows. */
+ globals_of_w32fns ();
+ /* This is zero if not using MS-Windows. */
w32_in_use = 0;
-
- /* TrackMouseEvent not available in all versions of Windows, so must load
- it dynamically. Do it once, here, instead of every time it is used. */
- track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
track_mouse_window = NULL;
w32_visible_system_caret_hwnd = NULL;
defsubr (&Sx_file_dialog);
}
+
+/*
+ globals_of_w32fns is used to initialize those global variables that
+ must always be initialized on startup even when the global variable
+ initialized is non zero (see the function main in emacs.c).
+ globals_of_w32fns is called from syms_of_w32fns when the global
+ variable initialized is 0 and directly from main when initialized
+ is non zero.
+ */
+void globals_of_w32fns ()
+{
+ HMODULE user32_lib = GetModuleHandle ("user32.dll");
+ /*
+ TrackMouseEvent not available in all versions of Windows, so must load
+ it dynamically. Do it once, here, instead of every time it is used.
+ */
+ track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
+}
+
void
init_xfns ()
{
static HMENU current_popup_menu;
void syms_of_w32menu ();
+void globals_of_w32menu ();
typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
IN HMENU,
initialize_frame_menubar (f)
FRAME_PTR f;
{
- HMODULE user32 = GetModuleHandle ("user32.dll");
- /*
- Reinitialize the function pointers set_menu_item_info and
- get_menu_item_info here.
- Even though these function pointers are initialized in
- syms_of_w32menu which is called from main (emacs.c),
- we need to initialize them again here in order to prevent
- a crash that occurs in Windows 9x (possibly only when Emacs
- was built on Windows NT / 2000 / XP?) in add_menu_item.
- The crash occurs when attempting to call the Win32 API
- function SetMenuItemInfo through the function pointer.
- It appears as if the function pointer that is obtained when
- syms_of_w32menu is called from main is no longer valid
- (possibly due to DLL relocation?).
- To resolve this issue, I have placed calls to reinitialize
- these function pointers here because this function is the
- entry point for menu creation.
- */
- get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
- set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
void syms_of_w32menu ()
{
- /* See if Get/SetMenuItemInfo functions are available. */
- HMODULE user32 = GetModuleHandle ("user32.dll");
- get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
- set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
-
+ globals_of_w32menu ();
staticpro (&menu_items);
menu_items = Qnil;
defsubr (&Sx_popup_dialog);
#endif
}
+
+/*
+ globals_of_w32menu is used to initialize those global variables that
+ must always be initialized on startup even when the global variable
+ initialized is non zero (see the function main in emacs.c).
+ globals_of_w32menu is called from syms_of_w32menu when the global
+ variable initialized is 0 and directly from main when initialized
+ is non zero.
+ */
+void globals_of_w32menu ()
+{
+ /* See if Get/SetMenuItemInfo functions are available. */
+ HMODULE user32 = GetModuleHandle ("user32.dll");
+ get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
+ set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
+}
struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
/* Hide the system caret during an update. */
- if (w32_use_visible_system_caret)
- SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
+ if (w32_use_visible_system_caret && w32_system_caret_hwnd)
+ {
+ SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
+ }
updated_window = w;
set_output_cursor (&w->cursor);
/* Unhide the caret. This won't actually show the cursor, unless it
was visible before the corresponding call to HideCaret in
x_update_window_begin. */
- if (w32_use_visible_system_caret)
- SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+ if (w32_use_visible_system_caret && w32_system_caret_hwnd)
+ {
+ SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+ }
updated_window = NULL;
}