1 /**************************************************************************
4 This file will contain an interface to ACM drivers.
5 Its content will be based mainly on wine/dlls/msacm32
6 actually, for audio decompression only the following functions
9 acmStreamOpen ( takes formats of src and dest, returns stream handle )
10 acmStreamPrepareHeader ( takes stream handler and info on data )
11 acmStreamConvert ( the same as PrepareHeader )
12 acmStreamUnprepareHeader
17 In future I'll also add functions for format enumeration,
20 Modified for use with MPlayer, detailed CVS changelog at
21 http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
24 ***************************************************************************/
27 #include "wine/winbase.h"
28 #include "wine/windef.h"
29 #include "wine/winuser.h"
31 #include "wine/winestring.h"
32 #include "wine/driver.h"
33 #include "wine/winerror.h"
34 #include "wine/msacm.h"
35 #include "wine/msacmdrv.h"
46 #define OpenDriverA DrvOpen
47 #define CloseDriver DrvClose
49 static inline PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
51 return (PWINE_ACMSTREAM)has;
54 /***********************************************************************
55 * acmDriverAddA (MSACM32.2)
57 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
58 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
61 return MMSYSERR_INVALPARAM;
63 /* Check if any unknown flags */
65 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
66 ACM_DRIVERADDF_GLOBAL))
67 return MMSYSERR_INVALFLAG;
69 /* Check if any incompatible flags */
70 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
71 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
72 return MMSYSERR_INVALFLAG;
74 /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
75 * LoadDriver on it, to be sure we can call SendDriverMessage on the
78 *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, 0, hinstModule);
80 /* FIXME: lParam, dwPriority and fdwAdd ignored */
82 return MMSYSERR_NOERROR;
85 /***********************************************************************
86 * acmDriverClose (MSACM32.4)
88 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
94 return MMSYSERR_INVALFLAG;
96 p = MSACM_GetDriver(had);
98 return MMSYSERR_INVALHANDLE;
100 for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
102 *tp = (*tp)->pNextACMDriver;
107 if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
108 CloseDriver(p->hDrvr);
110 HeapFree(MSACM_hHeap, 0, p);
112 return MMSYSERR_NOERROR;
115 /***********************************************************************
116 * acmDriverEnum (MSACM32.7)
118 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
124 return MMSYSERR_INVALPARAM;
127 if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) {
128 return MMSYSERR_INVALFLAG;
131 for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
132 fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
134 if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
135 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
139 (*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
142 return MMSYSERR_NOERROR;
145 /***********************************************************************
146 * acmDriverID (MSACM32.8)
148 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
152 pao = MSACM_GetObj(hao);
154 return MMSYSERR_INVALHANDLE;
157 return MMSYSERR_INVALPARAM;
160 return MMSYSERR_INVALFLAG;
162 *phadid = (HACMDRIVERID) pao->pACMDriverID;
164 return MMSYSERR_NOERROR;
167 /***********************************************************************
168 * acmDriverMessage (MSACM32.9)
172 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
174 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
176 return MMSYSERR_INVALPARAM;
178 /* FIXME: Check if uMsg legal */
180 if (!SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2))
181 return MMSYSERR_NOTSUPPORTED;
183 return MMSYSERR_NOERROR;
187 /***********************************************************************
188 * acmDriverOpen (MSACM32.10)
190 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
192 PWINE_ACMDRIVERID padid;
198 TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen);
201 return MMSYSERR_INVALPARAM;
203 padid = MSACM_GetDriverID(hadid);
205 return MMSYSERR_INVALHANDLE;
208 return MMSYSERR_INVALFLAG;
210 pad = (PWINE_ACMDRIVER) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
212 return MMSYSERR_NOMEM;
214 pad->obj.pACMDriverID = padid;
215 icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c');
216 icopen.fccHandler = (long)padid->pszFileName;
217 icopen.dwSize = sizeof(ICOPEN);
220 icopen.pV1Reserved = padid->pszFileName;
221 if (!padid->hInstModule)
222 pad->hDrvr = OpenDriverA((long)&icopen);
224 pad->hDrvr = padid->hInstModule;
227 HeapFree(MSACM_hHeap, 0, pad);
228 return MMSYSERR_ERROR;
231 pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
233 /* insert new pad at beg of list */
234 pad->pNextACMDriver = padid->pACMDriverList;
235 padid->pACMDriverList = pad;
237 /* FIXME: Create a WINE_ACMDRIVER32 */
238 *phad = (HACMDRIVER)pad;
240 return MMSYSERR_NOERROR;
243 /***********************************************************************
244 * acmDriverRemove (MSACM32.12)
246 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
248 PWINE_ACMDRIVERID padid;
250 padid = MSACM_GetDriverID(hadid);
252 return MMSYSERR_INVALHANDLE;
255 return MMSYSERR_INVALFLAG;
257 MSACM_UnregisterDriver(padid);
259 return MMSYSERR_NOERROR;
264 /**********************************************************************/
266 HANDLE MSACM_hHeap = (HANDLE) NULL;
267 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
268 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
270 /***********************************************************************
271 * MSACM_RegisterDriver32()
273 PWINE_ACMDRIVERID MSACM_RegisterDriver(const char* pszFileName,
275 HINSTANCE hinstModule)
277 PWINE_ACMDRIVERID padid;
279 TRACE("('%s', '%x', 0x%08x)\n", pszFileName, wFormatTag, hinstModule);
282 MSACM_hHeap = GetProcessHeap();
284 padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
285 padid->pszFileName = (char*)malloc(strlen(pszFileName)+1);
286 strcpy(padid->pszFileName, pszFileName);
287 // 1~strdup(pszDriverAlias);
288 padid->wFormatTag = wFormatTag;
289 padid->hInstModule = hinstModule;
290 padid->bEnabled = TRUE;
291 padid->pACMDriverList = NULL;
292 padid->pNextACMDriverID = NULL;
293 padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
294 if (MSACM_pLastACMDriverID)
295 MSACM_pLastACMDriverID->pNextACMDriverID = padid;
296 MSACM_pLastACMDriverID = padid;
297 if (!MSACM_pFirstACMDriverID)
298 MSACM_pFirstACMDriverID = padid;
304 /***********************************************************************
305 * MSACM_UnregisterDriver32()
307 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
309 PWINE_ACMDRIVERID pNextACMDriverID;
311 while (p->pACMDriverList)
312 acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
315 free(p->pszFileName);
317 if (p == MSACM_pFirstACMDriverID)
318 MSACM_pFirstACMDriverID = p->pNextACMDriverID;
319 if (p == MSACM_pLastACMDriverID)
320 MSACM_pLastACMDriverID = p->pPrevACMDriverID;
322 if (p->pPrevACMDriverID)
323 p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
324 if (p->pNextACMDriverID)
325 p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
327 pNextACMDriverID = p->pNextACMDriverID;
329 HeapFree(MSACM_hHeap, 0, p);
331 return pNextACMDriverID;
334 /***********************************************************************
335 * MSACM_UnregisterAllDrivers32()
337 * Where should this function be called?
339 void MSACM_UnregisterAllDrivers(void)
343 for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
346 /***********************************************************************
347 * MSACM_GetDriverID32()
349 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
351 return (PWINE_ACMDRIVERID)hDriverID;
354 /***********************************************************************
355 * MSACM_GetDriver32()
357 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
359 return (PWINE_ACMDRIVER)hDriver;
362 /***********************************************************************
365 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj)
367 return (PWINE_ACMOBJ)hObj;
372 /***********************************************************************
373 * acmStreamOpen (MSACM32.40)
375 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
376 PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
377 DWORD dwInstance, DWORD fdwOpen)
385 TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
386 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
388 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
389 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
390 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
392 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
393 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
394 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
396 #define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
397 wfxSrcSize = SIZEOF_WFX(pwfxSrc);
398 wfxDstSize = SIZEOF_WFX(pwfxDst);
401 was = (PWINE_ACMSTREAM) HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
403 return MMSYSERR_NOMEM;
404 was->drvInst.cbStruct = sizeof(was->drvInst);
405 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
406 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
407 // LHACM is checking for 0x1
408 // but if this will not help
409 // was->drvInst.pwfxSrc->wFormatTag = 1;
410 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
411 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
413 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
414 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
416 was->drvInst.pwfltr = NULL;
418 was->drvInst.dwCallback = dwCallback;
419 was->drvInst.dwInstance = dwInstance;
420 was->drvInst.fdwOpen = fdwOpen;
421 was->drvInst.fdwDriver = 0L;
422 was->drvInst.dwDriver = 0L;
423 was->drvInst.has = (HACMSTREAM)was;
426 if (!(wad = MSACM_GetDriver(had))) {
427 ret = MMSYSERR_INVALPARAM;
431 was->obj.pACMDriverID = wad->obj.pACMDriverID;
433 was->hAcmDriver = 0; /* not to close it in acmStreamClose */
435 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
436 if (ret != MMSYSERR_NOERROR)
439 PWINE_ACMDRIVERID wadi;
441 ret = ACMERR_NOTPOSSIBLE;
442 /* if(pwfxSrc->wFormatTag==1)//compression
443 drv_tag=pwfxDst->wFormatTag;
445 if(pwfxDst->wFormatTag==1)//decompression
446 drv_tag=pwfxSrc->wFormatTag;
450 ret=acmDriverOpen2(drv_tag);
451 if (ret == MMSYSERR_NOERROR) {
452 if ((wad = MSACM_GetDriver(had)) != 0) {
453 was->obj.pACMDriverID = wad->obj.pACMDriverID;
455 was->hAcmDriver = had;
457 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
458 if (ret == MMSYSERR_NOERROR) {
459 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
460 acmDriverClose(had, 0L);
465 acmDriverClose(had, 0L);*/
466 //if(MSACM_pFirstACMDriverID==NULL)
467 // MSACM_RegisterAllDrivers();
469 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID)
472 if ((int)wadi->wFormatTag != (int)pwfxSrc->wFormatTag) continue;
474 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
475 if (ret == MMSYSERR_NOERROR) {
476 if ((wad = MSACM_GetDriver(had)) != 0) {
477 was->obj.pACMDriverID = wad->obj.pACMDriverID;
479 was->hAcmDriver = had;
481 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
482 //lhacm - crash printf("RETOPEN %d\n", ret);
484 if (ret == MMSYSERR_NOERROR) {
485 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
486 acmDriverClose(had, 0L);
491 // no match, close this acm driver and try next one
492 acmDriverClose(had, 0L);
495 if (ret != MMSYSERR_NOERROR) {
496 ret = ACMERR_NOTPOSSIBLE;
500 ret = MMSYSERR_NOERROR;
501 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
503 *phas = (HACMSTREAM)was;
504 TRACE("=> (%d)\n", ret);
512 *phas = (HACMSTREAM)0;
513 HeapFree(MSACM_hHeap, 0, was);
514 TRACE("=> (%d)\n", ret);
519 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
524 TRACE("(0x%08x, %ld)\n", has, fdwClose);
526 if ((was = ACM_GetStream(has)) == NULL) {
527 return MMSYSERR_INVALHANDLE;
529 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
530 if (ret == MMSYSERR_NOERROR) {
532 acmDriverClose(was->hAcmDriver, 0L);
533 HeapFree(MSACM_hHeap, 0, was);
538 TRACE("=> (%d)\n", ret);
542 /***********************************************************************
543 * acmStreamConvert (MSACM32.38)
545 MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
549 MMRESULT ret = MMSYSERR_NOERROR;
550 PACMDRVSTREAMHEADER padsh;
552 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwConvert);
554 if ((was = ACM_GetStream(has)) == NULL)
555 return MMSYSERR_INVALHANDLE;
556 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
557 return MMSYSERR_INVALPARAM;
559 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
560 return ACMERR_UNPREPARED;
562 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
563 * size. some fields are private to msacm internals, and are exposed
564 * in ACMSTREAMHEADER in the dwReservedDriver array
566 padsh = (PACMDRVSTREAMHEADER)pash;
568 /* check that pointers have not been modified */
569 if (padsh->pbPreparedSrc != padsh->pbSrc ||
570 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
571 padsh->pbPreparedDst != padsh->pbDst ||
572 padsh->cbPreparedDstLength < padsh->cbDstLength) {
573 return MMSYSERR_INVALPARAM;
576 padsh->fdwConvert = fdwConvert;
578 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CONVERT, (DWORD)&was->drvInst, (DWORD)padsh);
579 if (ret == MMSYSERR_NOERROR) {
580 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
582 TRACE("=> (%d)\n", ret);
587 /***********************************************************************
588 * acmStreamPrepareHeader (MSACM32.41)
590 MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
594 MMRESULT ret = MMSYSERR_NOERROR;
595 PACMDRVSTREAMHEADER padsh;
597 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare);
599 if ((was = ACM_GetStream(has)) == NULL)
600 return MMSYSERR_INVALHANDLE;
601 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
602 return MMSYSERR_INVALPARAM;
604 ret = MMSYSERR_INVALFLAG;
606 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
607 return MMSYSERR_NOERROR;
609 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
610 * size. some fields are private to msacm internals, and are exposed
611 * in ACMSTREAMHEADER in the dwReservedDriver array
613 padsh = (PACMDRVSTREAMHEADER)pash;
615 padsh->fdwConvert = fdwPrepare;
616 padsh->padshNext = NULL;
617 padsh->fdwDriver = padsh->dwDriver = 0L;
619 padsh->fdwPrepared = 0;
620 padsh->dwPrepared = 0;
621 padsh->pbPreparedSrc = 0;
622 padsh->cbPreparedSrcLength = 0;
623 padsh->pbPreparedDst = 0;
624 padsh->cbPreparedDstLength = 0;
626 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
627 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
628 ret = MMSYSERR_NOERROR;
629 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
630 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
631 padsh->fdwPrepared = padsh->fdwStatus;
632 padsh->dwPrepared = 0;
633 padsh->pbPreparedSrc = padsh->pbSrc;
634 padsh->cbPreparedSrcLength = padsh->cbSrcLength;
635 padsh->pbPreparedDst = padsh->pbDst;
636 padsh->cbPreparedDstLength = padsh->cbDstLength;
638 padsh->fdwPrepared = 0;
639 padsh->dwPrepared = 0;
640 padsh->pbPreparedSrc = 0;
641 padsh->cbPreparedSrcLength = 0;
642 padsh->pbPreparedDst = 0;
643 padsh->cbPreparedDstLength = 0;
645 TRACE("=> (%d)\n", ret);
649 /***********************************************************************
650 * acmStreamReset (MSACM32.42)
652 MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
655 MMRESULT ret = MMSYSERR_NOERROR;
657 TRACE("(0x%08x, %ld)\n", has, fdwReset);
660 ret = MMSYSERR_INVALFLAG;
661 } else if ((was = ACM_GetStream(has)) == NULL) {
662 return MMSYSERR_INVALHANDLE;
663 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
664 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
666 TRACE("=> (%d)\n", ret);
670 /***********************************************************************
671 * acmStreamSize (MSACM32.43)
673 MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
674 LPDWORD pdwOutputBytes, DWORD fdwSize)
677 ACMDRVSTREAMSIZE adss;
680 TRACE("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize);
682 if ((was = ACM_GetStream(has)) == NULL) {
683 return MMSYSERR_INVALHANDLE;
685 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
686 return MMSYSERR_INVALFLAG;
689 *pdwOutputBytes = 0L;
691 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
692 case ACM_STREAMSIZEF_DESTINATION:
693 adss.cbDstLength = cbInput;
694 adss.cbSrcLength = 0;
696 case ACM_STREAMSIZEF_SOURCE:
697 adss.cbSrcLength = cbInput;
698 adss.cbDstLength = 0;
701 return MMSYSERR_INVALFLAG;
704 adss.cbStruct = sizeof(adss);
705 adss.fdwSize = fdwSize;
706 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
707 (DWORD)&was->drvInst, (DWORD)&adss);
708 if (ret == MMSYSERR_NOERROR) {
709 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
710 case ACM_STREAMSIZEF_DESTINATION:
711 *pdwOutputBytes = adss.cbSrcLength;
713 case ACM_STREAMSIZEF_SOURCE:
714 *pdwOutputBytes = adss.cbDstLength;
718 TRACE("=> (%d) [%lu]\n", ret, *pdwOutputBytes);
722 /***********************************************************************
723 * acmStreamUnprepareHeader (MSACM32.44)
725 MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
729 MMRESULT ret = MMSYSERR_NOERROR;
730 PACMDRVSTREAMHEADER padsh;
732 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare);
734 if ((was = ACM_GetStream(has)) == NULL)
735 return MMSYSERR_INVALHANDLE;
736 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
737 return MMSYSERR_INVALPARAM;
739 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
740 return ACMERR_UNPREPARED;
742 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
743 * size. some fields are private to msacm internals, and are exposed
744 * in ACMSTREAMHEADER in the dwReservedDriver array
746 padsh = (PACMDRVSTREAMHEADER)pash;
748 /* check that pointers have not been modified */
749 if (padsh->pbPreparedSrc != padsh->pbSrc ||
750 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
751 padsh->pbPreparedDst != padsh->pbDst ||
752 padsh->cbPreparedDstLength < padsh->cbDstLength) {
753 return MMSYSERR_INVALPARAM;
756 padsh->fdwConvert = fdwUnprepare;
758 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
759 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
760 ret = MMSYSERR_NOERROR;
761 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
763 TRACE("=> (%d)\n", ret);