dmloader: complete rewrite and full implementation.
[wine] / dlls / msacm / driver.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 "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28 #include <stdio.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winnls.h"
36 #include "winreg.h"
37 #include "mmsystem.h"
38 #include "mmreg.h"
39 #include "msacm.h"
40 #include "msacmdrv.h"
41 #include "wineacm.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
45
46 /***********************************************************************
47  *           acmDriverAddA (MSACM32.@)
48  */
49 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
50                               LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
51 {
52     if (!phadid)
53         return MMSYSERR_INVALPARAM;
54
55     /* Check if any unknown flags */
56     if (fdwAdd &
57         ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
58           ACM_DRIVERADDF_GLOBAL))
59         return MMSYSERR_INVALFLAG;
60
61     /* Check if any incompatible flags */
62     if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
63         (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
64         return MMSYSERR_INVALFLAG;
65
66     /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
67      * LoadDriver on it, to be sure we can call SendDriverMessage on the
68      * hDrvr handle.
69      */
70     *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, hinstModule);
71
72     /* FIXME: lParam, dwPriority and fdwAdd ignored */
73
74     return MMSYSERR_NOERROR;
75 }
76
77 /***********************************************************************
78  *           acmDriverAddW (MSACM32.@)
79  * FIXME
80  *   Not implemented
81  */
82 MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule,
83                               LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
84 {
85     FIXME("(%p, %p, %ld, %ld, %ld): stub\n",
86           phadid, hinstModule, lParam, dwPriority, fdwAdd);
87
88     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
89     return MMSYSERR_ERROR;
90 }
91
92 /***********************************************************************
93  *           acmDriverClose (MSACM32.@)
94  */
95 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
96 {
97     PWINE_ACMDRIVER     pad;
98     PWINE_ACMDRIVERID   padid;
99     PWINE_ACMDRIVER*    tpad;
100
101     if (fdwClose)
102         return MMSYSERR_INVALFLAG;
103
104     pad = MSACM_GetDriver(had);
105     if (!pad)
106         return MMSYSERR_INVALHANDLE;
107
108     padid = pad->obj.pACMDriverID;
109
110     /* remove driver from list */
111     for (tpad = &(padid->pACMDriverList); *tpad; *tpad = (*tpad)->pNextACMDriver) {
112         if (*tpad == pad) {
113             *tpad = (*tpad)->pNextACMDriver;
114             break;
115         }
116     }
117
118     /* close driver if it has been opened */
119     if (pad->hDrvr && !padid->hInstModule)
120         CloseDriver(pad->hDrvr, 0, 0);
121
122     HeapFree(MSACM_hHeap, 0, pad);
123
124     return MMSYSERR_NOERROR;
125 }
126
127 /***********************************************************************
128  *           acmDriverDetailsA (MSACM32.@)
129  */
130 MMRESULT WINAPI acmDriverDetailsA(HACMDRIVERID hadid, PACMDRIVERDETAILSA padd, DWORD fdwDetails)
131 {
132     MMRESULT mmr;
133     ACMDRIVERDETAILSW   addw;
134
135     if (!padd)
136         return MMSYSERR_INVALPARAM;
137
138     if (padd->cbStruct < 4)
139         return MMSYSERR_INVALPARAM;
140
141     addw.cbStruct = sizeof(addw);
142     mmr = acmDriverDetailsW(hadid, &addw, fdwDetails);
143     if (mmr == 0) {
144         ACMDRIVERDETAILSA padda;
145
146         padda.fccType = addw.fccType;
147         padda.fccComp = addw.fccComp;
148         padda.wMid = addw.wMid;
149         padda.wPid = addw.wPid;
150         padda.vdwACM = addw.vdwACM;
151         padda.vdwDriver = addw.vdwDriver;
152         padda.fdwSupport = addw.fdwSupport;
153         padda.cFormatTags = addw.cFormatTags;
154         padda.cFilterTags = addw.cFilterTags;
155         padda.hicon = addw.hicon;
156         WideCharToMultiByte( CP_ACP, 0, addw.szShortName, -1, padda.szShortName,
157                              sizeof(padda.szShortName), NULL, NULL );
158         WideCharToMultiByte( CP_ACP, 0, addw.szLongName, -1, padda.szLongName,
159                              sizeof(padda.szLongName), NULL, NULL );
160         WideCharToMultiByte( CP_ACP, 0, addw.szCopyright, -1, padda.szCopyright,
161                              sizeof(padda.szCopyright), NULL, NULL );
162         WideCharToMultiByte( CP_ACP, 0, addw.szLicensing, -1, padda.szLicensing,
163                              sizeof(padda.szLicensing), NULL, NULL );
164         WideCharToMultiByte( CP_ACP, 0, addw.szFeatures, -1, padda.szFeatures,
165                              sizeof(padda.szFeatures), NULL, NULL );
166         memcpy(padd, &padda, min(padd->cbStruct, sizeof(*padd)));
167     }
168     return mmr;
169 }
170
171 /***********************************************************************
172  *           acmDriverDetailsW (MSACM32.@)
173  */
174 MMRESULT WINAPI acmDriverDetailsW(HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails)
175 {
176     HACMDRIVER acmDrvr;
177     MMRESULT mmr;
178
179     if (!padd)
180         return MMSYSERR_INVALPARAM;
181
182     if (padd->cbStruct < 4)
183         return MMSYSERR_INVALPARAM;
184
185     if (fdwDetails)
186         return MMSYSERR_INVALFLAG;
187
188     mmr = acmDriverOpen(&acmDrvr, hadid, 0);
189     if (mmr == MMSYSERR_NOERROR) {
190         ACMDRIVERDETAILSW paddw;
191         mmr = (MMRESULT)MSACM_Message(acmDrvr, ACMDM_DRIVER_DETAILS, (LPARAM)&paddw,  0);
192
193         acmDriverClose(acmDrvr, 0);
194         memcpy(padd, &paddw, min(padd->cbStruct, sizeof(*padd)));
195     }
196
197     return mmr;
198 }
199
200 /***********************************************************************
201  *           acmDriverEnum (MSACM32.@)
202  */
203 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
204 {
205     PWINE_ACMDRIVERID   padid;
206     DWORD               fdwSupport;
207
208     if (!fnCallback) return MMSYSERR_INVALPARAM;
209
210     if (fdwEnum & ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED))
211         return MMSYSERR_INVALFLAG;
212
213     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
214         fdwSupport = padid->fdwSupport;
215
216         if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) {
217             if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
218                 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
219             else
220                 continue;
221         }
222         if (!(*fnCallback)((HACMDRIVERID)padid, dwInstance, fdwSupport))
223             break;
224     }
225
226     return MMSYSERR_NOERROR;
227 }
228
229 /***********************************************************************
230  *           acmDriverID (MSACM32.@)
231  */
232 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
233 {
234     PWINE_ACMOBJ pao;
235
236     if (fdwDriverID)
237         return MMSYSERR_INVALFLAG;
238
239     pao = MSACM_GetObj(hao, WINE_ACMOBJ_DONTCARE);
240     if (!pao)
241         return MMSYSERR_INVALHANDLE;
242
243     if (!phadid)
244         return MMSYSERR_INVALPARAM;
245
246     *phadid = (HACMDRIVERID) pao->pACMDriverID;
247
248     return MMSYSERR_NOERROR;
249 }
250
251 /***********************************************************************
252  *           acmDriverMessage (MSACM32.@)
253  *
254  */
255 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
256 {
257     if ((uMsg >= ACMDM_USER && uMsg < ACMDM_RESERVED_LOW) ||
258         uMsg == ACMDM_DRIVER_ABOUT ||
259         uMsg == DRV_QUERYCONFIGURE ||
260         uMsg == DRV_CONFIGURE)
261         return MSACM_Message(had, uMsg, lParam1, lParam2);
262     return MMSYSERR_INVALPARAM;
263 }
264
265 /***********************************************************************
266  *           acmDriverOpen (MSACM32.@)
267  */
268 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
269 {
270     PWINE_ACMDRIVERID   padid;
271     PWINE_ACMDRIVER     pad = NULL;
272     MMRESULT            ret;
273
274     TRACE("(%p, %p, %08lu)\n", phad, hadid, fdwOpen);
275
276     if (!phad)
277         return MMSYSERR_INVALPARAM;
278
279     if (fdwOpen)
280         return MMSYSERR_INVALFLAG;
281
282     padid = MSACM_GetDriverID(hadid);
283     if (!padid)
284         return MMSYSERR_INVALHANDLE;
285
286     pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
287     if (!pad)
288         return MMSYSERR_NOMEM;
289
290     pad->obj.dwType = WINE_ACMOBJ_DRIVER;
291     pad->obj.pACMDriverID = padid;
292
293     if (!(pad->hDrvr = (HDRVR)padid->hInstModule))
294     {
295         ACMDRVOPENDESCW adod;
296         int             len;
297
298         /* this is not an externally added driver... need to actually load it */
299         if (!padid->pszDriverAlias)
300         {
301             ret = MMSYSERR_ERROR;
302             goto gotError;
303         }
304
305         adod.cbStruct = sizeof(adod);
306         adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
307         adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
308         adod.dwVersion = acmGetVersion();
309         adod.dwFlags = fdwOpen;
310         adod.dwError = 0;
311         len = strlen("Drivers32") + 1;
312         adod.pszSectionName = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR));
313         MultiByteToWideChar(CP_ACP, 0, "Drivers32", -1, (LPWSTR)adod.pszSectionName, len);
314         adod.pszAliasName = padid->pszDriverAlias;
315         adod.dnDevNode = 0;
316
317         pad->hDrvr = OpenDriver(padid->pszDriverAlias, NULL, (DWORD)&adod);
318
319         HeapFree(MSACM_hHeap, 0, (LPWSTR)adod.pszSectionName);
320         if (!pad->hDrvr)
321         {
322             ret = adod.dwError;
323             goto gotError;
324         }
325     }
326
327     /* insert new pad at beg of list */
328     pad->pNextACMDriver = padid->pACMDriverList;
329     padid->pACMDriverList = pad;
330
331     /* FIXME: Create a WINE_ACMDRIVER32 */
332     *phad = (HACMDRIVER)pad;
333     TRACE("'%s' => %08lx\n", debugstr_w(padid->pszDriverAlias), (DWORD)pad);
334
335     return MMSYSERR_NOERROR;
336  gotError:
337     if (pad && !pad->hDrvr)
338         HeapFree(MSACM_hHeap, 0, pad);
339     return ret;
340 }
341
342 /***********************************************************************
343  *           acmDriverPriority (MSACM32.@)
344  */
345 MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority)
346 {
347     PWINE_ACMDRIVERID padid;
348     CHAR szSubKey[17];
349     CHAR szBuffer[256];
350     LONG lBufferLength = sizeof(szBuffer);
351     LONG lError;
352     HKEY hPriorityKey;
353     DWORD dwPriorityCounter;
354
355     padid = MSACM_GetDriverID(hadid);
356     if (!padid)
357         return MMSYSERR_INVALHANDLE;
358
359     /* Check for unknown flags */
360     if (fdwPriority &
361         ~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
362           ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END))
363         return MMSYSERR_INVALFLAG;
364
365     /* Check for incompatible flags */
366     if ((fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) &&
367         (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE))
368         return MMSYSERR_INVALFLAG;
369
370     /* Check for incompatible flags */
371     if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) &&
372         (fdwPriority & ACM_DRIVERPRIORITYF_END))
373         return MMSYSERR_INVALFLAG;
374
375     lError = RegOpenKeyA(HKEY_CURRENT_USER,
376                          "Software\\Microsoft\\Multimedia\\"
377                          "Audio Compression Manager\\Priority v4.00",
378                          &hPriorityKey
379                          );
380     /* FIXME: Create key */
381     if (lError != ERROR_SUCCESS)
382         return MMSYSERR_ERROR;
383
384     for (dwPriorityCounter = 1; ; dwPriorityCounter++)  {
385         snprintf(szSubKey, 17, "Priority%ld", dwPriorityCounter);
386         lError = RegQueryValueA(hPriorityKey, szSubKey, szBuffer, &lBufferLength);
387         if (lError != ERROR_SUCCESS)
388             break;
389
390         FIXME("(%p, %ld, %ld): stub (partial)\n",
391               hadid, dwPriority, fdwPriority);
392         break;
393     }
394
395     RegCloseKey(hPriorityKey);
396
397     return MMSYSERR_ERROR;
398 }
399
400 /***********************************************************************
401  *           acmDriverRemove (MSACM32.@)
402  */
403 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
404 {
405     PWINE_ACMDRIVERID padid;
406
407     padid = MSACM_GetDriverID(hadid);
408     if (!padid)
409         return MMSYSERR_INVALHANDLE;
410
411     if (fdwRemove)
412         return MMSYSERR_INVALFLAG;
413
414     MSACM_UnregisterDriver(padid);
415
416     return MMSYSERR_NOERROR;
417 }