Implemented _getdllprocaddr(), it cannot be simply a forward to
[wine] / dlls / msacm / internal.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  *      MSACM32 library
5  *
6  *      Copyright 1998  Patrik Stridvall
7  *                1999  Eric Pouech
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <string.h>
25
26 #include "winbase.h"
27 #include "windef.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winerror.h"
31 #include "winreg.h"
32 #include "mmsystem.h"
33 #include "msacm.h"
34 #include "msacmdrv.h"
35 #include "wineacm.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
39
40 /**********************************************************************/
41
42 HANDLE MSACM_hHeap = NULL;
43 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
44 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
45
46 #if 0
47 /***********************************************************************
48  *           MSACM_DumpCache
49  */
50 static  void MSACM_DumpCache(PWINE_ACMDRIVERID padid)
51 {
52     unsigned    i;
53
54     TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
55           padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
56     for (i = 0; i < padid->cache->cFormatTags; i++) {
57         TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
58               padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
59     }
60 }
61 #endif
62
63 /***********************************************************************
64  *           MSACM_FindFormatTagInCache                 [internal]
65  *
66  *      Returns TRUE is the format tag fmtTag is present in the cache.
67  *      If so, idx is set to its index.
68  */
69 BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
70 {
71     unsigned    i;
72
73     for (i = 0; i < padid->cFormatTags; i++) {
74         if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
75             if (idx) *idx = i;
76             return TRUE;
77         }
78     }
79     return FALSE;
80 }
81
82 /***********************************************************************
83  *           MSACM_FillCache
84  */
85 static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid)
86 {
87     HACMDRIVER                  had = 0;
88     int                         ntag;
89     ACMDRIVERDETAILSW           add;
90     ACMFORMATTAGDETAILSW        aftd;
91
92     if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
93         return FALSE;
94
95     padid->aFormatTag = NULL;
96     add.cbStruct = sizeof(add);
97     if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add,  0))
98         goto errCleanUp;
99
100     if (add.cFormatTags > 0) {
101         padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY,
102                                       add.cFormatTags * sizeof(padid->aFormatTag[0]));
103         if (!padid->aFormatTag) goto errCleanUp;
104     }
105
106     padid->cFormatTags = add.cFormatTags;
107     padid->cFilterTags = add.cFilterTags;
108     padid->fdwSupport  = add.fdwSupport;
109
110     aftd.cbStruct = sizeof(aftd);
111
112     for (ntag = 0; ntag < add.cFormatTags; ntag++) {
113         aftd.dwFormatTagIndex = ntag;
114         if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&aftd, ACM_FORMATTAGDETAILSF_INDEX)) {
115             TRACE("IIOs (%s)\n", padid->pszDriverAlias);
116             goto errCleanUp;
117         }
118         padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
119         padid->aFormatTag[ntag].cbwfx = aftd.cbFormatSize;
120     }
121
122     acmDriverClose(had, 0);
123
124     return TRUE;
125
126 errCleanUp:
127     if (had) acmDriverClose(had, 0);
128     HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
129     padid->aFormatTag = NULL;
130     return FALSE;
131 }
132
133 /***********************************************************************
134  *           MSACM_GetRegistryKey
135  */
136 static  LPSTR   MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
137 {
138     static const char*  baseKey = "Software\\Microsoft\\AudioCompressionManager\\DriverCache\\";
139     LPSTR       ret;
140     int         len;
141
142     if (!padid->pszDriverAlias) {
143         ERR("No alias needed for registry entry\n");
144         return NULL;
145     }
146     len = strlen(baseKey);
147     ret = HeapAlloc(MSACM_hHeap, 0, len + strlen(padid->pszDriverAlias) + 1);
148     if (!ret) return NULL;
149
150     strcpy(ret, baseKey);
151     strcpy(ret + len, padid->pszDriverAlias);
152     CharLowerA(ret + len);
153     return ret;
154 }
155
156 /***********************************************************************
157  *           MSACM_ReadCache
158  */
159 static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
160 {
161     LPSTR       key = MSACM_GetRegistryKey(padid);
162     HKEY        hKey;
163     DWORD       type, size;
164
165     if (!key) return FALSE;
166
167     padid->aFormatTag = NULL;
168
169     if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
170         goto errCleanUp;
171
172     size = sizeof(padid->cFormatTags);
173     if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
174         goto errCleanUp;
175     size = sizeof(padid->cFilterTags);
176     if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
177         goto errCleanUp;
178     size = sizeof(padid->fdwSupport);
179     if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
180         goto errCleanUp;
181
182     if (padid->cFormatTags > 0) {
183         size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
184         padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
185         if (!padid->aFormatTag) goto errCleanUp;
186         if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
187             goto errCleanUp;
188     }
189     HeapFree(MSACM_hHeap, 0, key);
190     return TRUE;
191
192  errCleanUp:
193     HeapFree(MSACM_hHeap, 0, key);
194     HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
195     padid->aFormatTag = NULL;
196     RegCloseKey(hKey);
197     return FALSE;
198 }
199
200 /***********************************************************************
201  *           MSACM_WriteCache
202  */
203 static  BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
204 {
205     LPSTR       key = MSACM_GetRegistryKey(padid);
206     HKEY        hKey;
207
208     if (!key) return FALSE;
209
210     if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
211         goto errCleanUp;
212
213     if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (void*)&padid->cFormatTags, sizeof(DWORD)))
214         goto errCleanUp;
215     if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (void*)&padid->cFilterTags, sizeof(DWORD)))
216         goto errCleanUp;
217     if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (void*)&padid->fdwSupport, sizeof(DWORD)))
218         goto errCleanUp;
219     if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY,
220                        (void*)padid->aFormatTag,
221                        padid->cFormatTags * sizeof(padid->aFormatTag[0])))
222         goto errCleanUp;
223     HeapFree(MSACM_hHeap, 0, key);
224     return TRUE;
225
226  errCleanUp:
227     HeapFree(MSACM_hHeap, 0, key);
228     return FALSE;
229 }
230
231 /***********************************************************************
232  *           MSACM_RegisterDriver()
233  */
234 PWINE_ACMDRIVERID MSACM_RegisterDriver(LPSTR pszDriverAlias, LPSTR pszFileName,
235                                        HINSTANCE hinstModule)
236 {
237     PWINE_ACMDRIVERID   padid;
238
239     TRACE("('%s', '%s', %p)\n", pszDriverAlias, pszFileName, hinstModule);
240
241     padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
242     padid->obj.dwType = WINE_ACMOBJ_DRIVERID;
243     padid->obj.pACMDriverID = padid;
244     padid->pszDriverAlias = NULL;
245     if (pszDriverAlias)
246     {
247         padid->pszDriverAlias = HeapAlloc( MSACM_hHeap, 0, strlen(pszDriverAlias)+1 );
248         strcpy( padid->pszDriverAlias, pszDriverAlias );
249     }
250     padid->pszFileName = NULL;
251     if (pszFileName)
252     {
253         padid->pszFileName = HeapAlloc( MSACM_hHeap, 0, strlen(pszFileName)+1 );
254         strcpy( padid->pszFileName, pszFileName );
255     }
256     padid->hInstModule = hinstModule;
257
258     padid->pACMDriverList = NULL;
259     padid->pNextACMDriverID = NULL;
260     padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
261     if (MSACM_pLastACMDriverID)
262         MSACM_pLastACMDriverID->pNextACMDriverID = padid;
263     MSACM_pLastACMDriverID = padid;
264     if (!MSACM_pFirstACMDriverID)
265         MSACM_pFirstACMDriverID = padid;
266     /* disable the driver if we cannot load the cache */
267     if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
268         WARN("Couldn't load cache for ACM driver (%s)\n", pszFileName);
269         MSACM_UnregisterDriver(padid);
270         return NULL;
271     }
272     return padid;
273 }
274
275 /***********************************************************************
276  *           MSACM_RegisterAllDrivers()
277  */
278 void MSACM_RegisterAllDrivers(void)
279 {
280     LPSTR pszBuffer;
281     DWORD dwBufferLength;
282
283     /* FIXME
284      *  What if the user edits system.ini while the program is running?
285      *  Does Windows handle that?
286      */
287     if (MSACM_pFirstACMDriverID)
288         return;
289
290     /* FIXME: Does not work! How do I determine the section length? */
291     dwBufferLength = 1024;
292 /* EPP  GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
293
294     pszBuffer = (LPSTR) HeapAlloc(MSACM_hHeap, 0, dwBufferLength);
295     if (GetPrivateProfileSectionA("drivers32", pszBuffer, dwBufferLength, "system.ini")) {
296         char* s = pszBuffer;
297         while (*s) {
298             if (!strncasecmp("MSACM.", s, 6)) {
299                 char *s2 = s;
300                 while (*s2 != '\0' && *s2 != '=') s2++;
301                 if (*s2) {
302                     *s2 = '\0';
303                     MSACM_RegisterDriver(s, s2 + 1, 0);
304                     *s2 = '=';
305                 }
306             }
307             s += strlen(s) + 1; /* Either next char or \0 */
308         }
309     }
310
311     HeapFree(MSACM_hHeap, 0, pszBuffer);
312
313     MSACM_RegisterDriver("msacm32.dll", "msacm32.dll", 0);
314 }
315
316 /***********************************************************************
317  *           MSACM_UnregisterDriver()
318  */
319 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
320 {
321     PWINE_ACMDRIVERID pNextACMDriverID;
322
323     while (p->pACMDriverList)
324         acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
325
326     if (p->pszDriverAlias)
327         HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
328     if (p->pszFileName)
329         HeapFree(MSACM_hHeap, 0, p->pszFileName);
330     HeapFree(MSACM_hHeap, 0, p->aFormatTag);
331
332     if (p == MSACM_pFirstACMDriverID)
333         MSACM_pFirstACMDriverID = p->pNextACMDriverID;
334     if (p == MSACM_pLastACMDriverID)
335         MSACM_pLastACMDriverID = p->pPrevACMDriverID;
336
337     if (p->pPrevACMDriverID)
338         p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
339     if (p->pNextACMDriverID)
340         p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
341
342     pNextACMDriverID = p->pNextACMDriverID;
343
344     HeapFree(MSACM_hHeap, 0, p);
345
346     return pNextACMDriverID;
347 }
348
349 /***********************************************************************
350  *           MSACM_UnregisterAllDrivers()
351  */
352 void MSACM_UnregisterAllDrivers(void)
353 {
354     PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID;
355
356     while (p) {
357         MSACM_WriteCache(p);
358         p = MSACM_UnregisterDriver(p);
359     }
360 }
361
362 /***********************************************************************
363  *           MSACM_GetObj()
364  */
365 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type)
366 {
367     PWINE_ACMOBJ        pao = (PWINE_ACMOBJ)hObj;
368
369     if (pao == NULL || IsBadReadPtr(pao, sizeof(WINE_ACMOBJ)) ||
370         ((type != WINE_ACMOBJ_DONTCARE) && (type != pao->dwType)))
371         return NULL;
372     return pao;
373 }
374
375 /***********************************************************************
376  *           MSACM_GetDriverID()
377  */
378 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
379 {
380     return (PWINE_ACMDRIVERID)MSACM_GetObj((HACMOBJ)hDriverID, WINE_ACMOBJ_DRIVERID);
381 }
382
383 /***********************************************************************
384  *           MSACM_GetDriver()
385  */
386 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
387 {
388     return (PWINE_ACMDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_DRIVER);
389 }
390
391 /***********************************************************************
392  *           MSACM_Message()
393  */
394 MMRESULT MSACM_Message(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
395 {
396     PWINE_ACMDRIVER     pad = MSACM_GetDriver(had);
397
398     return pad ? SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2) : MMSYSERR_INVALHANDLE;
399 }