1 /*
2  * PROJECT:     ReactOS
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * PURPOSE:     Audio Service List Manager
5  * COPYRIGHT:   Copyright 2007 Andrew Greenwood
6  */
7 
8 #include "audiosrv.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 /*
14     Device descriptor
15 */
16 
17 VOID*
18 CreateDeviceDescriptor(WCHAR* path, BOOL is_enabled)
19 {
20     PnP_AudioDevice* device;
21 
22     int path_length = WideStringSize(path);
23     int size = sizeof(PnP_AudioDevice) + path_length;
24 
25     device = malloc(size);
26     if (! device)
27     {
28         DPRINT("Failed to malloc device descriptor\n");
29         return NULL;
30     }
31 
32     device->enabled = is_enabled;
33     memcpy(device->path, path, path_length);
34 
35     return device;
36 }
37 
38 
39 /*
40     Device list (manager-side)
41 
42     The device list is stored in some shared-memory, with a named, global
43     mutex to provide a locking mechanism (to avoid it from being updated
44     whilst being read).
45 */
46 
47 static HANDLE device_list_file = NULL;
48 static PnP_AudioHeader* audio_device_list = NULL;
49 
50 
51 /*
52     TODO: Detect duplicate entries and ignore them! (In case we receive
53     a PnP event for an existing device...)
54 */
55 
56 BOOL
57 AppendAudioDeviceToList(PnP_AudioDevice* device)
58 {
59     int device_info_size;
60 
61     /* Figure out the actual structure size */
62     device_info_size = sizeof(PnP_AudioDevice);
63     device_info_size += WideStringSize(device->path);
64 
65     LockAudioDeviceList();
66 
67     /* We DON'T want to overshoot the end of the buffer! */
68     if (audio_device_list->size + device_info_size > audio_device_list->max_size)
69     {
70         /*DPRINT("failed, max_size would be exceeded\n");*/
71 
72         UnlockAudioDeviceList();
73 
74         return FALSE;
75     }
76 
77     /* Commit the device descriptor to the list */
78     memcpy((char*)audio_device_list + audio_device_list->size,
79            device,
80            device_info_size);
81 
82     /* Update the header */
83     audio_device_list->device_count ++;
84     audio_device_list->size += device_info_size;
85 
86     UnlockAudioDeviceList();
87 
88     DPRINT("Device added to list\n");
89 
90     return TRUE;
91 }
92 
93 BOOL
94 CreateAudioDeviceList(DWORD max_size)
95 {
96     if (!InitializeAudioDeviceListLock())
97     {
98         /*DPRINT("Failed\n");*/
99         return FALSE;
100     }
101 
102     /* Preliminary locking - the list memory will likely be a big
103        buffer of gibberish at this point so we don't want anyone
104        turning up before we're ready... */
105     LockAudioDeviceList();
106 
107     DPRINT("Creating file mapping\n");
108     /* Expose our device list to the world */
109     device_list_file = CreateFileMappingW(INVALID_HANDLE_VALUE,
110                                           NULL,
111                                           PAGE_READWRITE,
112                                           0,
113                                           max_size,
114                                           AUDIO_LIST_NAME);
115     if (!device_list_file)
116     {
117         DPRINT("Creation of audio device list failed (err %d)\n", GetLastError());
118 
119         UnlockAudioDeviceList();
120         KillAudioDeviceListLock();
121 
122         return FALSE;
123     }
124 
125     DPRINT("Mapping view of file\n");
126     /* Of course, we'll need to access the list ourselves */
127     audio_device_list = MapViewOfFile(device_list_file,
128                                       FILE_MAP_WRITE,
129                                       0,
130                                       0,
131                                       max_size);
132     if (!audio_device_list)
133     {
134         DPRINT("MapViewOfFile FAILED (err %d)\n", GetLastError());
135 
136         CloseHandle(device_list_file);
137         device_list_file = NULL;
138 
139         UnlockAudioDeviceList();
140         KillAudioDeviceListLock();
141 
142         return FALSE;
143     }
144 
145     /* Clear the mem to avoid any random stray data */
146     memset(audio_device_list, 0, max_size);
147 
148     /* Don't want devices to overwrite the list! */
149     audio_device_list->size = sizeof(PnP_AudioHeader);
150     audio_device_list->max_size = max_size;
151     audio_device_list->device_count = 0;
152 
153     UnlockAudioDeviceList();
154 
155     DPRINT("Device list created\n");
156 
157     return TRUE;
158 }
159 
160 VOID
161 DestroyAudioDeviceList(VOID)
162 {
163     DPRINT("Destroying device list\n");
164 
165     LockAudioDeviceList();
166 
167     /*DPRINT("Unmapping view\n");*/
168     UnmapViewOfFile(audio_device_list);
169     audio_device_list = NULL;
170 
171     /*DPRINT("Closing memory mapped file\n");*/
172     CloseHandle(device_list_file);
173     device_list_file = NULL;
174 
175     UnlockAudioDeviceList();
176 
177     /*DPRINT("Killing devlist lock\n");*/
178     KillAudioDeviceListLock();
179 }
180