aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBen Key2002-11-17 22:35:26 +0000
committerBen Key2002-11-17 22:35:26 +0000
commitf60ae425e9095d06f4ad06e5b277903606c25dca (patch)
tree5cf0be810c07412c8e145c431327f53df9e8ad89 /src
parent87a609d3fb43ab67d043ae2462ac5aacff9381c1 (diff)
downloademacs-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/ChangeLog69
-rw-r--r--src/makefile.w32-in9
-rw-r--r--src/s/ms-w32.h1
-rw-r--r--src/sound.c446
-rw-r--r--src/w32.c183
-rw-r--r--src/w32.h5
-rw-r--r--src/w32fns.c33
-rw-r--r--src/w32menu.c46
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 @@
12002-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
12002-11-16 Jason Rumney <jasonr@gnu.org> 702002-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
95extern Lisp_Object QCfile, QCdata;
96Lisp_Object QCvolume, QCdevice;
97Lisp_Object Qsound;
98Lisp_Object Qplay_sound_functions;
99
100/* Indices of attributes in a sound attributes vector. */
101
102enum sound_attr
103{
104 SOUND_FILE,
105 SOUND_DATA,
106 SOUND_DEVICE,
107 SOUND_VOLUME,
108 SOUND_ATTR_SENTINEL
109};
110
111static void sound_perror P_ ((char *));
112static void sound_warning P_ ((char *));
113static 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
208enum sound_attr
209{
210 SOUND_FILE,
211 SOUND_DATA,
212 SOUND_DEVICE,
213 SOUND_VOLUME,
214 SOUND_ATTR_SENTINEL
215};
216
217/* Symbols. */
218
219extern Lisp_Object QCfile, QCdata;
220Lisp_Object QCvolume, QCdevice;
221Lisp_Object Qsound;
222Lisp_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));
235static void vox_choose_format P_ ((struct sound_device *, struct sound *)); 281static void vox_choose_format P_ ((struct sound_device *, struct sound *));
236static void vox_init P_ ((struct sound_device *)); 282static void vox_init P_ ((struct sound_device *));
237static void vox_write P_ ((struct sound_device *, const char *, int)); 283static void vox_write P_ ((struct sound_device *, const char *, int));
238static void sound_perror P_ ((char *));
239static void sound_warning P_ ((char *));
240static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
241static void find_sound_type P_ ((struct sound *)); 284static void find_sound_type P_ ((struct sound *));
242static u_int32_t le2hl P_ ((u_int32_t)); 285static u_int32_t le2hl P_ ((u_int32_t));
243static u_int16_t le2hs P_ ((u_int16_t)); 286static u_int16_t le2hs P_ ((u_int16_t));
@@ -251,12 +294,22 @@ static void au_play P_ ((struct sound *, struct sound_device *));
251static u_int16_t be2hs P_ ((u_int16_t)); 294static 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 */
301static 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
262static void 315static 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
393DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
394 doc: /* Play sound SOUND.
395
396Internal 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
915static void 885static 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
901static int
902do_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
986DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
987 doc: /* Play sound SOUND.
988
989Internal 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
diff --git a/src/w32.c b/src/w32.c
index 7a31e78d1da..c80c4232bc6 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -105,6 +105,171 @@ extern Lisp_Object Vw32_get_true_file_attributes;
105extern Lisp_Object Vw32_num_mouse_buttons; 105extern 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 ** */
114typedef BOOL (WINAPI * OpenProcessToken_Proc) (
115 HANDLE ProcessHandle,
116 DWORD DesiredAccess,
117 PHANDLE TokenHandle);
118typedef BOOL (WINAPI * GetTokenInformation_Proc) (
119 HANDLE TokenHandle,
120 TOKEN_INFORMATION_CLASS TokenInformationClass,
121 LPVOID TokenInformation,
122 DWORD TokenInformationLength,
123 PDWORD ReturnLength);
124#ifdef _UNICODE
125const char * const LookupAccountSid_Name = "LookupAccountSidW";
126#else
127const char * const LookupAccountSid_Name = "LookupAccountSidA";
128#endif
129typedef 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);
137typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
138 PSID pSid);
139
140 /* ** A utility function ** */
141static 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
156BOOL 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
182BOOL 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
212BOOL 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
246PSID_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. */
109char * 274char *
110w32_strerror (int error_no) 275w32_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) +
diff --git a/src/w32.h b/src/w32.h
index 2b87f58a567..24fda2c648b 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -124,5 +124,10 @@ extern LPBYTE w32_get_resource (char * key, LPDWORD type);
124 124
125extern void init_ntproc (); 125extern void init_ntproc ();
126extern void term_ntproc (); 126extern void term_ntproc ();
127extern void syms_of_w32term ();
128extern void syms_of_w32fns ();
129extern void syms_of_w32select ();
130extern void syms_of_w32menu ();
131extern 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. */
285static HWND track_mouse_window; 285static HWND track_mouse_window;
286FARPROC track_mouse_event_fn; 286
287typedef BOOL (WINAPI * TrackMouseEvent_Proc) (
288 IN OUT LPTRACKMOUSEEVENT lpEventTrack
289 );
290
291TrackMouseEvent_Proc track_mouse_event_fn=NULL;
287 292
288/* W95 mousewheel handler */ 293/* W95 mousewheel handler */
289unsigned int msh_mousewheel = 0; 294unsigned 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
130static HMENU current_popup_menu; 130static HMENU current_popup_menu;
131 131
132FARPROC get_menu_item_info; 132void syms_of_w32menu ();
133FARPROC set_menu_item_info; 133
134typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
135 IN HMENU,
136 IN UINT,
137 IN BOOL,
138 IN OUT LPMENUITEMINFOA
139 );
140typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
141 IN HMENU,
142 IN UINT,
143 IN BOOL,
144 IN LPCMENUITEMINFOA
145 );
146
147GetMenuItemInfoA_Proc get_menu_item_info=NULL;
148SetMenuItemInfoA_Proc set_menu_item_info=NULL;
134 149
135Lisp_Object Vmenu_updating_frame; 150Lisp_Object Vmenu_updating_frame;
136 151
@@ -1591,6 +1606,26 @@ void
1591initialize_frame_menubar (f) 1606initialize_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 2393void syms_of_w32menu ()
2359syms_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;