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

This commit is contained in:
Ben Key 2002-12-18 06:16:28 +00:00
parent 2504650303
commit 9785d95b98
7 changed files with 226 additions and 91 deletions

View file

@ -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.

View file

@ -1375,6 +1375,7 @@ main (argc, argv
#endif /* MSDOS */
#ifdef WINDOWSNT
globals_of_w32 ();
/* Initialize environment from registry settings. */
init_environment (argv);
init_ntproc (); /* must precede init_editfns. */
@ -1540,6 +1541,17 @@ main (argc, argv
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)

107
src/w32.c
View file

@ -99,12 +99,23 @@ Boston, MA 02111-1307, USA.
#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;
/*
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
@ -140,15 +151,19 @@ typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
/* ** 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 @@ BOOL WINAPI open_process_token (
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 @@ BOOL WINAPI get_token_information (
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 @@ BOOL WINAPI lookup_account_sid (
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 @@ BOOL WINAPI lookup_account_sid (
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 @@ init_ntproc ()
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 */

View file

@ -124,10 +124,13 @@ extern LPBYTE w32_get_resource (char * key, LPDWORD type);
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 */

View file

@ -55,6 +55,9 @@ Boston, MA 02111-1307, USA. */
#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 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
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 @@ If the underlying system call fails, value is nil. */)
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 @@ versions of Windows) characters. */);
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 ()
{

View file

@ -130,6 +130,7 @@ typedef struct _widget_value
static HMENU current_popup_menu;
void syms_of_w32menu ();
void globals_of_w32menu ();
typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
IN HMENU,
@ -1606,26 +1607,6 @@ void
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 @@ w32_free_menu_strings (hwnd)
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 @@ The enable predicate for a menu command should check this variable. */);
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");
}

View file

@ -603,8 +603,10 @@ x_update_window_begin (w)
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 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
/* 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;
}