1 /*
2  * PROJECT:     ReactOS Sound System "MME Buddy" Library
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        lib/sound/mmebuddy/reentrancy.c
5  *
6  * PURPOSE:     Provides entry-point mutex guards.
7  *
8  * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 */
10 
11 #include "precomp.h"
12 
13 HANDLE EntrypointMutexes[SOUND_DEVICE_TYPES];
14 
15 /*
16     Creates a set of mutexes which are used for the purpose of guarding the
17     device-type specific module entry-points. If any of these fail creation,
18     all of them will be destroyed and the failure reported.
19 */
20 MMRESULT
21 InitEntrypointMutexes()
22 {
23     UCHAR i;
24     MMRESULT Result = MMSYSERR_NOERROR;
25 
26     /* Blank all entries ni the table first */
27     for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i )
28     {
29         EntrypointMutexes[i] = NULL;
30     }
31 
32     /* Now create the mutexes */
33     for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i )
34     {
35         EntrypointMutexes[i] = CreateMutex(NULL, FALSE, NULL);
36 
37         if ( ! EntrypointMutexes[i] )
38         {
39             Result = Win32ErrorToMmResult(GetLastError());
40 
41             /* Clean up any mutexes we successfully created */
42             CleanupEntrypointMutexes();
43             break;
44         }
45     }
46 
47     return Result;
48 }
49 
50 /*
51     Cleans up any of the entry-point guard mutexes. This will only close the
52     handles of mutexes which have been created, making it safe for use as a
53     cleanup routine even within the InitEntrypointMutexes routine above.
54 */
55 VOID
56 CleanupEntrypointMutexes()
57 {
58     UCHAR i;
59 
60     /* Only clean up a mutex if it actually exists */
61     for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i )
62     {
63         if ( EntrypointMutexes[i] )
64         {
65             CloseHandle(EntrypointMutexes[i]);
66             EntrypointMutexes[i] = NULL;
67         }
68     }
69 }
70 
71 /*
72     Grabs an entry-point mutex.
73 */
74 VOID
75 AcquireEntrypointMutex(
76     IN  MMDEVICE_TYPE DeviceType)
77 {
78     UCHAR i;
79 
80     SND_ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
81     i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType);
82 
83     SND_ASSERT( EntrypointMutexes[i] );
84 
85     WaitForSingleObject(EntrypointMutexes[i], INFINITE);
86 }
87 
88 /*
89     Releases an entry-point mutex.
90 */
91 VOID
92 ReleaseEntrypointMutex(
93     IN  MMDEVICE_TYPE DeviceType)
94 {
95     UCHAR i;
96 
97     SND_ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
98     i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType);
99 
100     SND_ASSERT( EntrypointMutexes[i] );
101 
102     ReleaseMutex(EntrypointMutexes[i]);
103 }
104