# HG changeset patch # User Ben Key # Date 1040192188 0 # Node ID f0df5f687c15a533e6ec0166d7e0ef18808e82e1 # Parent e846f8d1619c2a82c4dbc2724188379b5e07772b 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 diff -r e846f8d1619c -r f0df5f687c15 src/ChangeLog --- 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 + * 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 * coding.c (coding_system_require_warning): New variable. diff -r e846f8d1619c -r f0df5f687c15 src/emacs.c --- 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) { diff -r e846f8d1619c -r f0df5f687c15 src/w32.c --- 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 */ diff -r e846f8d1619c -r f0df5f687c15 src/w32.h --- 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 */ diff -r e846f8d1619c -r f0df5f687c15 src/w32fns.c --- 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 #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 () { diff -r e846f8d1619c -r f0df5f687c15 src/w32menu.c --- 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"); +} diff -r e846f8d1619c -r f0df5f687c15 src/w32term.c --- 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; }