1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-28 10:56:36 +00:00

Added a partial implementation of play-sound-internal for Windows. Fixed the following entry in etc/PROBLEMS: Emacs built on Windows 9x/ME crashes at startup on Windows XP, or Emacs built on XP crashes at startup on Windows 9x/ME.

This commit is contained in:
Ben Key 2002-11-17 22:35:26 +00:00
parent 87a609d3fb
commit f60ae425e9
11 changed files with 661 additions and 141 deletions

View File

@ -1,3 +1,11 @@
2002-11-17 Ben Key <BKey1@tampabay.rr.com>
* nmake.defs: Made changes so that Emacs would link with
WinMM.lib. This change was required for my addition of a Windows
compatible implementation of play-sound-internal.
* gmake.defs: Made changes so that Emacs would link with
WinMM.lib. This change was required for my addition of a Windows
compatible implementation of play-sound-internal.
2002-09-03 Juanma Barranquero <lektu@terra.es> (tiny change)
* emacs.rc: Version updated to 21.3.50. From Peter Runestig

View File

@ -166,6 +166,7 @@ MPR = -lmpr
SHELL32 = -lshell32
USER32 = -luser32
WSOCK32 = -lwsock32
WINMM = -lwinmm
ifdef NOOPT
DEBUG_CFLAGS = -DEMACSDEBUG

View File

@ -123,6 +123,7 @@ MPR = mpr.lib
SHELL32 = shell32.lib
USER32 = user32.lib
WSOCK32 = wsock32.lib
WINMM = winmm.lib
!ifdef NOOPT
DEBUG_CFLAGS = -DEMACSDEBUG

View File

@ -1,3 +1,72 @@
2002-11-17 Ben Key <BKey1@tampabay.rr.com>
* w32.c: Added wrapper functions around the win32 API functions
OpenProcessToken, GetTokenInformation, LookupAccountSid, and
GetSidIdentifierAuthority. These wrapper functions serve two
purposes:
1. They ensure that the wrapped function can never be called
when Emacs is running on an operating system on which they are
not supported (Microsoft Windows 95 / 98 / ME).
2. They call the wrapped functions via function pointers rather
than calling them directly. This avoids taking advantage of the
undocumented fact that although these functions are not supported
in the 9x branch of Microsoft Windows, the functions do exist in
the version of advapi32.dll that is found in the 9x branch of
Microsoft Windows.
This change is part of my fix for the following entry in
etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup on Windows
9x/ME."
* w32.c (init_user_info): Replaced the calls to the win32 API
functions OpenProcessToken, GetTokenInformation, LookupAccountSid,
and GetSidIdentifierAuthority with calls to the newly added
wrapper functions.
This change is part of my fix for the following entry in
etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup on Windows
9x/ME."
* w32.h: Added extern declarations for the following functions:
syms_of_w32term, syms_of_w32fns, syms_of_w32select,
syms_of_w32menu, and void syms_of_fontset.
This change is part of my fix for the following entry in
etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup on Windows
9x/ME."
* w32fns.c (w32_wnd_proc): Added code to reinitialize the
function pointer track_mouse_event_fn in the handler for the
WM_SETFOCUS message.
This change is part of my fix for the following entry in
etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup on Windows
9x/ME."
* w32menu.c (initialize_frame_menubar): Added code to
reinitialize the function pointers set_menu_item_info and
get_menu_item_info.
This change is part of my fix for the following entry in
etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on
Windows XP, or Emacs built on XP crashes at startup on Windows
9x/ME."
* sound.c: Added a partial implementation of play-sound-internal
for Microsoft Windows. Added various #ifdef / #else / #endif
code blocks to separate the code that will compile under
Microsoft Windows from the code that is specific to Gnu/Linux.
Moved several blocks of code around to make this separation of
code into Windows compatible and Gnu/Linux compatible code blocks
easier.
* makefile.w32-in: Made modifications so that sound.c would be
included in the Windows port of Emacs and that it would link with
WinMM.lib.
* s/ms-w32.h: Defined the symbol HAVE_SOUND so that the newly
added support for play-sound-internal under Windows would be
included in the build of Emacs.
2002-11-16 Jason Rumney <jasonr@gnu.org>
* w32fns.c (w32_load_system_font): Don't disable Cleartype.

View File

@ -94,6 +94,7 @@ OBJ1 = $(BLD)/abbrev.$(O) \
$(BLD)/regex.$(O) \
$(BLD)/scroll.$(O) \
$(BLD)/search.$(O) \
$(BLD)/sound.$(O) \
$(BLD)/syntax.$(O) \
$(BLD)/sysdep.$(O) \
$(BLD)/term.$(O) \
@ -133,6 +134,7 @@ LIBS = $(TLIB0) \
$(TLIB1) \
$(TLIBW32) \
$(TLASTLIB) \
$(WINMM) \
$(ADVAPI32) \
$(GDI32) \
$(COMDLG32) \
@ -1094,6 +1096,13 @@ $(BLD)/search.$(O) : \
$(SRC)/w32bdf.h \
$(SRC)/w32gui.h
$(BLD)/sound.$(O) : \
$(SRC)/sound.c \
$(SRC)/lisp.h \
$(SRC)/dispextern.h \
$(SRC)/atimer.h \
$(SRC)/syssignal.h
$(BLD)/strftime.$(O) : \
$(SRC)/strftime.c \
$(EMACS_ROOT)/src/s/ms-w32.h \

View File

@ -217,6 +217,7 @@ Boston, MA 02111-1307, USA. */
#define MAXPATHLEN _MAX_PATH
#endif
#define HAVE_SOUND 1
#define LISP_FLOAT_TYPE 1
#undef HAVE_SYS_SELECT_H

View File

@ -21,10 +21,26 @@ Boston, MA 02111-1307, USA. */
/* Written by Gerd Moellmann <gerd@gnu.org>. Tested with Luigi's
driver on FreeBSD 2.2.7 with a SoundBlaster 16. */
/*
Modified by Ben Key <Bkey1@tampabay.rr.com> to add a partial
implementation of the play-sound specification for Windows.
Notes:
In the Windows implementation of play-sound-internal only the
:file and :volume keywords are supported. The :device keyword,
if present, is ignored. The :data keyword, if present, will
cause an error to be generated.
The Windows implementation of play-sound is implemented via the
Win32 API functions mciSendString, waveOutGetVolume, and
waveOutGetVolume which are exported by Winmm.dll.
*/
#include <config.h>
#if defined HAVE_SOUND
/* BEGIN: Common Includes */
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
@ -34,6 +50,11 @@ Boston, MA 02111-1307, USA. */
#include "atimer.h"
#include <signal.h>
#include "syssignal.h"
/* END: Common Includes */
/* BEGIN: Non Windows Includes */
#ifndef WINDOWSNT
#ifndef MSDOS
#include <sys/ioctl.h>
@ -51,12 +72,55 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_SOUNDCARD_H
#include <soundcard.h>
#endif
/* END: Non Windows Includes */
#else /* WINDOWSNT */
/* BEGIN: Windows Specific Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <windows.h>
#include <mmsystem.h>
/* END: Windows Specific Includes */
#endif /* WINDOWSNT */
/* BEGIN: Common Definitions */
#define abs(X) ((X) < 0 ? -(X) : (X))
/* Symbols. */
extern Lisp_Object QCfile, QCdata;
Lisp_Object QCvolume, QCdevice;
Lisp_Object Qsound;
Lisp_Object Qplay_sound_functions;
/* Indices of attributes in a sound attributes vector. */
enum sound_attr
{
SOUND_FILE,
SOUND_DATA,
SOUND_DEVICE,
SOUND_VOLUME,
SOUND_ATTR_SENTINEL
};
static void sound_perror P_ ((char *));
static void sound_warning P_ ((char *));
static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
/* END: Common Definitions */
/* BEGIN: Non Windows Definitions */
#ifndef WINDOWSNT
#ifndef DEFAULT_SOUND_DEVICE
#define DEFAULT_SOUND_DEVICE "/dev/dsp"
#endif
#define abs(X) ((X) < 0 ? -(X) : (X))
/* Structure forward declarations. */
@ -203,24 +267,6 @@ struct sound
void (* play) P_ ((struct sound *s, struct sound_device *sd));
};
/* Indices of attributes in a sound attributes vector. */
enum sound_attr
{
SOUND_FILE,
SOUND_DATA,
SOUND_DEVICE,
SOUND_VOLUME,
SOUND_ATTR_SENTINEL
};
/* Symbols. */
extern Lisp_Object QCfile, QCdata;
Lisp_Object QCvolume, QCdevice;
Lisp_Object Qsound;
Lisp_Object Qplay_sound_functions;
/* These are set during `play-sound-internal' so that sound_cleanup has
access to them. */
@ -235,9 +281,6 @@ static void vox_close P_ ((struct sound_device *sd));
static void vox_choose_format P_ ((struct sound_device *, struct sound *));
static void vox_init P_ ((struct sound_device *));
static void vox_write P_ ((struct sound_device *, const char *, int));
static void sound_perror P_ ((char *));
static void sound_warning P_ ((char *));
static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
static void find_sound_type P_ ((struct sound *));
static u_int32_t le2hl P_ ((u_int32_t));
static u_int16_t le2hs P_ ((u_int16_t));
@ -251,12 +294,22 @@ static void au_play P_ ((struct sound *, struct sound_device *));
static u_int16_t be2hs P_ ((u_int16_t));
#endif
/* END: Non Windows Definitions */
#else /* WINDOWSNT */
/* BEGIN: Windows Specific Definitions */
static int do_play_sound P_ ((const char *, unsigned long));
/*
END: Windows Specific Definitions */
#endif /* WINDOWSNT */
/***********************************************************************
General
***********************************************************************/
/* BEGIN: Common functions */
/* Like perror, but signals an error. */
static void
@ -327,10 +380,21 @@ parse_sound (sound, attrs)
attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
#ifndef WINDOWSNT
/* File name or data must be specified. */
if (!STRINGP (attrs[SOUND_FILE])
&& !STRINGP (attrs[SOUND_DATA]))
return 0;
#else /* WINDOWSNT */
/*
Data is not supported in Windows. Therefore a
File name MUST be supplied.
*/
if (!STRINGP (attrs[SOUND_FILE]))
{
return 0;
}
#endif /* WINDOWSNT */
/* Volume must be in the range 0..100 or unspecified. */
if (!NILP (attrs[SOUND_VOLUME]))
@ -351,14 +415,23 @@ parse_sound (sound, attrs)
return 0;
}
#ifndef WINDOWSNT
/* Device must be a string or unspecified. */
if (!NILP (attrs[SOUND_DEVICE])
&& !STRINGP (attrs[SOUND_DEVICE]))
return 0;
#endif /* WINDOWSNT */
/*
Since device is ignored in Windows, it does not matter
what it is.
*/
return 1;
}
/* END: Common functions */
/* BEGIN: Non Windows functions */
#ifndef WINDOWSNT
/* Find out the type of the sound file whose file descriptor is FD.
S is the sound file structure to fill in. */
@ -389,105 +462,6 @@ sound_cleanup (arg)
return Qnil;
}
DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
doc: /* Play sound SOUND.
Internal use only, use `play-sound' instead. */)
(sound)
Lisp_Object sound;
{
Lisp_Object attrs[SOUND_ATTR_SENTINEL];
Lisp_Object file;
struct gcpro gcpro1, gcpro2;
struct sound_device sd;
struct sound s;
Lisp_Object args[2];
int count = SPECPDL_INDEX ();
file = Qnil;
GCPRO2 (sound, file);
bzero (&sd, sizeof sd);
bzero (&s, sizeof s);
current_sound_device = &sd;
current_sound = &s;
record_unwind_protect (sound_cleanup, Qnil);
s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
/* Parse the sound specification. Give up if it is invalid. */
if (!parse_sound (sound, attrs))
error ("Invalid sound specification");
if (STRINGP (attrs[SOUND_FILE]))
{
/* Open the sound file. */
s.fd = openp (Fcons (Vdata_directory, Qnil),
attrs[SOUND_FILE], Qnil, &file, Qnil);
if (s.fd < 0)
sound_perror ("Could not open sound file");
/* Read the first bytes from the file. */
s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);
if (s.header_size < 0)
sound_perror ("Invalid sound file header");
}
else
{
s.data = attrs[SOUND_DATA];
s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));
bcopy (SDATA (s.data), s.header, s.header_size);
}
/* Find out the type of sound. Give up if we can't tell. */
find_sound_type (&s);
/* Set up a device. */
if (STRINGP (attrs[SOUND_DEVICE]))
{
int len = SCHARS (attrs[SOUND_DEVICE]);
sd.file = (char *) alloca (len + 1);
strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));
}
if (INTEGERP (attrs[SOUND_VOLUME]))
sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
else if (FLOATP (attrs[SOUND_VOLUME]))
sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
args[0] = Qplay_sound_functions;
args[1] = sound;
Frun_hook_with_args (2, args);
/* There is only one type of device we currently support, the VOX
sound driver. Set up the device interface functions for that
device. */
vox_init (&sd);
/* Open the device. */
sd.open (&sd);
/* Play the sound. */
s.play (&s, &sd);
/* Close the input file, if any. */
if (!STRINGP (s.data))
{
emacs_close (s.fd);
s.fd = -1;
}
/* Close the device. */
sd.close (&sd);
/* Clean up. */
current_sound_device = NULL;
current_sound = NULL;
UNGCPRO;
unbind_to (count, Qnil);
return Qnil;
}
/***********************************************************************
Byte-order Conversion
***********************************************************************/
@ -555,7 +529,6 @@ be2hs (value)
#endif /* 0 */
/***********************************************************************
RIFF-WAVE (*.wav)
***********************************************************************/
@ -645,7 +618,6 @@ wav_play (s, sd)
}
/***********************************************************************
Sun Audio (*.au)
***********************************************************************/
@ -735,7 +707,6 @@ au_play (s, sd)
}
/***********************************************************************
Voxware Driver Interface
***********************************************************************/
@ -909,7 +880,6 @@ vox_init (sd)
sd->write = vox_write;
}
/* Write NBYTES bytes from BUFFER to device SD. */
static void
@ -923,7 +893,231 @@ vox_write (sd, buffer, nbytes)
sound_perror ("Error writing to sound device");
}
/* END: Non Windows functions */
#else /* WINDOWSNT */
/* BEGIN: Windows specific functions */
static int
do_play_sound (psz_file, ui_volume)
const char * psz_file;
unsigned long ui_volume;
{
int i_result=0;
MCIERROR mci_error=0;
char sz_cmd_buf[520]={0};
char sz_ret_buf[520]={0};
MMRESULT mm_result=MMSYSERR_NOERROR;
unsigned long ui_volume_org=0;
BOOL b_reset_volume=FALSE;
memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
sprintf (
sz_cmd_buf,
"open \"%s\" alias GNUEmacs_PlaySound_Device wait",
psz_file);
mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
if (mci_error != 0)
{
sound_warning (
"The open mciSendString command failed to open\n"
"the specified sound file");
i_result=(int)mci_error;
return i_result;
}
if ((ui_volume > 0) && (ui_volume != UINT_MAX))
{
mm_result=waveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, &ui_volume_org);
if (mm_result == MMSYSERR_NOERROR)
{
b_reset_volume=TRUE;
mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume);
if ( mm_result != MMSYSERR_NOERROR)
{
sound_warning (
"waveOutSetVolume failed to set the volume level\n"
"of the WAVE_MAPPER device.\n"
"As a result, the user selected volume level will\n"
"not be used.");
}
}
else
{
sound_warning (
"waveOutGetVolume failed to obtain the original\n"
"volume level of the WAVE_MAPPER device.\n"
"As a result, the user selected volume level will\n"
"not be used.");
}
}
memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait");
mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
if (mci_error != 0)
{
sound_warning (
"The play mciSendString command failed to play the\n"
"opened sound file.");
i_result=(int)mci_error;
}
memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait");
mci_error=mciSendString ( sz_cmd_buf, sz_ret_buf, 520, NULL);
if (b_reset_volume == TRUE)
{
mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume_org);
if (mm_result != MMSYSERR_NOERROR)
{
sound_warning (
"waveOutSetVolume failed to reset the original volume\n"
"level of the WAVE_MAPPER device.");
}
}
return i_result;
}
/* END: Windows specific functions */
#endif /* WINDOWSNT */
DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
doc: /* Play sound SOUND.
Internal use only, use `play-sound' instead.\n */)
(sound)
Lisp_Object sound;
{
Lisp_Object attrs[SOUND_ATTR_SENTINEL];
int count = SPECPDL_INDEX ();
#ifndef WINDOWSNT
Lisp_Object file;
struct gcpro gcpro1, gcpro2;
struct sound_device sd;
struct sound s;
Lisp_Object args[2];
#else /* WINDOWSNT */
int len=0;
Lisp_Object lo_file={0};
char * psz_file=NULL;
unsigned long ui_volume_tmp=UINT_MAX;
unsigned long ui_volume=UINT_MAX;
int i_result=0;
#endif /* WINDOWSNT */
/* Parse the sound specification. Give up if it is invalid. */
if (!parse_sound (sound, attrs))
error ("Invalid sound specification");
#ifndef WINDOWSNT
file = Qnil;
GCPRO2 (sound, file);
bzero (&sd, sizeof sd);
bzero (&s, sizeof s);
current_sound_device = &sd;
current_sound = &s;
record_unwind_protect (sound_cleanup, Qnil);
s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
if (STRINGP (attrs[SOUND_FILE]))
{
/* Open the sound file. */
s.fd = openp (Fcons (Vdata_directory, Qnil),
attrs[SOUND_FILE], Qnil, &file, Qnil);
if (s.fd < 0)
sound_perror ("Could not open sound file");
/* Read the first bytes from the file. */
s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);
if (s.header_size < 0)
sound_perror ("Invalid sound file header");
}
else
{
s.data = attrs[SOUND_DATA];
s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));
bcopy (SDATA (s.data), s.header, s.header_size);
}
/* Find out the type of sound. Give up if we can't tell. */
find_sound_type (&s);
/* Set up a device. */
if (STRINGP (attrs[SOUND_DEVICE]))
{
int len = SCHARS (attrs[SOUND_DEVICE]);
sd.file = (char *) alloca (len + 1);
strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));
}
if (INTEGERP (attrs[SOUND_VOLUME]))
sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
else if (FLOATP (attrs[SOUND_VOLUME]))
sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
args[0] = Qplay_sound_functions;
args[1] = sound;
Frun_hook_with_args (2, args);
/* There is only one type of device we currently support, the VOX
sound driver. Set up the device interface functions for that
device. */
vox_init (&sd);
/* Open the device. */
sd.open (&sd);
/* Play the sound. */
s.play (&s, &sd);
/* Close the input file, if any. */
if (!STRINGP (s.data))
{
emacs_close (s.fd);
s.fd = -1;
}
/* Close the device. */
sd.close (&sd);
/* Clean up. */
current_sound_device = NULL;
current_sound = NULL;
UNGCPRO;
#else /* WINDOWSNT */
lo_file=Fexpand_file_name (attrs[SOUND_FILE], Qnil);
len=XSTRING (lo_file)->size;
psz_file=(char *)alloca (len+1);
strcpy (psz_file, XSTRING (lo_file)->data);
if (INTEGERP (attrs[SOUND_VOLUME]))
{
ui_volume_tmp=XFASTINT (attrs[SOUND_VOLUME]);
}
else if (FLOATP (attrs[SOUND_VOLUME]))
{
ui_volume_tmp=(unsigned long)XFLOAT_DATA (attrs[SOUND_VOLUME])*100;
}
/*
Based on some experiments I have conducted, a value of 100 or less
for the sound volume is much too low. You cannot even hear it.
A value of UINT_MAX indicates that you wish for the sound to played
at the maximum possible volume. A value of UINT_MAX/2 plays the
sound at 50% maximum volume. Therefore the value passed to do_play_sound
(and thus to waveOutSetVolume must be some fraction of UINT_MAX.
The following code adjusts the user specified volume level appropriately.
*/
if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
{
ui_volume=ui_volume_tmp * (UINT_MAX / 100);
}
i_result=do_play_sound (psz_file, ui_volume);
#endif /* WINDOWSNT */
unbind_to (count, Qnil);
return Qnil;
}
/***********************************************************************
Initialization

183
src/w32.c
View File

@ -104,6 +104,171 @@ extern Lisp_Object Vw32_generate_fake_inodes;
extern Lisp_Object Vw32_get_true_file_attributes;
extern Lisp_Object Vw32_num_mouse_buttons;
/*
BEGIN: Wrapper functions around OpenProcessToken
and other functions in advapi32.dll that are only
supported in Windows NT / 2k / XP
*/
/* ** Function pointer typedefs ** */
typedef BOOL (WINAPI * OpenProcessToken_Proc) (
HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle);
typedef BOOL (WINAPI * GetTokenInformation_Proc) (
HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
DWORD TokenInformationLength,
PDWORD ReturnLength);
#ifdef _UNICODE
const char * const LookupAccountSid_Name = "LookupAccountSidW";
#else
const char * const LookupAccountSid_Name = "LookupAccountSidA";
#endif
typedef BOOL (WINAPI * LookupAccountSid_Proc) (
LPCTSTR lpSystemName,
PSID Sid,
LPTSTR Name,
LPDWORD cbName,
LPTSTR DomainName,
LPDWORD cbDomainName,
PSID_NAME_USE peUse);
typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
PSID pSid);
/* ** A utility function ** */
static BOOL is_windows_9x ()
{
BOOL b_ret=0;
OSVERSIONINFO os_ver;
ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx (&os_ver))
{
b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
}
return b_ret;
}
/* ** The wrapper functions ** */
BOOL WINAPI open_process_token (
HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle)
{
OpenProcessToken_Proc 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)
{
return FALSE;
}
return (
pfn_Open_Process_Token (
ProcessHandle,
DesiredAccess,
TokenHandle)
);
}
BOOL WINAPI get_token_information (
HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
DWORD TokenInformationLength,
PDWORD ReturnLength)
{
GetTokenInformation_Proc 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)
{
return FALSE;
}
return (
pfn_Get_Token_Information (
TokenHandle,
TokenInformationClass,
TokenInformation,
TokenInformationLength,
ReturnLength)
);
}
BOOL WINAPI lookup_account_sid (
LPCTSTR lpSystemName,
PSID Sid,
LPTSTR Name,
LPDWORD cbName,
LPTSTR DomainName,
LPDWORD cbDomainName,
PSID_NAME_USE peUse)
{
LookupAccountSid_Proc 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)
{
return FALSE;
}
return (
pfn_Lookup_Account_Sid (
lpSystemName,
Sid,
Name,
cbName,
DomainName,
cbDomainName,
peUse)
);
}
PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
PSID pSid)
{
GetSidIdentifierAuthority_Proc 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)
{
return NULL;
}
return (pfn_Get_Sid_Identifier_Authority (pSid));
}
/*
END: Wrapper functions around OpenProcessToken
and other functions in advapi32.dll that are only
supported in Windows NT / 2k / XP
*/
/* Equivalent of strerror for W32 error codes. */
char *
@ -254,11 +419,15 @@ init_user_info ()
HANDLE token = NULL;
SID_NAME_USE user_type;
if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
&& GetTokenInformation (token, TokenUser,
if (
open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
&& get_token_information (
token, TokenUser,
(PVOID) user_sid, sizeof (user_sid), &trash)
&& LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
domain, &dlength, &user_type))
&& lookup_account_sid (
NULL, *((PSID *) user_sid), name, &length,
domain, &dlength, &user_type)
)
{
strcpy (the_passwd.pw_name, name);
/* Determine a reasonable uid value. */
@ -271,7 +440,7 @@ init_user_info ()
{
SID_IDENTIFIER_AUTHORITY * pSIA;
pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
/* I believe the relative portion is the last 4 bytes (of 6)
with msb first. */
the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
@ -282,12 +451,12 @@ init_user_info ()
the_passwd.pw_uid = the_passwd.pw_uid % 60001;
/* Get group id */
if (GetTokenInformation (token, TokenPrimaryGroup,
if (get_token_information (token, TokenPrimaryGroup,
(PVOID) user_sid, sizeof (user_sid), &trash))
{
SID_IDENTIFIER_AUTHORITY * pSIA;
pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
(pSIA->Value[3] << 16) +
(pSIA->Value[4] << 8) +

View File

@ -124,5 +124,10 @@ extern LPBYTE w32_get_resource (char * key, LPDWORD type);
extern void init_ntproc ();
extern void term_ntproc ();
extern void syms_of_w32term ();
extern void syms_of_w32fns ();
extern void syms_of_w32select ();
extern void syms_of_w32menu ();
extern void syms_of_fontset ();
#endif /* EMACS_W32_H */

View File

@ -283,7 +283,12 @@ static unsigned mouse_move_timer = 0;
/* Window that is tracking the mouse. */
static HWND track_mouse_window;
FARPROC track_mouse_event_fn;
typedef BOOL (WINAPI * TrackMouseEvent_Proc) (
IN OUT LPTRACKMOUSEEVENT lpEventTrack
);
TrackMouseEvent_Proc track_mouse_event_fn=NULL;
/* W95 mousewheel handler */
unsigned int msh_mousewheel = 0;
@ -4929,6 +4934,30 @@ 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);
@ -14843,7 +14872,7 @@ syms_of_w32fns ()
/* 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 = GetProcAddress (user32_lib, "TrackMouseEvent");
track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
track_mouse_window = NULL;
w32_visible_system_caret_hwnd = NULL;

View File

@ -129,8 +129,23 @@ typedef struct _widget_value
static HMENU current_popup_menu;
FARPROC get_menu_item_info;
FARPROC set_menu_item_info;
void syms_of_w32menu ();
typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
IN HMENU,
IN UINT,
IN BOOL,
IN OUT LPMENUITEMINFOA
);
typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
IN HMENU,
IN UINT,
IN BOOL,
IN LPCMENUITEMINFOA
);
GetMenuItemInfoA_Proc get_menu_item_info=NULL;
SetMenuItemInfoA_Proc set_menu_item_info=NULL;
Lisp_Object Vmenu_updating_frame;
@ -1591,6 +1606,26 @@ 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));
@ -2355,13 +2390,12 @@ w32_free_menu_strings (hwnd)
#endif /* HAVE_MENUS */
syms_of_w32menu ()
void syms_of_w32menu ()
{
/* See if Get/SetMenuItemInfo functions are available. */
HMODULE user32 = GetModuleHandle ("user32.dll");
get_menu_item_info = GetProcAddress (user32, "GetMenuItemInfoA");
set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfoA");
get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
staticpro (&menu_items);
menu_items = Qnil;