18 private class IntSecurity
26 if (safeSubWindows ==
null)
30 return safeSubWindows;
39 private class NativeMethods
42 internal class MMCKINFO
50 internal int dwDataOffset;
56 internal class WAVEFORMATEX
58 internal short wFormatTag;
60 internal short nChannels;
62 internal int nSamplesPerSec;
64 internal int nAvgBytesPerSec;
66 internal short nBlockAlign;
68 internal short wBitsPerSample;
70 internal short cbSize;
73 internal const int WAVE_FORMAT_PCM = 1;
75 internal const int WAVE_FORMAT_ADPCM = 2;
77 internal const int WAVE_FORMAT_IEEE_FLOAT = 3;
79 internal const int MMIO_READ = 0;
81 internal const int MMIO_ALLOCBUF = 65536;
83 internal const int MMIO_FINDRIFF = 32;
85 internal const int SND_SYNC = 0;
87 internal const int SND_ASYNC = 1;
89 internal const int SND_NODEFAULT = 2;
91 internal const int SND_MEMORY = 4;
93 internal const int SND_LOOP = 8;
95 internal const int SND_PURGE = 64;
97 internal const int SND_FILENAME = 131072;
99 internal const int SND_NOSTOP = 16;
101 private NativeMethods()
106 private class UnsafeNativeMethods
108 private UnsafeNativeMethods()
113 internal static extern bool PlaySound([MarshalAs(
UnmanagedType.LPWStr)]
string soundName,
IntPtr hmod,
int soundFlags);
115 [DllImport(
"winmm.dll",
CharSet =
CharSet.Auto, ExactSpelling =
true)]
116 internal static extern bool PlaySound(
byte[] soundName,
IntPtr hmod,
int soundFlags);
119 internal static extern IntPtr mmioOpen(
string fileName,
IntPtr not_used,
int flags);
122 internal static extern int mmioAscend(
IntPtr hMIO, NativeMethods.MMCKINFO lpck,
int flags);
125 internal static extern int mmioDescend(
IntPtr hMIO, [MarshalAs(
UnmanagedType.LPStruct)] NativeMethods.MMCKINFO lpck, [MarshalAs(
UnmanagedType.LPStruct)] NativeMethods.MMCKINFO lcpkParent,
int flags);
128 internal static extern int mmioRead(
IntPtr hMIO, [MarshalAs(
UnmanagedType.LPArray)]
byte[] wf,
int cch);
131 internal static extern int mmioClose(
IntPtr hMIO,
int flags);
134 private const int blockSize = 1024;
136 private const int defaultLoadTimeout = 10000;
140 private string soundLocation =
string.Empty;
142 private int loadTimeout = 10000;
148 private Thread copyThread;
150 private int currentPos;
154 private bool isLoadCompleted;
158 private bool doesLoadAppearSynchronous;
160 private byte[] streamData;
166 private static readonly
object EventLoadCompleted =
new object();
168 private static readonly
object EventSoundLocationChanged =
new object();
170 private static readonly
object EventStreamChanged =
new object();
196 if (uri !=
null && uri.
IsFile)
200 fileIOPermission.
Demand();
202 return soundLocation;
208 value =
string.Empty;
210 if (!soundLocation.Equals(value))
212 SetupSoundLocation(value);
264 base.Events.AddHandler(EventLoadCompleted, value);
268 base.Events.RemoveHandler(EventLoadCompleted, value);
277 base.Events.AddHandler(EventSoundLocationChanged, value);
281 base.Events.RemoveHandler(EventSoundLocationChanged, value);
290 base.Events.AddHandler(EventStreamChanged, value);
294 base.Events.RemoveHandler(EventStreamChanged, value);
301 loadAsyncOperationCompleted = LoadAsyncOperationCompleted;
310 if (soundLocation ==
null)
312 soundLocation =
string.Empty;
314 SetupSoundLocation(soundLocation);
322 this.stream = stream;
335 switch (current.
Name)
337 case "SoundLocation":
338 SetupSoundLocation((
string)current.
Value);
359 if (uri !=
null && uri.
IsFile)
361 isLoadCompleted =
true;
369 else if (copyThread ==
null || copyThread.
ThreadState != 0)
371 isLoadCompleted =
false;
375 LoadStream(loadSync:
false);
379 private void LoadAsyncOperationCompleted(
object arg)
384 private void CleanupStreamData()
388 isLoadCompleted =
false;
389 lastLoadException =
null;
390 doesLoadAppearSynchronous =
false;
400 if (uri !=
null && uri.
IsFile)
407 isLoadCompleted =
true;
416 private void LoadAndPlay(
int flags)
418 if (
string.IsNullOrEmpty(soundLocation) && stream ==
null)
422 else if (uri !=
null && uri.
IsFile)
426 fileIOPermission.
Demand();
427 isLoadCompleted =
true;
428 IntSecurity.SafeSubWindows.Demand();
432 ValidateSoundFile(localPath);
433 UnsafeNativeMethods.PlaySound(localPath,
IntPtr.
Zero, 2 | flags);
443 ValidateSoundData(streamData);
444 IntSecurity.SafeSubWindows.Demand();
448 UnsafeNativeMethods.PlaySound(streamData, IntPtr.Zero, 6 | flags);
457 private void LoadSync()
461 if (copyThread !=
null)
466 throw new TimeoutException(SR.GetString(
"SoundAPILoadTimedOut"));
468 if (streamData !=
null)
472 if (uri !=
null && !uri.
IsFile && stream ==
null)
483 LoadStream(loadSync:
true);
487 doesLoadAppearSynchronous =
true;
488 LoadStream(loadSync:
false);
491 if (copyThread !=
null)
496 throw new TimeoutException(SR.GetString(
"SoundAPILoadTimedOut"));
498 doesLoadAppearSynchronous =
false;
499 if (lastLoadException !=
null)
501 throw lastLoadException;
507 private void LoadStream(
bool loadSync)
509 if (loadSync && stream.
CanSeek)
511 int num = (int)stream.
Length;
513 streamData =
new byte[num];
514 stream.
Read(streamData, 0, num);
515 isLoadCompleted =
true;
521 copyThread =
new Thread(WorkerThread);
553 private static Uri ResolveUri(
string partialUri)
558 uri =
new Uri(partialUri);
570 catch (UriFormatException)
578 private void SetupSoundLocation(
string soundLocation)
580 if (copyThread !=
null)
585 uri = ResolveUri(soundLocation);
586 this.soundLocation = soundLocation;
590 if (!
string.IsNullOrEmpty(soundLocation))
592 throw new UriFormatException(SR.GetString(
"SoundAPIBadSoundLocation"));
599 isLoadCompleted =
false;
603 private void SetupStream(
Stream stream)
605 if (copyThread !=
null)
610 this.stream = stream;
611 soundLocation =
string.Empty;
614 isLoadCompleted =
false;
624 IntSecurity.SafeSubWindows.Demand();
625 UnsafeNativeMethods.PlaySound((
byte[])
null,
IntPtr.
Zero, 64);
639 ((
EventHandler)base.Events[EventSoundLocationChanged])?.Invoke(
this, e);
646 ((
EventHandler)base.Events[EventStreamChanged])?.Invoke(
this, e);
649 private void WorkerThread()
653 if (uri !=
null && !uri.
IsFile && stream ==
null)
659 streamData =
new byte[1024];
660 int num = stream.
Read(streamData, currentPos, 1024);
665 if (streamData.Length < currentPos + 1024)
667 byte[] destinationArray =
new byte[streamData.Length * 2];
668 Array.
Copy(streamData, destinationArray, streamData.Length);
669 streamData = destinationArray;
671 num = stream.
Read(streamData, currentPos, 1024);
674 lastLoadException =
null;
678 Exception ex2 = lastLoadException = ex;
680 if (!doesLoadAppearSynchronous)
684 isLoadCompleted =
true;
688 private unsafe
void ValidateSoundFile(
string fileName)
690 NativeMethods.MMCKINFO mMCKINFO =
new NativeMethods.MMCKINFO();
691 NativeMethods.MMCKINFO mMCKINFO2 =
new NativeMethods.MMCKINFO();
692 NativeMethods.WAVEFORMATEX wAVEFORMATEX =
null;
693 IntPtr intPtr = UnsafeNativeMethods.mmioOpen(fileName, IntPtr.Zero, 65536);
694 if (intPtr == IntPtr.Zero)
700 mMCKINFO.fccType = mmioFOURCC(
'W',
'A',
'V',
'E');
701 if (UnsafeNativeMethods.mmioDescend(intPtr, mMCKINFO,
null, 32) != 0)
703 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveFile", soundLocation));
705 while (UnsafeNativeMethods.mmioDescend(intPtr, mMCKINFO2, mMCKINFO, 0) == 0)
707 if (mMCKINFO2.dwDataOffset + mMCKINFO2.cksize > mMCKINFO.dwDataOffset + mMCKINFO.cksize)
709 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
711 if (mMCKINFO2.ckID == mmioFOURCC(
'f',
'm',
't',
' ') && wAVEFORMATEX ==
null)
713 int num = mMCKINFO2.cksize;
714 if (num <
Marshal.
SizeOf(typeof(NativeMethods.WAVEFORMATEX)))
718 wAVEFORMATEX =
new NativeMethods.WAVEFORMATEX();
719 byte[] array =
new byte[num];
720 if (UnsafeNativeMethods.mmioRead(intPtr, array, num) != num)
722 throw new InvalidOperationException(SR.GetString(
"SoundAPIReadError", soundLocation));
726 byte[] array2 = array;
727 fixed (
byte* value = array2)
736 UnsafeNativeMethods.mmioAscend(intPtr, mMCKINFO2, 0);
738 if (wAVEFORMATEX ==
null)
740 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
742 if (wAVEFORMATEX.wFormatTag != 1 && wAVEFORMATEX.wFormatTag != 2 && wAVEFORMATEX.wFormatTag != 3)
744 throw new InvalidOperationException(SR.GetString(
"SoundAPIFormatNotSupported"));
749 if (intPtr != IntPtr.Zero)
751 UnsafeNativeMethods.mmioClose(intPtr, 0);
756 private static void ValidateSoundData(
byte[] data)
761 if (data.Length < 12)
763 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
765 if (data[0] != 82 || data[1] != 73 || data[2] != 70 || data[3] != 70)
767 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
769 if (data[8] != 87 || data[9] != 65 || data[10] != 86 || data[11] != 69)
771 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
774 int num3 = data.Length;
775 while (!flag && num < num3 - 8)
777 if (data[num] == 102 && data[num + 1] == 109 && data[num + 2] == 116 && data[num + 3] == 32)
780 int num4 = BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]);
785 if (num3 < num + 8 + num6 - 1)
787 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
789 short num7 = BytesToInt16(data[num + 8 + num6 - 1], data[num + 8 + num6 - 2]);
790 if (num7 + num6 != num4)
792 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
797 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
799 num2 = BytesToInt16(data[num + 9], data[num + 8]);
804 num += 8 + BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]);
809 throw new InvalidOperationException(SR.GetString(
"SoundAPIInvalidWaveHeader"));
811 if (num2 != 1 && num2 != 2 && num2 != 3)
813 throw new InvalidOperationException(SR.GetString(
"SoundAPIFormatNotSupported"));
817 private static short BytesToInt16(
byte ch0,
byte ch1)
819 int num = ch1 | (ch0 << 8);
823 private static int BytesToInt(
byte ch0,
byte ch1,
byte ch2,
byte ch3)
825 return mmioFOURCC((
char)ch3, (
char)ch2, (
char)ch1, (
char)ch0);
828 private static int mmioFOURCC(
char ch0,
char ch1,
char ch2,
char ch3)
832 num |= (int)((uint)ch1 << 8);
833 num |= (int)((uint)ch2 << 16);
834 return num | (int)((uint)ch3 << 24);
843 if (!
string.IsNullOrEmpty(soundLocation))
845 info.AddValue(
"SoundLocation", soundLocation);
849 info.AddValue(
"Stream", stream);
851 info.AddValue(
"LoadTimeout", loadTimeout);
Exposes the user interface.
Provides concurrency management for classes that support asynchronous method calls....
Users can only use F:System.Security.Permissions.UIPermissionWindow.SafeSubWindows for drawing,...
Describes a set of security permissions applied to code. This class cannot be inherited.
FileIOPermissionAccess
Specifies the type of file access requested.
abstract int Read([In] [Out] byte[] buffer, int offset, int count)
When overridden in a derived class, reads a sequence of bytes from the current stream and advances th...
delegate void SendOrPostCallback(object state)
Represents a method to be called when a message is to be dispatched to a synchronization context.
Tracks the lifetime of an asynchronous operation.
string LocalPath
Gets a local operating-system representation of a file name.
abstract bool CanSeek
When overridden in a derived class, gets a value indicating whether the current stream supports seeki...
NetworkAccess
Specifies network access permissions.
bool Set()
Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
bool IsFile
Gets a value indicating whether the specified T:System.Uri is a file URI.
Makes a request to a Uniform Resource Identifier (URI). This is an abstract class.
LayoutKind
Controls the layout of an object when exported to unmanaged code.
ThreadState ThreadState
Gets a value containing the states of the current thread.
The exception that is thrown when the value of an argument is outside the allowable range of values a...
static int SizeOf(object structure)
Returns the unmanaged size of an object in bytes.
UIPermissionWindow
Specifies the type of windows that code is allowed to use.
SerializationInfoEnumerator GetEnumerator()
Returns a T:System.Runtime.Serialization.SerializationInfoEnumerator used to iterate through the name...
Represents the base class for classes that contain event data, and provides a value to use for events...
Describes the source and destination of a given serialized stream, and provides an additional caller-...
virtual int Timeout
Gets or sets the length of time, in milliseconds, before the request times out.
virtual bool WaitOne(int millisecondsTimeout, bool exitContext)
Blocks the current thread until the current T:System.Threading.WaitHandle receives a signal,...
SeekOrigin
Specifies the position in a stream to use for seeking.
Provides data for the MethodNameCompleted event.
SecurityAction
Specifies the security actions that can be performed using declarative security.
string AbsolutePath
Gets the absolute path of the URI.
Provides a response from a Uniform Resource Identifier (URI). This is an abstract class.
static readonly EventArgs Empty
Provides a value to use with events that do not have event data.
Provides properties and instance methods for the creation, copying, deletion, moving,...
UnmanagedType
Identifies how to marshal parameters or fields to unmanaged code.
delegate void EventHandler(object sender, EventArgs e)
Represents the method that will handle an event that has no event data.
Controls rights to access HTTP Internet resources.
Controls the permissions related to user interfaces and the Clipboard. This class cannot be inherited...
Defines the underlying structure of all code access permissions.
A platform-specific type that is used to represent a pointer or a handle.
Notifies one or more waiting threads that an event has occurred. This class cannot be inherited.
Provides the base implementation for the T:System.ComponentModel.IComponent interface and enables obj...
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks,...
static string GetFullPath(string path)
Returns the absolute path for the specified path string.
abstract long Seek(long offset, SeekOrigin origin)
When overridden in a derived class, sets the position within the current stream.
FileIOPermissionAccess AllFiles
Gets or sets the permitted access to all files.
CharSet
Dictates which character set marshaled strings should use.
Stores all the data needed to serialize or deserialize an object. This class cannot be inherited.
static void RevertAssert()
Causes any previous M:System.Security.CodeAccessPermission.Assert for the current frame to be removed...
void Start()
Causes the operating system to change the state of the current instance to F:System....
void Abort(object stateInfo)
Raises a T:System.Threading.ThreadAbortException in the thread on which it is invoked,...
void Demand()
Forces a T:System.Security.SecurityException at run time if all callers higher in the call stack have...
abstract long Length
When overridden in a derived class, gets the length in bytes of the stream.
The exception that is thrown when an attempt to access a file that does not exist on disk fails.
static void Copy(Array sourceArray, Array destinationArray, int length)
Copies a range of elements from an T:System.Array starting at the first element and pastes them into ...
Allows an object to control its own serialization and deserialization.
static void PtrToStructure(IntPtr ptr, object structure)
Marshals data from an unmanaged block of memory to a managed object.
PermissionState
Specifies whether a permission should have all or no access to resources at creation.
Represents errors that occur during application execution.To browse the .NET Framework source code fo...
static AsyncOperation CreateOperation(object userSuppliedState)
Returns an T:System.ComponentModel.AsyncOperation for tracking the duration of a particular asynchron...
static readonly IntPtr Zero
A read-only field that represents a pointer or handle that has been initialized to zero.
void PostOperationCompleted(SendOrPostCallback d, object arg)
Ends the lifetime of an asynchronous operation.
Holds the value, T:System.Type, and name of a serialized object.
virtual WebResponse GetResponse()
When overridden in a descendant class, returns a response to an Internet request.
Controls the ability to access files and folders. This class cannot be inherited.
SecurityPermissionFlag
Specifies access flags for the security permission object.
Provides an object representation of a uniform resource identifier (URI) and easy access to the parts...
virtual Stream GetResponseStream()
When overridden in a descendant class, returns the data stream from the Internet resource.
Provides a formatter-friendly mechanism for parsing the data in T:System.Runtime.Serialization....
override bool Exists
Gets a value indicating whether a file exists.
delegate void AsyncCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
Represents the method that will handle the MethodNameCompleted event of an asynchronous operation.
object Value
Gets the value contained in the object.
void GetObjectData(SerializationInfo info, StreamingContext context)
Populates a T:System.Runtime.Serialization.SerializationInfo with the data needed to serialize the ta...
string Name
Gets the name of the object.
Performs operations on T:System.String instances that contain file or directory path information....
bool Reset()
Sets the state of the event to nonsignaled, causing threads to block.
bool MoveNext()
Updates the enumerator to the next item.
Provides a generic view of a sequence of bytes. This is an abstract class.To browse the ....
Creates and controls a thread, sets its priority, and gets its status.