diff options
| author | Ben Key | 2002-11-17 22:35:26 +0000 |
|---|---|---|
| committer | Ben Key | 2002-11-17 22:35:26 +0000 |
| commit | f60ae425e9095d06f4ad06e5b277903606c25dca (patch) | |
| tree | 5cf0be810c07412c8e145c431327f53df9e8ad89 /src | |
| parent | 87a609d3fb43ab67d043ae2462ac5aacff9381c1 (diff) | |
| download | emacs-f60ae425e9095d06f4ad06e5b277903606c25dca.tar.gz emacs-f60ae425e9095d06f4ad06e5b277903606c25dca.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 69 | ||||
| -rw-r--r-- | src/makefile.w32-in | 9 | ||||
| -rw-r--r-- | src/s/ms-w32.h | 1 | ||||
| -rw-r--r-- | src/sound.c | 446 | ||||
| -rw-r--r-- | src/w32.c | 183 | ||||
| -rw-r--r-- | src/w32.h | 5 | ||||
| -rw-r--r-- | src/w32fns.c | 33 | ||||
| -rw-r--r-- | src/w32menu.c | 46 |
8 files changed, 651 insertions, 141 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index ad38b61b789..b174d8d6ab1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,72 @@ | |||
| 1 | 2002-11-17 Ben Key <BKey1@tampabay.rr.com> | ||
| 2 | * w32.c: Added wrapper functions around the win32 API functions | ||
| 3 | OpenProcessToken, GetTokenInformation, LookupAccountSid, and | ||
| 4 | GetSidIdentifierAuthority. These wrapper functions serve two | ||
| 5 | purposes: | ||
| 6 | 1. They ensure that the wrapped function can never be called | ||
| 7 | when Emacs is running on an operating system on which they are | ||
| 8 | not supported (Microsoft Windows 95 / 98 / ME). | ||
| 9 | 2. They call the wrapped functions via function pointers rather | ||
| 10 | than calling them directly. This avoids taking advantage of the | ||
| 11 | undocumented fact that although these functions are not supported | ||
| 12 | in the 9x branch of Microsoft Windows, the functions do exist in | ||
| 13 | the version of advapi32.dll that is found in the 9x branch of | ||
| 14 | Microsoft Windows. | ||
| 15 | This change is part of my fix for the following entry in | ||
| 16 | etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on | ||
| 17 | Windows XP, or Emacs built on XP crashes at startup on Windows | ||
| 18 | 9x/ME." | ||
| 19 | |||
| 20 | * w32.c (init_user_info): Replaced the calls to the win32 API | ||
| 21 | functions OpenProcessToken, GetTokenInformation, LookupAccountSid, | ||
| 22 | and GetSidIdentifierAuthority with calls to the newly added | ||
| 23 | wrapper functions. | ||
| 24 | This change is part of my fix for the following entry in | ||
| 25 | etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on | ||
| 26 | Windows XP, or Emacs built on XP crashes at startup on Windows | ||
| 27 | 9x/ME." | ||
| 28 | |||
| 29 | * w32.h: Added extern declarations for the following functions: | ||
| 30 | syms_of_w32term, syms_of_w32fns, syms_of_w32select, | ||
| 31 | syms_of_w32menu, and void syms_of_fontset. | ||
| 32 | This change is part of my fix for the following entry in | ||
| 33 | etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on | ||
| 34 | Windows XP, or Emacs built on XP crashes at startup on Windows | ||
| 35 | 9x/ME." | ||
| 36 | |||
| 37 | * w32fns.c (w32_wnd_proc): Added code to reinitialize the | ||
| 38 | function pointer track_mouse_event_fn in the handler for the | ||
| 39 | WM_SETFOCUS message. | ||
| 40 | This change is part of my fix for the following entry in | ||
| 41 | etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on | ||
| 42 | Windows XP, or Emacs built on XP crashes at startup on Windows | ||
| 43 | 9x/ME." | ||
| 44 | |||
| 45 | * w32menu.c (initialize_frame_menubar): Added code to | ||
| 46 | reinitialize the function pointers set_menu_item_info and | ||
| 47 | get_menu_item_info. | ||
| 48 | This change is part of my fix for the following entry in | ||
| 49 | etc/PROBLEMS: "Emacs built on Windows 9x/ME crashes at startup on | ||
| 50 | Windows XP, or Emacs built on XP crashes at startup on Windows | ||
| 51 | 9x/ME." | ||
| 52 | |||
| 53 | * sound.c: Added a partial implementation of play-sound-internal | ||
| 54 | for Microsoft Windows. Added various #ifdef / #else / #endif | ||
| 55 | code blocks to separate the code that will compile under | ||
| 56 | Microsoft Windows from the code that is specific to Gnu/Linux. | ||
| 57 | Moved several blocks of code around to make this separation of | ||
| 58 | code into Windows compatible and Gnu/Linux compatible code blocks | ||
| 59 | easier. | ||
| 60 | |||
| 61 | * makefile.w32-in: Made modifications so that sound.c would be | ||
| 62 | included in the Windows port of Emacs and that it would link with | ||
| 63 | WinMM.lib. | ||
| 64 | |||
| 65 | * s/ms-w32.h: Defined the symbol HAVE_SOUND so that the newly | ||
| 66 | added support for play-sound-internal under Windows would be | ||
| 67 | included in the build of Emacs. | ||
| 68 | |||
| 69 | |||
| 1 | 2002-11-16 Jason Rumney <jasonr@gnu.org> | 70 | 2002-11-16 Jason Rumney <jasonr@gnu.org> |
| 2 | 71 | ||
| 3 | * w32fns.c (w32_load_system_font): Don't disable Cleartype. | 72 | * w32fns.c (w32_load_system_font): Don't disable Cleartype. |
diff --git a/src/makefile.w32-in b/src/makefile.w32-in index 8c56c25667a..0a11245df0e 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in | |||
| @@ -94,6 +94,7 @@ OBJ1 = $(BLD)/abbrev.$(O) \ | |||
| 94 | $(BLD)/regex.$(O) \ | 94 | $(BLD)/regex.$(O) \ |
| 95 | $(BLD)/scroll.$(O) \ | 95 | $(BLD)/scroll.$(O) \ |
| 96 | $(BLD)/search.$(O) \ | 96 | $(BLD)/search.$(O) \ |
| 97 | $(BLD)/sound.$(O) \ | ||
| 97 | $(BLD)/syntax.$(O) \ | 98 | $(BLD)/syntax.$(O) \ |
| 98 | $(BLD)/sysdep.$(O) \ | 99 | $(BLD)/sysdep.$(O) \ |
| 99 | $(BLD)/term.$(O) \ | 100 | $(BLD)/term.$(O) \ |
| @@ -133,6 +134,7 @@ LIBS = $(TLIB0) \ | |||
| 133 | $(TLIB1) \ | 134 | $(TLIB1) \ |
| 134 | $(TLIBW32) \ | 135 | $(TLIBW32) \ |
| 135 | $(TLASTLIB) \ | 136 | $(TLASTLIB) \ |
| 137 | $(WINMM) \ | ||
| 136 | $(ADVAPI32) \ | 138 | $(ADVAPI32) \ |
| 137 | $(GDI32) \ | 139 | $(GDI32) \ |
| 138 | $(COMDLG32) \ | 140 | $(COMDLG32) \ |
| @@ -1094,6 +1096,13 @@ $(BLD)/search.$(O) : \ | |||
| 1094 | $(SRC)/w32bdf.h \ | 1096 | $(SRC)/w32bdf.h \ |
| 1095 | $(SRC)/w32gui.h | 1097 | $(SRC)/w32gui.h |
| 1096 | 1098 | ||
| 1099 | $(BLD)/sound.$(O) : \ | ||
| 1100 | $(SRC)/sound.c \ | ||
| 1101 | $(SRC)/lisp.h \ | ||
| 1102 | $(SRC)/dispextern.h \ | ||
| 1103 | $(SRC)/atimer.h \ | ||
| 1104 | $(SRC)/syssignal.h | ||
| 1105 | |||
| 1097 | $(BLD)/strftime.$(O) : \ | 1106 | $(BLD)/strftime.$(O) : \ |
| 1098 | $(SRC)/strftime.c \ | 1107 | $(SRC)/strftime.c \ |
| 1099 | $(EMACS_ROOT)/src/s/ms-w32.h \ | 1108 | $(EMACS_ROOT)/src/s/ms-w32.h \ |
diff --git a/src/s/ms-w32.h b/src/s/ms-w32.h index 0585c22d0fe..51f3e9ddb25 100644 --- a/src/s/ms-w32.h +++ b/src/s/ms-w32.h | |||
| @@ -217,6 +217,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 217 | #define MAXPATHLEN _MAX_PATH | 217 | #define MAXPATHLEN _MAX_PATH |
| 218 | #endif | 218 | #endif |
| 219 | 219 | ||
| 220 | #define HAVE_SOUND 1 | ||
| 220 | #define LISP_FLOAT_TYPE 1 | 221 | #define LISP_FLOAT_TYPE 1 |
| 221 | 222 | ||
| 222 | #undef HAVE_SYS_SELECT_H | 223 | #undef HAVE_SYS_SELECT_H |
diff --git a/src/sound.c b/src/sound.c index a9336a04af9..185ba864be7 100644 --- a/src/sound.c +++ b/src/sound.c | |||
| @@ -21,10 +21,26 @@ Boston, MA 02111-1307, USA. */ | |||
| 21 | /* Written by Gerd Moellmann <gerd@gnu.org>. Tested with Luigi's | 21 | /* Written by Gerd Moellmann <gerd@gnu.org>. Tested with Luigi's |
| 22 | driver on FreeBSD 2.2.7 with a SoundBlaster 16. */ | 22 | driver on FreeBSD 2.2.7 with a SoundBlaster 16. */ |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | Modified by Ben Key <Bkey1@tampabay.rr.com> to add a partial | ||
| 26 | implementation of the play-sound specification for Windows. | ||
| 27 | |||
| 28 | Notes: | ||
| 29 | In the Windows implementation of play-sound-internal only the | ||
| 30 | :file and :volume keywords are supported. The :device keyword, | ||
| 31 | if present, is ignored. The :data keyword, if present, will | ||
| 32 | cause an error to be generated. | ||
| 33 | |||
| 34 | The Windows implementation of play-sound is implemented via the | ||
| 35 | Win32 API functions mciSendString, waveOutGetVolume, and | ||
| 36 | waveOutGetVolume which are exported by Winmm.dll. | ||
| 37 | */ | ||
| 38 | |||
| 24 | #include <config.h> | 39 | #include <config.h> |
| 25 | 40 | ||
| 26 | #if defined HAVE_SOUND | 41 | #if defined HAVE_SOUND |
| 27 | 42 | ||
| 43 | /* BEGIN: Common Includes */ | ||
| 28 | #include <fcntl.h> | 44 | #include <fcntl.h> |
| 29 | #include <unistd.h> | 45 | #include <unistd.h> |
| 30 | #include <sys/types.h> | 46 | #include <sys/types.h> |
| @@ -34,6 +50,11 @@ Boston, MA 02111-1307, USA. */ | |||
| 34 | #include "atimer.h" | 50 | #include "atimer.h" |
| 35 | #include <signal.h> | 51 | #include <signal.h> |
| 36 | #include "syssignal.h" | 52 | #include "syssignal.h" |
| 53 | /* END: Common Includes */ | ||
| 54 | |||
| 55 | |||
| 56 | /* BEGIN: Non Windows Includes */ | ||
| 57 | #ifndef WINDOWSNT | ||
| 37 | 58 | ||
| 38 | #ifndef MSDOS | 59 | #ifndef MSDOS |
| 39 | #include <sys/ioctl.h> | 60 | #include <sys/ioctl.h> |
| @@ -51,12 +72,55 @@ Boston, MA 02111-1307, USA. */ | |||
| 51 | #ifdef HAVE_SOUNDCARD_H | 72 | #ifdef HAVE_SOUNDCARD_H |
| 52 | #include <soundcard.h> | 73 | #include <soundcard.h> |
| 53 | #endif | 74 | #endif |
| 75 | /* END: Non Windows Includes */ | ||
| 76 | |||
| 77 | #else /* WINDOWSNT */ | ||
| 78 | |||
| 79 | /* BEGIN: Windows Specific Includes */ | ||
| 80 | #include <stdio.h> | ||
| 81 | #include <stdlib.h> | ||
| 82 | #include <string.h> | ||
| 83 | #include <limits.h> | ||
| 84 | #include <windows.h> | ||
| 85 | #include <mmsystem.h> | ||
| 86 | /* END: Windows Specific Includes */ | ||
| 87 | |||
| 88 | #endif /* WINDOWSNT */ | ||
| 89 | |||
| 90 | /* BEGIN: Common Definitions */ | ||
| 91 | #define abs(X) ((X) < 0 ? -(X) : (X)) | ||
| 92 | |||
| 93 | /* Symbols. */ | ||
| 94 | |||
| 95 | extern Lisp_Object QCfile, QCdata; | ||
| 96 | Lisp_Object QCvolume, QCdevice; | ||
| 97 | Lisp_Object Qsound; | ||
| 98 | Lisp_Object Qplay_sound_functions; | ||
| 99 | |||
| 100 | /* Indices of attributes in a sound attributes vector. */ | ||
| 101 | |||
| 102 | enum sound_attr | ||
| 103 | { | ||
| 104 | SOUND_FILE, | ||
| 105 | SOUND_DATA, | ||
| 106 | SOUND_DEVICE, | ||
| 107 | SOUND_VOLUME, | ||
| 108 | SOUND_ATTR_SENTINEL | ||
| 109 | }; | ||
| 110 | |||
| 111 | static void sound_perror P_ ((char *)); | ||
| 112 | static void sound_warning P_ ((char *)); | ||
| 113 | static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); | ||
| 114 | |||
| 115 | /* END: Common Definitions */ | ||
| 116 | |||
| 117 | /* BEGIN: Non Windows Definitions */ | ||
| 118 | #ifndef WINDOWSNT | ||
| 54 | 119 | ||
| 55 | #ifndef DEFAULT_SOUND_DEVICE | 120 | #ifndef DEFAULT_SOUND_DEVICE |
| 56 | #define DEFAULT_SOUND_DEVICE "/dev/dsp" | 121 | #define DEFAULT_SOUND_DEVICE "/dev/dsp" |
| 57 | #endif | 122 | #endif |
| 58 | 123 | ||
| 59 | #define abs(X) ((X) < 0 ? -(X) : (X)) | ||
| 60 | 124 | ||
| 61 | /* Structure forward declarations. */ | 125 | /* Structure forward declarations. */ |
| 62 | 126 | ||
| @@ -203,24 +267,6 @@ struct sound | |||
| 203 | void (* play) P_ ((struct sound *s, struct sound_device *sd)); | 267 | void (* play) P_ ((struct sound *s, struct sound_device *sd)); |
| 204 | }; | 268 | }; |
| 205 | 269 | ||
| 206 | /* Indices of attributes in a sound attributes vector. */ | ||
| 207 | |||
| 208 | enum sound_attr | ||
| 209 | { | ||
| 210 | SOUND_FILE, | ||
| 211 | SOUND_DATA, | ||
| 212 | SOUND_DEVICE, | ||
| 213 | SOUND_VOLUME, | ||
| 214 | SOUND_ATTR_SENTINEL | ||
| 215 | }; | ||
| 216 | |||
| 217 | /* Symbols. */ | ||
| 218 | |||
| 219 | extern Lisp_Object QCfile, QCdata; | ||
| 220 | Lisp_Object QCvolume, QCdevice; | ||
| 221 | Lisp_Object Qsound; | ||
| 222 | Lisp_Object Qplay_sound_functions; | ||
| 223 | |||
| 224 | /* These are set during `play-sound-internal' so that sound_cleanup has | 270 | /* These are set during `play-sound-internal' so that sound_cleanup has |
| 225 | access to them. */ | 271 | access to them. */ |
| 226 | 272 | ||
| @@ -235,9 +281,6 @@ static void vox_close P_ ((struct sound_device *sd)); | |||
| 235 | static void vox_choose_format P_ ((struct sound_device *, struct sound *)); | 281 | static void vox_choose_format P_ ((struct sound_device *, struct sound *)); |
| 236 | static void vox_init P_ ((struct sound_device *)); | 282 | static void vox_init P_ ((struct sound_device *)); |
| 237 | static void vox_write P_ ((struct sound_device *, const char *, int)); | 283 | static void vox_write P_ ((struct sound_device *, const char *, int)); |
| 238 | static void sound_perror P_ ((char *)); | ||
| 239 | static void sound_warning P_ ((char *)); | ||
| 240 | static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); | ||
| 241 | static void find_sound_type P_ ((struct sound *)); | 284 | static void find_sound_type P_ ((struct sound *)); |
| 242 | static u_int32_t le2hl P_ ((u_int32_t)); | 285 | static u_int32_t le2hl P_ ((u_int32_t)); |
| 243 | static u_int16_t le2hs P_ ((u_int16_t)); | 286 | static u_int16_t le2hs P_ ((u_int16_t)); |
| @@ -251,12 +294,22 @@ static void au_play P_ ((struct sound *, struct sound_device *)); | |||
| 251 | static u_int16_t be2hs P_ ((u_int16_t)); | 294 | static u_int16_t be2hs P_ ((u_int16_t)); |
| 252 | #endif | 295 | #endif |
| 253 | 296 | ||
| 297 | /* END: Non Windows Definitions */ | ||
| 298 | #else /* WINDOWSNT */ | ||
| 299 | |||
| 300 | /* BEGIN: Windows Specific Definitions */ | ||
| 301 | static int do_play_sound P_ ((const char *, unsigned long)); | ||
| 302 | /* | ||
| 303 | END: Windows Specific Definitions */ | ||
| 304 | #endif /* WINDOWSNT */ | ||
| 254 | 305 | ||
| 255 | 306 | ||
| 256 | /*********************************************************************** | 307 | /*********************************************************************** |
| 257 | General | 308 | General |
| 258 | ***********************************************************************/ | 309 | ***********************************************************************/ |
| 259 | 310 | ||
| 311 | /* BEGIN: Common functions */ | ||
| 312 | |||
| 260 | /* Like perror, but signals an error. */ | 313 | /* Like perror, but signals an error. */ |
| 261 | 314 | ||
| 262 | static void | 315 | static void |
| @@ -327,10 +380,21 @@ parse_sound (sound, attrs) | |||
| 327 | attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice); | 380 | attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice); |
| 328 | attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume); | 381 | attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume); |
| 329 | 382 | ||
| 383 | #ifndef WINDOWSNT | ||
| 330 | /* File name or data must be specified. */ | 384 | /* File name or data must be specified. */ |
| 331 | if (!STRINGP (attrs[SOUND_FILE]) | 385 | if (!STRINGP (attrs[SOUND_FILE]) |
| 332 | && !STRINGP (attrs[SOUND_DATA])) | 386 | && !STRINGP (attrs[SOUND_DATA])) |
| 333 | return 0; | 387 | return 0; |
| 388 | #else /* WINDOWSNT */ | ||
| 389 | /* | ||
| 390 | Data is not supported in Windows. Therefore a | ||
| 391 | File name MUST be supplied. | ||
| 392 | */ | ||
| 393 | if (!STRINGP (attrs[SOUND_FILE])) | ||
| 394 | { | ||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | #endif /* WINDOWSNT */ | ||
| 334 | 398 | ||
| 335 | /* Volume must be in the range 0..100 or unspecified. */ | 399 | /* Volume must be in the range 0..100 or unspecified. */ |
| 336 | if (!NILP (attrs[SOUND_VOLUME])) | 400 | if (!NILP (attrs[SOUND_VOLUME])) |
| @@ -351,14 +415,23 @@ parse_sound (sound, attrs) | |||
| 351 | return 0; | 415 | return 0; |
| 352 | } | 416 | } |
| 353 | 417 | ||
| 418 | #ifndef WINDOWSNT | ||
| 354 | /* Device must be a string or unspecified. */ | 419 | /* Device must be a string or unspecified. */ |
| 355 | if (!NILP (attrs[SOUND_DEVICE]) | 420 | if (!NILP (attrs[SOUND_DEVICE]) |
| 356 | && !STRINGP (attrs[SOUND_DEVICE])) | 421 | && !STRINGP (attrs[SOUND_DEVICE])) |
| 357 | return 0; | 422 | return 0; |
| 358 | 423 | #endif /* WINDOWSNT */ | |
| 424 | /* | ||
| 425 | Since device is ignored in Windows, it does not matter | ||
| 426 | what it is. | ||
| 427 | */ | ||
| 359 | return 1; | 428 | return 1; |
| 360 | } | 429 | } |
| 361 | 430 | ||
| 431 | /* END: Common functions */ | ||
| 432 | |||
| 433 | /* BEGIN: Non Windows functions */ | ||
| 434 | #ifndef WINDOWSNT | ||
| 362 | 435 | ||
| 363 | /* Find out the type of the sound file whose file descriptor is FD. | 436 | /* Find out the type of the sound file whose file descriptor is FD. |
| 364 | S is the sound file structure to fill in. */ | 437 | S is the sound file structure to fill in. */ |
| @@ -389,105 +462,6 @@ sound_cleanup (arg) | |||
| 389 | return Qnil; | 462 | return Qnil; |
| 390 | } | 463 | } |
| 391 | 464 | ||
| 392 | |||
| 393 | DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0, | ||
| 394 | doc: /* Play sound SOUND. | ||
| 395 | |||
| 396 | Internal use only, use `play-sound' instead. */) | ||
| 397 | (sound) | ||
| 398 | Lisp_Object sound; | ||
| 399 | { | ||
| 400 | Lisp_Object attrs[SOUND_ATTR_SENTINEL]; | ||
| 401 | Lisp_Object file; | ||
| 402 | struct gcpro gcpro1, gcpro2; | ||
| 403 | struct sound_device sd; | ||
| 404 | struct sound s; | ||
| 405 | Lisp_Object args[2]; | ||
| 406 | int count = SPECPDL_INDEX (); | ||
| 407 | |||
| 408 | file = Qnil; | ||
| 409 | GCPRO2 (sound, file); | ||
| 410 | bzero (&sd, sizeof sd); | ||
| 411 | bzero (&s, sizeof s); | ||
| 412 | current_sound_device = &sd; | ||
| 413 | current_sound = &s; | ||
| 414 | record_unwind_protect (sound_cleanup, Qnil); | ||
| 415 | s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES); | ||
| 416 | |||
| 417 | /* Parse the sound specification. Give up if it is invalid. */ | ||
| 418 | if (!parse_sound (sound, attrs)) | ||
| 419 | error ("Invalid sound specification"); | ||
| 420 | |||
| 421 | if (STRINGP (attrs[SOUND_FILE])) | ||
| 422 | { | ||
| 423 | /* Open the sound file. */ | ||
| 424 | s.fd = openp (Fcons (Vdata_directory, Qnil), | ||
| 425 | attrs[SOUND_FILE], Qnil, &file, Qnil); | ||
| 426 | if (s.fd < 0) | ||
| 427 | sound_perror ("Could not open sound file"); | ||
| 428 | |||
| 429 | /* Read the first bytes from the file. */ | ||
| 430 | s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES); | ||
| 431 | if (s.header_size < 0) | ||
| 432 | sound_perror ("Invalid sound file header"); | ||
| 433 | } | ||
| 434 | else | ||
| 435 | { | ||
| 436 | s.data = attrs[SOUND_DATA]; | ||
| 437 | s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data)); | ||
| 438 | bcopy (SDATA (s.data), s.header, s.header_size); | ||
| 439 | } | ||
| 440 | |||
| 441 | /* Find out the type of sound. Give up if we can't tell. */ | ||
| 442 | find_sound_type (&s); | ||
| 443 | |||
| 444 | /* Set up a device. */ | ||
| 445 | if (STRINGP (attrs[SOUND_DEVICE])) | ||
| 446 | { | ||
| 447 | int len = SCHARS (attrs[SOUND_DEVICE]); | ||
| 448 | sd.file = (char *) alloca (len + 1); | ||
| 449 | strcpy (sd.file, SDATA (attrs[SOUND_DEVICE])); | ||
| 450 | } | ||
| 451 | |||
| 452 | if (INTEGERP (attrs[SOUND_VOLUME])) | ||
| 453 | sd.volume = XFASTINT (attrs[SOUND_VOLUME]); | ||
| 454 | else if (FLOATP (attrs[SOUND_VOLUME])) | ||
| 455 | sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100; | ||
| 456 | |||
| 457 | args[0] = Qplay_sound_functions; | ||
| 458 | args[1] = sound; | ||
| 459 | Frun_hook_with_args (2, args); | ||
| 460 | |||
| 461 | /* There is only one type of device we currently support, the VOX | ||
| 462 | sound driver. Set up the device interface functions for that | ||
| 463 | device. */ | ||
| 464 | vox_init (&sd); | ||
| 465 | |||
| 466 | /* Open the device. */ | ||
| 467 | sd.open (&sd); | ||
| 468 | |||
| 469 | /* Play the sound. */ | ||
| 470 | s.play (&s, &sd); | ||
| 471 | |||
| 472 | /* Close the input file, if any. */ | ||
| 473 | if (!STRINGP (s.data)) | ||
| 474 | { | ||
| 475 | emacs_close (s.fd); | ||
| 476 | s.fd = -1; | ||
| 477 | } | ||
| 478 | |||
| 479 | /* Close the device. */ | ||
| 480 | sd.close (&sd); | ||
| 481 | |||
| 482 | /* Clean up. */ | ||
| 483 | current_sound_device = NULL; | ||
| 484 | current_sound = NULL; | ||
| 485 | UNGCPRO; | ||
| 486 | unbind_to (count, Qnil); | ||
| 487 | return Qnil; | ||
| 488 | } | ||
| 489 | |||
| 490 | |||
| 491 | /*********************************************************************** | 465 | /*********************************************************************** |
| 492 | Byte-order Conversion | 466 | Byte-order Conversion |
| 493 | ***********************************************************************/ | 467 | ***********************************************************************/ |
| @@ -555,7 +529,6 @@ be2hs (value) | |||
| 555 | 529 | ||
| 556 | #endif /* 0 */ | 530 | #endif /* 0 */ |
| 557 | 531 | ||
| 558 | |||
| 559 | /*********************************************************************** | 532 | /*********************************************************************** |
| 560 | RIFF-WAVE (*.wav) | 533 | RIFF-WAVE (*.wav) |
| 561 | ***********************************************************************/ | 534 | ***********************************************************************/ |
| @@ -645,7 +618,6 @@ wav_play (s, sd) | |||
| 645 | } | 618 | } |
| 646 | 619 | ||
| 647 | 620 | ||
| 648 | |||
| 649 | /*********************************************************************** | 621 | /*********************************************************************** |
| 650 | Sun Audio (*.au) | 622 | Sun Audio (*.au) |
| 651 | ***********************************************************************/ | 623 | ***********************************************************************/ |
| @@ -735,7 +707,6 @@ au_play (s, sd) | |||
| 735 | } | 707 | } |
| 736 | 708 | ||
| 737 | 709 | ||
| 738 | |||
| 739 | /*********************************************************************** | 710 | /*********************************************************************** |
| 740 | Voxware Driver Interface | 711 | Voxware Driver Interface |
| 741 | ***********************************************************************/ | 712 | ***********************************************************************/ |
| @@ -909,7 +880,6 @@ vox_init (sd) | |||
| 909 | sd->write = vox_write; | 880 | sd->write = vox_write; |
| 910 | } | 881 | } |
| 911 | 882 | ||
| 912 | |||
| 913 | /* Write NBYTES bytes from BUFFER to device SD. */ | 883 | /* Write NBYTES bytes from BUFFER to device SD. */ |
| 914 | 884 | ||
| 915 | static void | 885 | static void |
| @@ -923,7 +893,231 @@ vox_write (sd, buffer, nbytes) | |||
| 923 | sound_perror ("Error writing to sound device"); | 893 | sound_perror ("Error writing to sound device"); |
| 924 | } | 894 | } |
| 925 | 895 | ||
| 896 | /* END: Non Windows functions */ | ||
| 897 | #else /* WINDOWSNT */ | ||
| 898 | |||
| 899 | /* BEGIN: Windows specific functions */ | ||
| 900 | |||
| 901 | static int | ||
| 902 | do_play_sound (psz_file, ui_volume) | ||
| 903 | const char * psz_file; | ||
| 904 | unsigned long ui_volume; | ||
| 905 | { | ||
| 906 | int i_result=0; | ||
| 907 | MCIERROR mci_error=0; | ||
| 908 | char sz_cmd_buf[520]={0}; | ||
| 909 | char sz_ret_buf[520]={0}; | ||
| 910 | MMRESULT mm_result=MMSYSERR_NOERROR; | ||
| 911 | unsigned long ui_volume_org=0; | ||
| 912 | BOOL b_reset_volume=FALSE; | ||
| 913 | memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf)); | ||
| 914 | memset (sz_ret_buf, 0, sizeof(sz_ret_buf)); | ||
| 915 | sprintf ( | ||
| 916 | sz_cmd_buf, | ||
| 917 | "open \"%s\" alias GNUEmacs_PlaySound_Device wait", | ||
| 918 | psz_file); | ||
| 919 | mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL); | ||
| 920 | if (mci_error != 0) | ||
| 921 | { | ||
| 922 | sound_warning ( | ||
| 923 | "The open mciSendString command failed to open\n" | ||
| 924 | "the specified sound file"); | ||
| 925 | i_result=(int)mci_error; | ||
| 926 | return i_result; | ||
| 927 | } | ||
| 928 | if ((ui_volume > 0) && (ui_volume != UINT_MAX)) | ||
| 929 | { | ||
| 930 | mm_result=waveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, &ui_volume_org); | ||
| 931 | if (mm_result == MMSYSERR_NOERROR) | ||
| 932 | { | ||
| 933 | b_reset_volume=TRUE; | ||
| 934 | mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume); | ||
| 935 | if ( mm_result != MMSYSERR_NOERROR) | ||
| 936 | { | ||
| 937 | sound_warning ( | ||
| 938 | "waveOutSetVolume failed to set the volume level\n" | ||
| 939 | "of the WAVE_MAPPER device.\n" | ||
| 940 | "As a result, the user selected volume level will\n" | ||
| 941 | "not be used."); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | else | ||
| 945 | { | ||
| 946 | sound_warning ( | ||
| 947 | "waveOutGetVolume failed to obtain the original\n" | ||
| 948 | "volume level of the WAVE_MAPPER device.\n" | ||
| 949 | "As a result, the user selected volume level will\n" | ||
| 950 | "not be used."); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf)); | ||
| 954 | memset (sz_ret_buf, 0, sizeof(sz_ret_buf)); | ||
| 955 | strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait"); | ||
| 956 | mci_error=mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL); | ||
| 957 | if (mci_error != 0) | ||
| 958 | { | ||
| 959 | sound_warning ( | ||
| 960 | "The play mciSendString command failed to play the\n" | ||
| 961 | "opened sound file."); | ||
| 962 | i_result=(int)mci_error; | ||
| 963 | } | ||
| 964 | memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf)); | ||
| 965 | memset (sz_ret_buf, 0, sizeof(sz_ret_buf)); | ||
| 966 | strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait"); | ||
| 967 | mci_error=mciSendString ( sz_cmd_buf, sz_ret_buf, 520, NULL); | ||
| 968 | if (b_reset_volume == TRUE) | ||
| 969 | { | ||
| 970 | mm_result=waveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, ui_volume_org); | ||
| 971 | if (mm_result != MMSYSERR_NOERROR) | ||
| 972 | { | ||
| 973 | sound_warning ( | ||
| 974 | "waveOutSetVolume failed to reset the original volume\n" | ||
| 975 | "level of the WAVE_MAPPER device."); | ||
| 976 | } | ||
| 977 | } | ||
| 978 | return i_result; | ||
| 979 | } | ||
| 980 | |||
| 981 | /* END: Windows specific functions */ | ||
| 982 | |||
| 983 | #endif /* WINDOWSNT */ | ||
| 984 | |||
| 985 | |||
| 986 | DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0, | ||
| 987 | doc: /* Play sound SOUND. | ||
| 988 | |||
| 989 | Internal use only, use `play-sound' instead.\n */) | ||
| 990 | (sound) | ||
| 991 | Lisp_Object sound; | ||
| 992 | { | ||
| 993 | Lisp_Object attrs[SOUND_ATTR_SENTINEL]; | ||
| 994 | int count = SPECPDL_INDEX (); | ||
| 995 | |||
| 996 | #ifndef WINDOWSNT | ||
| 997 | Lisp_Object file; | ||
| 998 | struct gcpro gcpro1, gcpro2; | ||
| 999 | struct sound_device sd; | ||
| 1000 | struct sound s; | ||
| 1001 | Lisp_Object args[2]; | ||
| 1002 | #else /* WINDOWSNT */ | ||
| 1003 | int len=0; | ||
| 1004 | Lisp_Object lo_file={0}; | ||
| 1005 | char * psz_file=NULL; | ||
| 1006 | unsigned long ui_volume_tmp=UINT_MAX; | ||
| 1007 | unsigned long ui_volume=UINT_MAX; | ||
| 1008 | int i_result=0; | ||
| 1009 | #endif /* WINDOWSNT */ | ||
| 1010 | |||
| 1011 | /* Parse the sound specification. Give up if it is invalid. */ | ||
| 1012 | if (!parse_sound (sound, attrs)) | ||
| 1013 | error ("Invalid sound specification"); | ||
| 1014 | |||
| 1015 | #ifndef WINDOWSNT | ||
| 1016 | file = Qnil; | ||
| 1017 | GCPRO2 (sound, file); | ||
| 1018 | bzero (&sd, sizeof sd); | ||
| 1019 | bzero (&s, sizeof s); | ||
| 1020 | current_sound_device = &sd; | ||
| 1021 | current_sound = &s; | ||
| 1022 | record_unwind_protect (sound_cleanup, Qnil); | ||
| 1023 | s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES); | ||
| 1024 | |||
| 1025 | if (STRINGP (attrs[SOUND_FILE])) | ||
| 1026 | { | ||
| 1027 | /* Open the sound file. */ | ||
| 1028 | s.fd = openp (Fcons (Vdata_directory, Qnil), | ||
| 1029 | attrs[SOUND_FILE], Qnil, &file, Qnil); | ||
| 1030 | if (s.fd < 0) | ||
| 1031 | sound_perror ("Could not open sound file"); | ||
| 1032 | |||
| 1033 | /* Read the first bytes from the file. */ | ||
| 1034 | s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES); | ||
| 1035 | if (s.header_size < 0) | ||
| 1036 | sound_perror ("Invalid sound file header"); | ||
| 1037 | } | ||
| 1038 | else | ||
| 1039 | { | ||
| 1040 | s.data = attrs[SOUND_DATA]; | ||
| 1041 | s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data)); | ||
| 1042 | bcopy (SDATA (s.data), s.header, s.header_size); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | /* Find out the type of sound. Give up if we can't tell. */ | ||
| 1046 | find_sound_type (&s); | ||
| 1047 | |||
| 1048 | /* Set up a device. */ | ||
| 1049 | if (STRINGP (attrs[SOUND_DEVICE])) | ||
| 1050 | { | ||
| 1051 | int len = SCHARS (attrs[SOUND_DEVICE]); | ||
| 1052 | sd.file = (char *) alloca (len + 1); | ||
| 1053 | strcpy (sd.file, SDATA (attrs[SOUND_DEVICE])); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | if (INTEGERP (attrs[SOUND_VOLUME])) | ||
| 1057 | sd.volume = XFASTINT (attrs[SOUND_VOLUME]); | ||
| 1058 | else if (FLOATP (attrs[SOUND_VOLUME])) | ||
| 1059 | sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100; | ||
| 926 | 1060 | ||
| 1061 | args[0] = Qplay_sound_functions; | ||
| 1062 | args[1] = sound; | ||
| 1063 | Frun_hook_with_args (2, args); | ||
| 1064 | |||
| 1065 | /* There is only one type of device we currently support, the VOX | ||
| 1066 | sound driver. Set up the device interface functions for that | ||
| 1067 | device. */ | ||
| 1068 | vox_init (&sd); | ||
| 1069 | |||
| 1070 | /* Open the device. */ | ||
| 1071 | sd.open (&sd); | ||
| 1072 | |||
| 1073 | /* Play the sound. */ | ||
| 1074 | s.play (&s, &sd); | ||
| 1075 | |||
| 1076 | /* Close the input file, if any. */ | ||
| 1077 | if (!STRINGP (s.data)) | ||
| 1078 | { | ||
| 1079 | emacs_close (s.fd); | ||
| 1080 | s.fd = -1; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | /* Close the device. */ | ||
| 1084 | sd.close (&sd); | ||
| 1085 | |||
| 1086 | /* Clean up. */ | ||
| 1087 | current_sound_device = NULL; | ||
| 1088 | current_sound = NULL; | ||
| 1089 | UNGCPRO; | ||
| 1090 | #else /* WINDOWSNT */ | ||
| 1091 | lo_file=Fexpand_file_name (attrs[SOUND_FILE], Qnil); | ||
| 1092 | len=XSTRING (lo_file)->size; | ||
| 1093 | psz_file=(char *)alloca (len+1); | ||
| 1094 | strcpy (psz_file, XSTRING (lo_file)->data); | ||
| 1095 | if (INTEGERP (attrs[SOUND_VOLUME])) | ||
| 1096 | { | ||
| 1097 | ui_volume_tmp=XFASTINT (attrs[SOUND_VOLUME]); | ||
| 1098 | } | ||
| 1099 | else if (FLOATP (attrs[SOUND_VOLUME])) | ||
| 1100 | { | ||
| 1101 | ui_volume_tmp=(unsigned long)XFLOAT_DATA (attrs[SOUND_VOLUME])*100; | ||
| 1102 | } | ||
| 1103 | /* | ||
| 1104 | Based on some experiments I have conducted, a value of 100 or less | ||
| 1105 | for the sound volume is much too low. You cannot even hear it. | ||
| 1106 | A value of UINT_MAX indicates that you wish for the sound to played | ||
| 1107 | at the maximum possible volume. A value of UINT_MAX/2 plays the | ||
| 1108 | sound at 50% maximum volume. Therefore the value passed to do_play_sound | ||
| 1109 | (and thus to waveOutSetVolume must be some fraction of UINT_MAX. | ||
| 1110 | The following code adjusts the user specified volume level appropriately. | ||
| 1111 | */ | ||
| 1112 | if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100)) | ||
| 1113 | { | ||
| 1114 | ui_volume=ui_volume_tmp * (UINT_MAX / 100); | ||
| 1115 | } | ||
| 1116 | i_result=do_play_sound (psz_file, ui_volume); | ||
| 1117 | #endif /* WINDOWSNT */ | ||
| 1118 | unbind_to (count, Qnil); | ||
| 1119 | return Qnil; | ||
| 1120 | } | ||
| 927 | 1121 | ||
| 928 | /*********************************************************************** | 1122 | /*********************************************************************** |
| 929 | Initialization | 1123 | Initialization |
| @@ -105,6 +105,171 @@ extern Lisp_Object Vw32_get_true_file_attributes; | |||
| 105 | extern Lisp_Object Vw32_num_mouse_buttons; | 105 | extern Lisp_Object Vw32_num_mouse_buttons; |
| 106 | 106 | ||
| 107 | 107 | ||
| 108 | /* | ||
| 109 | BEGIN: Wrapper functions around OpenProcessToken | ||
| 110 | and other functions in advapi32.dll that are only | ||
| 111 | supported in Windows NT / 2k / XP | ||
| 112 | */ | ||
| 113 | /* ** Function pointer typedefs ** */ | ||
| 114 | typedef BOOL (WINAPI * OpenProcessToken_Proc) ( | ||
| 115 | HANDLE ProcessHandle, | ||
| 116 | DWORD DesiredAccess, | ||
| 117 | PHANDLE TokenHandle); | ||
| 118 | typedef BOOL (WINAPI * GetTokenInformation_Proc) ( | ||
| 119 | HANDLE TokenHandle, | ||
| 120 | TOKEN_INFORMATION_CLASS TokenInformationClass, | ||
| 121 | LPVOID TokenInformation, | ||
| 122 | DWORD TokenInformationLength, | ||
| 123 | PDWORD ReturnLength); | ||
| 124 | #ifdef _UNICODE | ||
| 125 | const char * const LookupAccountSid_Name = "LookupAccountSidW"; | ||
| 126 | #else | ||
| 127 | const char * const LookupAccountSid_Name = "LookupAccountSidA"; | ||
| 128 | #endif | ||
| 129 | typedef BOOL (WINAPI * LookupAccountSid_Proc) ( | ||
| 130 | LPCTSTR lpSystemName, | ||
| 131 | PSID Sid, | ||
| 132 | LPTSTR Name, | ||
| 133 | LPDWORD cbName, | ||
| 134 | LPTSTR DomainName, | ||
| 135 | LPDWORD cbDomainName, | ||
| 136 | PSID_NAME_USE peUse); | ||
| 137 | typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) ( | ||
| 138 | PSID pSid); | ||
| 139 | |||
| 140 | /* ** A utility function ** */ | ||
| 141 | static BOOL is_windows_9x () | ||
| 142 | { | ||
| 143 | BOOL b_ret=0; | ||
| 144 | OSVERSIONINFO os_ver; | ||
| 145 | ZeroMemory(&os_ver, sizeof(OSVERSIONINFO)); | ||
| 146 | os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | ||
| 147 | if (GetVersionEx (&os_ver)) | ||
| 148 | { | ||
| 149 | b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); | ||
| 150 | } | ||
| 151 | return b_ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* ** The wrapper functions ** */ | ||
| 155 | |||
| 156 | BOOL WINAPI open_process_token ( | ||
| 157 | HANDLE ProcessHandle, | ||
| 158 | DWORD DesiredAccess, | ||
| 159 | PHANDLE TokenHandle) | ||
| 160 | { | ||
| 161 | OpenProcessToken_Proc pfn_Open_Process_Token = NULL; | ||
| 162 | HMODULE hm_advapi32 = NULL; | ||
| 163 | if (is_windows_9x () == TRUE) | ||
| 164 | { | ||
| 165 | return FALSE; | ||
| 166 | } | ||
| 167 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 168 | pfn_Open_Process_Token = | ||
| 169 | (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken"); | ||
| 170 | if (pfn_Open_Process_Token == NULL) | ||
| 171 | { | ||
| 172 | return FALSE; | ||
| 173 | } | ||
| 174 | return ( | ||
| 175 | pfn_Open_Process_Token ( | ||
| 176 | ProcessHandle, | ||
| 177 | DesiredAccess, | ||
| 178 | TokenHandle) | ||
| 179 | ); | ||
| 180 | } | ||
| 181 | |||
| 182 | BOOL WINAPI get_token_information ( | ||
| 183 | HANDLE TokenHandle, | ||
| 184 | TOKEN_INFORMATION_CLASS TokenInformationClass, | ||
| 185 | LPVOID TokenInformation, | ||
| 186 | DWORD TokenInformationLength, | ||
| 187 | PDWORD ReturnLength) | ||
| 188 | { | ||
| 189 | GetTokenInformation_Proc pfn_Get_Token_Information = NULL; | ||
| 190 | HMODULE hm_advapi32 = NULL; | ||
| 191 | if (is_windows_9x () == TRUE) | ||
| 192 | { | ||
| 193 | return FALSE; | ||
| 194 | } | ||
| 195 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 196 | pfn_Get_Token_Information = | ||
| 197 | (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation"); | ||
| 198 | if (pfn_Get_Token_Information == NULL) | ||
| 199 | { | ||
| 200 | return FALSE; | ||
| 201 | } | ||
| 202 | return ( | ||
| 203 | pfn_Get_Token_Information ( | ||
| 204 | TokenHandle, | ||
| 205 | TokenInformationClass, | ||
| 206 | TokenInformation, | ||
| 207 | TokenInformationLength, | ||
| 208 | ReturnLength) | ||
| 209 | ); | ||
| 210 | } | ||
| 211 | |||
| 212 | BOOL WINAPI lookup_account_sid ( | ||
| 213 | LPCTSTR lpSystemName, | ||
| 214 | PSID Sid, | ||
| 215 | LPTSTR Name, | ||
| 216 | LPDWORD cbName, | ||
| 217 | LPTSTR DomainName, | ||
| 218 | LPDWORD cbDomainName, | ||
| 219 | PSID_NAME_USE peUse) | ||
| 220 | { | ||
| 221 | LookupAccountSid_Proc pfn_Lookup_Account_Sid = NULL; | ||
| 222 | HMODULE hm_advapi32 = NULL; | ||
| 223 | if (is_windows_9x () == TRUE) | ||
| 224 | { | ||
| 225 | return FALSE; | ||
| 226 | } | ||
| 227 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 228 | pfn_Lookup_Account_Sid = | ||
| 229 | (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name); | ||
| 230 | if (pfn_Lookup_Account_Sid == NULL) | ||
| 231 | { | ||
| 232 | return FALSE; | ||
| 233 | } | ||
| 234 | return ( | ||
| 235 | pfn_Lookup_Account_Sid ( | ||
| 236 | lpSystemName, | ||
| 237 | Sid, | ||
| 238 | Name, | ||
| 239 | cbName, | ||
| 240 | DomainName, | ||
| 241 | cbDomainName, | ||
| 242 | peUse) | ||
| 243 | ); | ||
| 244 | } | ||
| 245 | |||
| 246 | PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority ( | ||
| 247 | PSID pSid) | ||
| 248 | { | ||
| 249 | GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority = NULL; | ||
| 250 | HMODULE hm_advapi32 = NULL; | ||
| 251 | if (is_windows_9x () == TRUE) | ||
| 252 | { | ||
| 253 | return NULL; | ||
| 254 | } | ||
| 255 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 256 | pfn_Get_Sid_Identifier_Authority = | ||
| 257 | (GetSidIdentifierAuthority_Proc) GetProcAddress ( | ||
| 258 | hm_advapi32, "GetSidIdentifierAuthority"); | ||
| 259 | if (pfn_Get_Sid_Identifier_Authority == NULL) | ||
| 260 | { | ||
| 261 | return NULL; | ||
| 262 | } | ||
| 263 | return (pfn_Get_Sid_Identifier_Authority (pSid)); | ||
| 264 | } | ||
| 265 | |||
| 266 | /* | ||
| 267 | END: Wrapper functions around OpenProcessToken | ||
| 268 | and other functions in advapi32.dll that are only | ||
| 269 | supported in Windows NT / 2k / XP | ||
| 270 | */ | ||
| 271 | |||
| 272 | |||
| 108 | /* Equivalent of strerror for W32 error codes. */ | 273 | /* Equivalent of strerror for W32 error codes. */ |
| 109 | char * | 274 | char * |
| 110 | w32_strerror (int error_no) | 275 | w32_strerror (int error_no) |
| @@ -254,11 +419,15 @@ init_user_info () | |||
| 254 | HANDLE token = NULL; | 419 | HANDLE token = NULL; |
| 255 | SID_NAME_USE user_type; | 420 | SID_NAME_USE user_type; |
| 256 | 421 | ||
| 257 | if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token) | 422 | if ( |
| 258 | && GetTokenInformation (token, TokenUser, | 423 | open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token) |
| 424 | && get_token_information ( | ||
| 425 | token, TokenUser, | ||
| 259 | (PVOID) user_sid, sizeof (user_sid), &trash) | 426 | (PVOID) user_sid, sizeof (user_sid), &trash) |
| 260 | && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length, | 427 | && lookup_account_sid ( |
| 261 | domain, &dlength, &user_type)) | 428 | NULL, *((PSID *) user_sid), name, &length, |
| 429 | domain, &dlength, &user_type) | ||
| 430 | ) | ||
| 262 | { | 431 | { |
| 263 | strcpy (the_passwd.pw_name, name); | 432 | strcpy (the_passwd.pw_name, name); |
| 264 | /* Determine a reasonable uid value. */ | 433 | /* Determine a reasonable uid value. */ |
| @@ -271,7 +440,7 @@ init_user_info () | |||
| 271 | { | 440 | { |
| 272 | SID_IDENTIFIER_AUTHORITY * pSIA; | 441 | SID_IDENTIFIER_AUTHORITY * pSIA; |
| 273 | 442 | ||
| 274 | pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid)); | 443 | pSIA = get_sid_identifier_authority (*((PSID *) user_sid)); |
| 275 | /* I believe the relative portion is the last 4 bytes (of 6) | 444 | /* I believe the relative portion is the last 4 bytes (of 6) |
| 276 | with msb first. */ | 445 | with msb first. */ |
| 277 | the_passwd.pw_uid = ((pSIA->Value[2] << 24) + | 446 | the_passwd.pw_uid = ((pSIA->Value[2] << 24) + |
| @@ -282,12 +451,12 @@ init_user_info () | |||
| 282 | the_passwd.pw_uid = the_passwd.pw_uid % 60001; | 451 | the_passwd.pw_uid = the_passwd.pw_uid % 60001; |
| 283 | 452 | ||
| 284 | /* Get group id */ | 453 | /* Get group id */ |
| 285 | if (GetTokenInformation (token, TokenPrimaryGroup, | 454 | if (get_token_information (token, TokenPrimaryGroup, |
| 286 | (PVOID) user_sid, sizeof (user_sid), &trash)) | 455 | (PVOID) user_sid, sizeof (user_sid), &trash)) |
| 287 | { | 456 | { |
| 288 | SID_IDENTIFIER_AUTHORITY * pSIA; | 457 | SID_IDENTIFIER_AUTHORITY * pSIA; |
| 289 | 458 | ||
| 290 | pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid)); | 459 | pSIA = get_sid_identifier_authority (*((PSID *) user_sid)); |
| 291 | the_passwd.pw_gid = ((pSIA->Value[2] << 24) + | 460 | the_passwd.pw_gid = ((pSIA->Value[2] << 24) + |
| 292 | (pSIA->Value[3] << 16) + | 461 | (pSIA->Value[3] << 16) + |
| 293 | (pSIA->Value[4] << 8) + | 462 | (pSIA->Value[4] << 8) + |
| @@ -124,5 +124,10 @@ extern LPBYTE w32_get_resource (char * key, LPDWORD type); | |||
| 124 | 124 | ||
| 125 | extern void init_ntproc (); | 125 | extern void init_ntproc (); |
| 126 | extern void term_ntproc (); | 126 | extern void term_ntproc (); |
| 127 | extern void syms_of_w32term (); | ||
| 128 | extern void syms_of_w32fns (); | ||
| 129 | extern void syms_of_w32select (); | ||
| 130 | extern void syms_of_w32menu (); | ||
| 131 | extern void syms_of_fontset (); | ||
| 127 | 132 | ||
| 128 | #endif /* EMACS_W32_H */ | 133 | #endif /* EMACS_W32_H */ |
diff --git a/src/w32fns.c b/src/w32fns.c index e0925869d89..7037493e3a1 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -283,7 +283,12 @@ static unsigned mouse_move_timer = 0; | |||
| 283 | 283 | ||
| 284 | /* Window that is tracking the mouse. */ | 284 | /* Window that is tracking the mouse. */ |
| 285 | static HWND track_mouse_window; | 285 | static HWND track_mouse_window; |
| 286 | FARPROC track_mouse_event_fn; | 286 | |
| 287 | typedef BOOL (WINAPI * TrackMouseEvent_Proc) ( | ||
| 288 | IN OUT LPTRACKMOUSEEVENT lpEventTrack | ||
| 289 | ); | ||
| 290 | |||
| 291 | TrackMouseEvent_Proc track_mouse_event_fn=NULL; | ||
| 287 | 292 | ||
| 288 | /* W95 mousewheel handler */ | 293 | /* W95 mousewheel handler */ |
| 289 | unsigned int msh_mousewheel = 0; | 294 | unsigned int msh_mousewheel = 0; |
| @@ -4929,6 +4934,30 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 4929 | goto dflt; | 4934 | goto dflt; |
| 4930 | 4935 | ||
| 4931 | case WM_SETFOCUS: | 4936 | case WM_SETFOCUS: |
| 4937 | /* | ||
| 4938 | Reinitialize the function pointer track_mouse_event_fn here. | ||
| 4939 | This is required even though it is initialized in syms_of_w32fns | ||
| 4940 | which is called in main (emacs.c). | ||
| 4941 | Reinitialize the function pointer track_mouse_event_fn here. | ||
| 4942 | Even though this function pointer is initialized in | ||
| 4943 | syms_of_w32fns which is called from main (emacs.c), | ||
| 4944 | we need to initialize it again here in order to prevent | ||
| 4945 | a crash that occurs in Windows 9x (possibly only when Emacs | ||
| 4946 | was built on Windows NT / 2000 / XP?) when handling the | ||
| 4947 | WM_MOUSEMOVE message. | ||
| 4948 | The crash occurs when attempting to call the Win32 API | ||
| 4949 | function TrackMouseEvent through the function pointer. | ||
| 4950 | It appears as if the function pointer that is obtained when | ||
| 4951 | syms_of_w32fns is called from main is no longer valid | ||
| 4952 | (possibly due to DLL relocation?). | ||
| 4953 | To resolve this issue, I have placed a call to reinitialize | ||
| 4954 | this function pointer here because this message gets received | ||
| 4955 | when the Emacs window gains focus. | ||
| 4956 | */ | ||
| 4957 | track_mouse_event_fn = | ||
| 4958 | (TrackMouseEvent_Proc) GetProcAddress ( | ||
| 4959 | GetModuleHandle ("user32.dll"), | ||
| 4960 | "TrackMouseEvent"); | ||
| 4932 | dpyinfo->faked_key = 0; | 4961 | dpyinfo->faked_key = 0; |
| 4933 | reset_modifiers (); | 4962 | reset_modifiers (); |
| 4934 | register_hot_keys (hwnd); | 4963 | register_hot_keys (hwnd); |
| @@ -14843,7 +14872,7 @@ syms_of_w32fns () | |||
| 14843 | 14872 | ||
| 14844 | /* TrackMouseEvent not available in all versions of Windows, so must load | 14873 | /* TrackMouseEvent not available in all versions of Windows, so must load |
| 14845 | it dynamically. Do it once, here, instead of every time it is used. */ | 14874 | it dynamically. Do it once, here, instead of every time it is used. */ |
| 14846 | track_mouse_event_fn = GetProcAddress (user32_lib, "TrackMouseEvent"); | 14875 | track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent"); |
| 14847 | track_mouse_window = NULL; | 14876 | track_mouse_window = NULL; |
| 14848 | 14877 | ||
| 14849 | w32_visible_system_caret_hwnd = NULL; | 14878 | w32_visible_system_caret_hwnd = NULL; |
diff --git a/src/w32menu.c b/src/w32menu.c index 44791448d94..8139a0ad956 100644 --- a/src/w32menu.c +++ b/src/w32menu.c | |||
| @@ -129,8 +129,23 @@ typedef struct _widget_value | |||
| 129 | 129 | ||
| 130 | static HMENU current_popup_menu; | 130 | static HMENU current_popup_menu; |
| 131 | 131 | ||
| 132 | FARPROC get_menu_item_info; | 132 | void syms_of_w32menu (); |
| 133 | FARPROC set_menu_item_info; | 133 | |
| 134 | typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) ( | ||
| 135 | IN HMENU, | ||
| 136 | IN UINT, | ||
| 137 | IN BOOL, | ||
| 138 | IN OUT LPMENUITEMINFOA | ||
| 139 | ); | ||
| 140 | typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) ( | ||
| 141 | IN HMENU, | ||
| 142 | IN UINT, | ||
| 143 | IN BOOL, | ||
| 144 | IN LPCMENUITEMINFOA | ||
| 145 | ); | ||
| 146 | |||
| 147 | GetMenuItemInfoA_Proc get_menu_item_info=NULL; | ||
| 148 | SetMenuItemInfoA_Proc set_menu_item_info=NULL; | ||
| 134 | 149 | ||
| 135 | Lisp_Object Vmenu_updating_frame; | 150 | Lisp_Object Vmenu_updating_frame; |
| 136 | 151 | ||
| @@ -1591,6 +1606,26 @@ void | |||
| 1591 | initialize_frame_menubar (f) | 1606 | initialize_frame_menubar (f) |
| 1592 | FRAME_PTR f; | 1607 | FRAME_PTR f; |
| 1593 | { | 1608 | { |
| 1609 | HMODULE user32 = GetModuleHandle ("user32.dll"); | ||
| 1610 | /* | ||
| 1611 | Reinitialize the function pointers set_menu_item_info and | ||
| 1612 | get_menu_item_info here. | ||
| 1613 | Even though these function pointers are initialized in | ||
| 1614 | syms_of_w32menu which is called from main (emacs.c), | ||
| 1615 | we need to initialize them again here in order to prevent | ||
| 1616 | a crash that occurs in Windows 9x (possibly only when Emacs | ||
| 1617 | was built on Windows NT / 2000 / XP?) in add_menu_item. | ||
| 1618 | The crash occurs when attempting to call the Win32 API | ||
| 1619 | function SetMenuItemInfo through the function pointer. | ||
| 1620 | It appears as if the function pointer that is obtained when | ||
| 1621 | syms_of_w32menu is called from main is no longer valid | ||
| 1622 | (possibly due to DLL relocation?). | ||
| 1623 | To resolve this issue, I have placed calls to reinitialize | ||
| 1624 | these function pointers here because this function is the | ||
| 1625 | entry point for menu creation. | ||
| 1626 | */ | ||
| 1627 | get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); | ||
| 1628 | set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); | ||
| 1594 | /* This function is called before the first chance to redisplay | 1629 | /* This function is called before the first chance to redisplay |
| 1595 | the frame. It has to be, so the frame will have the right size. */ | 1630 | the frame. It has to be, so the frame will have the right size. */ |
| 1596 | FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | 1631 | FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); |
| @@ -2355,13 +2390,12 @@ w32_free_menu_strings (hwnd) | |||
| 2355 | 2390 | ||
| 2356 | #endif /* HAVE_MENUS */ | 2391 | #endif /* HAVE_MENUS */ |
| 2357 | 2392 | ||
| 2358 | 2393 | void syms_of_w32menu () | |
| 2359 | syms_of_w32menu () | ||
| 2360 | { | 2394 | { |
| 2361 | /* See if Get/SetMenuItemInfo functions are available. */ | 2395 | /* See if Get/SetMenuItemInfo functions are available. */ |
| 2362 | HMODULE user32 = GetModuleHandle ("user32.dll"); | 2396 | HMODULE user32 = GetModuleHandle ("user32.dll"); |
| 2363 | get_menu_item_info = GetProcAddress (user32, "GetMenuItemInfoA"); | 2397 | get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); |
| 2364 | set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfoA"); | 2398 | set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); |
| 2365 | 2399 | ||
| 2366 | staticpro (&menu_items); | 2400 | staticpro (&menu_items); |
| 2367 | menu_items = Qnil; | 2401 | menu_items = Qnil; |