changeset 48888:f0df5f687c15

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.' Fixed several Windows API errors detected by BoundsChecker
author Ben Key <bkey1@tampabay.rr.com>
date Wed, 18 Dec 2002 06:16:28 +0000
parents e846f8d1619c
children ec1a96fb72d6
files src/ChangeLog src/emacs.c src/w32.c src/w32.h src/w32fns.c src/w32menu.c src/w32term.c
diffstat 7 files changed, 227 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/ChangeLog	Wed Dec 18 06:16:28 2002 +0000
@@ -1,3 +1,88 @@
+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.
--- a/src/emacs.c	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/emacs.c	Wed Dec 18 06:16:28 2002 +0000
@@ -1375,6 +1375,7 @@
 #endif /* MSDOS */
 
 #ifdef WINDOWSNT
+  globals_of_w32 ();
   /* Initialize environment from registry settings.  */
   init_environment (argv);
   init_ntproc ();	/* must precede init_editfns.  */
@@ -1541,6 +1542,17 @@
       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)
     {
--- a/src/w32.c	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/w32.c	Wed Dec 18 06:16:28 2002 +0000
@@ -99,6 +99,8 @@
 #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;
@@ -106,6 +108,15 @@
 
 
 /*
+	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
   supported in Windows NT / 2k / XP
@@ -140,15 +151,19 @@
   /* ** 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 ** */
@@ -158,21 +173,25 @@
     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)
@@ -186,21 +205,25 @@
     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,
@@ -218,21 +241,25 @@
     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,
@@ -246,21 +273,25 @@
 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));
 }
 
 /*
@@ -3909,4 +3940,18 @@
   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 */
--- a/src/w32.h	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/w32.h	Wed Dec 18 06:16:28 2002 +0000
@@ -124,10 +124,13 @@
 
 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 */
--- a/src/w32fns.c	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/w32fns.c	Wed Dec 18 06:16:28 2002 +0000
@@ -55,6 +55,9 @@
 #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 ();
@@ -4934,30 +4937,6 @@
       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);
@@ -14906,14 +14885,9 @@
 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;
@@ -15496,7 +15470,26 @@
   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 ()
 {
--- a/src/w32menu.c	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/w32menu.c	Wed Dec 18 06:16:28 2002 +0000
@@ -130,6 +130,7 @@
 static HMENU current_popup_menu;
 
 void syms_of_w32menu ();
+void globals_of_w32menu ();
 
 typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
     IN HMENU,
@@ -1606,26 +1607,6 @@
 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));
@@ -2392,11 +2373,7 @@
 
 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;
 
@@ -2415,3 +2392,19 @@
   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");
+}
--- a/src/w32term.c	Wed Dec 18 05:16:09 2002 +0000
+++ b/src/w32term.c	Wed Dec 18 06:16:28 2002 +0000
@@ -603,8 +603,10 @@
   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);
@@ -730,8 +732,10 @@
   /* 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;
 }