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