2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * FIXME: This all assumes 32 bit codecs
20 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
21 * There is the ICOpenFunction16 to worry about still, though.
30 #include "msvideo_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
39 static inline const char *wine_dbgstr_fcc( DWORD fcc )
41 return wine_dbg_sprintf("%c%c%c%c",
42 LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)),
43 LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc)));
46 LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM) = NULL;
48 static WINE_HIC* MSVIDEO_FirstHic /* = NULL */;
50 /******************************************************************
55 WINE_HIC* MSVIDEO_GetHicPtr(HIC hic)
59 for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next);
63 /***********************************************************************
64 * VideoForWindowsVersion [MSVFW32.2]
65 * VideoForWindowsVersion [MSVIDEO.2]
66 * Returns the version in major.minor form.
67 * In Windows95 this returns 0x040003b6 (4.950)
69 DWORD WINAPI VideoForWindowsVersion(void)
71 return 0x040003B6; /* 4.950 */
74 /* system.ini: [drivers] */
76 /***********************************************************************
78 * Get information about an installable compressor. Return TRUE if there
82 DWORD fccType, /* [in] type of compressor ('vidc') */
83 DWORD fccHandler, /* [in] real fcc for handler or <n>th compressor */
84 ICINFO *lpicinfo) /* [out] information about compressor */
88 TRACE("(%s,%s/%08lx,%p)\n",
89 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo);
91 if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini"))
94 char fccHandlerStr[4];
97 fccTypeStr[0] = LOBYTE(LOWORD(fccType));
98 fccTypeStr[1] = HIBYTE(LOWORD(fccType));
99 fccTypeStr[2] = LOBYTE(HIWORD(fccType));
100 fccTypeStr[3] = HIBYTE(HIWORD(fccType));
102 fccHandlerStr[0] = LOBYTE(LOWORD(fccHandler));
103 fccHandlerStr[1] = HIBYTE(LOWORD(fccHandler));
104 fccHandlerStr[2] = LOBYTE(HIWORD(fccHandler));
105 fccHandlerStr[3] = HIBYTE(HIWORD(fccHandler));
107 for (s = buf; *s; s += strlen(s) + 1)
109 if (!strncasecmp(fccTypeStr, s, 4) && s[4] == '.' && s[9] == '=' &&
110 (!fccHandler-- || !strncasecmp(fccHandlerStr, s + 5, 4)))
112 /* exact match of fccHandler or nth driver found ?? */
113 lpicinfo->fccType = fccType;
114 lpicinfo->fccHandler = mmioStringToFOURCCA(s + 5, 0);
115 lpicinfo->dwFlags = 0;
116 lpicinfo->dwVersion = 0;
117 lpicinfo->dwVersionICM = 0x104;
118 lpicinfo->szName[0] = 0;
119 lpicinfo->szDescription[0] = 0;
120 MultiByteToWideChar(CP_ACP, 0, s + 10, -1,
122 sizeof(lpicinfo->szDriver)/sizeof(WCHAR));
130 static DWORD IC_HandleRef = 1;
132 /***********************************************************************
134 * Opens an installable compressor. Return special handle.
136 HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
144 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode);
146 codecname[0] = LOBYTE(LOWORD(fccType));
147 codecname[1] = HIBYTE(LOWORD(fccType));
148 codecname[2] = LOBYTE(HIWORD(fccType));
149 codecname[3] = HIBYTE(HIWORD(fccType));
151 codecname[5] = LOBYTE(LOWORD(fccHandler));
152 codecname[6] = HIBYTE(LOWORD(fccHandler));
153 codecname[7] = LOBYTE(HIWORD(fccHandler));
154 codecname[8] = HIBYTE(HIWORD(fccHandler));
157 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
158 * same layout as ICOPEN
160 icopen.dwSize = sizeof(ICOPEN);
161 icopen.fccType = fccType;
162 icopen.fccHandler = fccHandler;
163 icopen.dwVersion = 0x00001000; /* FIXME */
164 icopen.dwFlags = wMode;
166 icopen.pV1Reserved = NULL;
167 icopen.pV2Reserved = NULL;
168 icopen.dnDevNode = 0; /* FIXME */
170 hdrv = OpenDriverA(codecname, "drivers32", (LPARAM)&icopen);
173 if (fccType == streamtypeVIDEO)
180 fccType = ICTYPE_VIDEO;
181 hdrv = OpenDriverA(codecname, "drivers32", (LPARAM)&icopen);
186 bIs16 = GetDriverFlags(hdrv) & WINE_GDF_16BIT;
188 if (bIs16 && !pFnCallTo16)
190 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
193 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
196 CloseDriver(hdrv, 0, 0);
200 /* FIXME: is the signature the real one ? */
201 whic->driverproc = bIs16 ? (DRIVERPROC)pFnCallTo16 : NULL;
202 whic->driverproc16 = 0;
203 whic->type = fccType;
204 whic->handler = fccHandler;
205 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
206 whic->hic = HIC_32(IC_HandleRef++);
207 whic->next = MSVIDEO_FirstHic;
208 MSVIDEO_FirstHic = whic;
210 TRACE("=> %p\n", whic->hic);
214 /***********************************************************************
215 * MSVIDEO_OpenFunction
217 HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode,
218 DRIVERPROC lpfnHandler, DWORD lpfnHandler16)
223 TRACE("(%s,%s,%d,%p,%08lx)\n",
224 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler, lpfnHandler16);
226 icopen.dwSize = sizeof(ICOPEN);
227 icopen.fccType = fccType;
228 icopen.fccHandler = fccHandler;
229 icopen.dwVersion = 0x00001000; /* FIXME */
230 icopen.dwFlags = wMode;
232 icopen.pV1Reserved = NULL;
233 icopen.pV2Reserved = NULL;
234 icopen.dnDevNode = 0; /* FIXME */
236 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
239 whic->driverproc = lpfnHandler;
240 whic->driverproc16 = lpfnHandler16;
241 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
242 whic->hic = HIC_32(IC_HandleRef++);
243 whic->next = MSVIDEO_FirstHic;
244 MSVIDEO_FirstHic = whic;
246 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
247 /* What if the function is used more than once? */
249 if (MSVIDEO_SendMessage(whic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS)
251 WARN("DRV_LOAD failed for hic %p\n", whic->hic);
252 MSVIDEO_FirstHic = whic->next;
253 HeapFree(GetProcessHeap(), 0, whic);
256 /* return value is not checked */
257 MSVIDEO_SendMessage(whic, DRV_ENABLE, 0L, 0L);
259 whic->hdrv = (HDRVR)MSVIDEO_SendMessage(whic, DRV_OPEN, 0, (DWORD)&icopen);
263 WARN("DRV_OPEN failed for hic %p\n", whic->hic);
264 MSVIDEO_FirstHic = whic->next;
265 HeapFree(GetProcessHeap(), 0, whic);
269 TRACE("=> %p\n", whic->hic);
273 /***********************************************************************
274 * ICOpenFunction [MSVFW32.@]
276 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler)
278 return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)lpfnHandler, 0);
281 /***********************************************************************
282 * ICGetInfo [MSVFW32.@]
284 LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb)
287 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
289 TRACE("(%p,%p,%ld)\n", hic, picinfo, cb);
291 whic = MSVIDEO_GetHicPtr(hic);
292 if (!whic) return ICERR_BADHANDLE;
293 if (!picinfo) return MMSYSERR_INVALPARAM;
295 /* (WS) The field szDriver should be initialized because the driver
296 * is not obliged and often will not do it. Some applications, like
297 * VirtualDub, rely on this field and will occasionally crash if it
300 if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0';
302 ret = ICSendMessage(hic, ICM_GETINFO, (DWORD)picinfo, cb);
304 /* (WS) When szDriver was not supplied by the driver itself, apparently
305 * Windows will set its value equal to the driver file name. This can
306 * be obtained from the registry as we do here.
308 if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0)
312 memset(&ii, 0, sizeof(ii));
313 ii.dwSize = sizeof(ii);
314 ICInfo(picinfo->fccType, picinfo->fccHandler, &ii);
315 lstrcpyW(picinfo->szDriver, ii.szDriver);
318 TRACE(" -> 0x%08lx\n", ret);
322 /***********************************************************************
323 * ICLocate [MSVFW32.@]
325 HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
326 LPBITMAPINFOHEADER lpbiOut, WORD wMode)
332 TRACE("(%s,%s,%p,%p,0x%04x)\n",
333 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
337 case ICMODE_FASTCOMPRESS:
338 case ICMODE_COMPRESS:
339 querymsg = ICM_COMPRESS_QUERY;
341 case ICMODE_FASTDECOMPRESS:
342 case ICMODE_DECOMPRESS:
343 querymsg = ICM_DECOMPRESS_QUERY;
346 querymsg = ICM_DRAW_QUERY;
349 WARN("Unknown mode (%d)\n", wMode);
353 /* Easy case: handler/type match, we just fire a query and return */
354 hic = ICOpen(fccType, fccHandler, wMode);
357 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
359 TRACE("=> %p\n", hic);
365 /* Now try each driver in turn. 32 bit codecs only. */
366 /* FIXME: Move this to an init routine? */
368 pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 1024);
369 if (GetPrivateProfileSectionA("drivers32", pszBuffer, 1024, "system.ini"))
376 fcc[0] = LOBYTE(LOWORD(fccType));
377 fcc[1] = HIBYTE(LOWORD(fccType));
378 fcc[2] = LOBYTE(HIWORD(fccType));
379 fcc[3] = HIBYTE(HIWORD(fccType));
380 if (!strncasecmp(fcc, s, 4) && s[4] == '.' && s[9] == '=')
383 while (*s2 != '\0' && *s2 != '.') s2++;
386 hic = ICOpen(fccType, mmioStringToFOURCCA(s2, 0), wMode);
389 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
391 HeapFree(GetProcessHeap(), 0, pszBuffer);
392 TRACE("=> %p\n", hic);
402 HeapFree(GetProcessHeap(), 0, pszBuffer);
404 if (fccType == streamtypeVIDEO)
405 return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode);
407 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
408 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
412 /***********************************************************************
413 * ICGetDisplayFormat [MSVFW32.@]
415 HIC VFWAPI ICGetDisplayFormat(
416 HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
417 INT depth,INT dx,INT dy)
421 FIXME("(%p,%p,%p,%d,%d,%d),stub!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);
423 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
427 if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
428 dy = dx = 0; /* no resize needed */
430 /* Can we decompress it ? */
431 if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
432 goto errout; /* no, sorry */
434 ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
436 if (lpbiOut->biCompression != 0) {
437 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
438 lpbiOut->biCompression);
440 if (lpbiOut->biSize < sizeof(*lpbiOut)) {
441 FIXME("Ooch, size of output BIH is too small (%ld)\n",
443 lpbiOut->biSize = sizeof(*lpbiOut);
449 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
451 if (depth==15) depth = 16;
452 if (depth<8) depth = 8;
454 if (lpbiIn->biBitCount == 8)
457 TRACE("=> %p\n", tmphic);
467 /***********************************************************************
468 * ICCompress [MSVFW32.@]
472 HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
473 LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
474 LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
475 LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
479 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
481 iccmp.dwFlags = dwFlags;
483 iccmp.lpbiOutput = lpbiOutput;
484 iccmp.lpOutput = lpData;
485 iccmp.lpbiInput = lpbiInput;
486 iccmp.lpInput = lpBits;
488 iccmp.lpckid = lpckid;
489 iccmp.lpdwFlags = lpdwFlags;
490 iccmp.lFrameNum = lFrameNum;
491 iccmp.dwFrameSize = dwFrameSize;
492 iccmp.dwQuality = dwQuality;
493 iccmp.lpbiPrev = lpbiPrev;
494 iccmp.lpPrev = lpPrev;
495 return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp));
498 /***********************************************************************
499 * ICDecompress [MSVFW32.@]
501 DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
502 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
507 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
509 TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]);
511 icd.dwFlags = dwFlags;
512 icd.lpbiInput = lpbiFormat;
513 icd.lpInput = lpData;
515 icd.lpbiOutput = lpbi;
516 icd.lpOutput = lpBits;
518 ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
520 TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]);
522 TRACE("-> %ld\n",ret);
528 /***********************************************************************
529 * ICCompressorChoose [MSVFW32.@]
531 BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn, LPVOID lpData,
532 PCOMPVARS pc, LPSTR lpszTitle)
539 /***********************************************************************
540 * ICCompressorFree [MSVFW32.@]
542 void VFWAPI ICCompressorFree(PCOMPVARS pc)
548 /******************************************************************
549 * MSVIDEO_SendMessage
553 LRESULT MSVIDEO_SendMessage(WINE_HIC* whic, UINT msg, DWORD lParam1, DWORD lParam2)
557 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
572 XX(ICM_GETDEFAULTQUALITY);
579 XX(ICM_COMPRESS_FRAMES_INFO);
580 XX(ICM_COMPRESS_GET_FORMAT);
581 XX(ICM_COMPRESS_GET_SIZE);
582 XX(ICM_COMPRESS_QUERY);
583 XX(ICM_COMPRESS_BEGIN);
585 XX(ICM_COMPRESS_END);
586 XX(ICM_DECOMPRESS_GET_FORMAT);
587 XX(ICM_DECOMPRESS_QUERY);
588 XX(ICM_DECOMPRESS_BEGIN);
590 XX(ICM_DECOMPRESS_END);
591 XX(ICM_DECOMPRESS_SET_PALETTE);
592 XX(ICM_DECOMPRESS_GET_PALETTE);
595 XX(ICM_DRAW_GET_PALETTE);
599 XX(ICM_DRAW_GETTIME);
602 XX(ICM_DRAW_SETTIME);
603 XX(ICM_DRAW_REALIZE);
605 XX(ICM_DRAW_RENDERBUFFER);
606 XX(ICM_DRAW_START_PLAY);
607 XX(ICM_DRAW_STOP_PLAY);
608 XX(ICM_DRAW_SUGGESTFORMAT);
609 XX(ICM_DRAW_CHANGEPALETTE);
610 XX(ICM_GETBUFFERSWANTED);
611 XX(ICM_GETDEFAULTKEYFRAMERATE);
612 XX(ICM_DECOMPRESSEX_BEGIN);
613 XX(ICM_DECOMPRESSEX_QUERY);
614 XX(ICM_DECOMPRESSEX);
615 XX(ICM_DECOMPRESSEX_END);
616 XX(ICM_SET_STATUS_PROC);
618 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic,(DWORD)msg,lParam1,lParam2);
623 if (whic->driverproc) {
624 ret = whic->driverproc((DWORD)whic->hic, whic->hdrv, msg, lParam1, lParam2);
626 ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
629 TRACE(" -> 0x%08lx\n", ret);
633 /***********************************************************************
634 * ICSendMessage [MSVFW32.@]
636 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2)
638 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
640 if (!whic) return ICERR_BADHANDLE;
641 return MSVIDEO_SendMessage(whic, msg, lParam1, lParam2);
644 /***********************************************************************
645 * ICDrawBegin [MSVFW32.@]
647 DWORD VFWAPIV ICDrawBegin(
649 DWORD dwFlags, /* [in] flags */
650 HPALETTE hpal, /* [in] palette to draw with */
651 HWND hwnd, /* [in] window to draw to */
652 HDC hdc, /* [in] HDC to draw to */
653 INT xDst, /* [in] destination rectangle */
655 INT dxDst, /* [in] */
656 INT dyDst, /* [in] */
657 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */
658 INT xSrc, /* [in] source rectangle */
660 INT dxSrc, /* [in] */
661 INT dySrc, /* [in] */
662 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
663 DWORD dwScale) /* [in] */
668 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
669 hic, dwFlags, hpal, hwnd, hdc, xDst, yDst, dxDst, dyDst,
670 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
672 icdb.dwFlags = dwFlags;
685 icdb.dwRate = dwRate;
686 icdb.dwScale = dwScale;
687 return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
690 /***********************************************************************
693 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
696 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime);
698 icd.dwFlags = dwFlags;
699 icd.lpFormat = lpFormat;
704 return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
707 /***********************************************************************
708 * ICClose [MSVFW32.@]
710 LRESULT WINAPI ICClose(HIC hic)
712 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
717 if (!whic) return ICERR_BADHANDLE;
719 if (whic->driverproc)
721 MSVIDEO_SendMessage(whic, DRV_CLOSE, 0, 0);
722 MSVIDEO_SendMessage(whic, DRV_DISABLE, 0, 0);
723 MSVIDEO_SendMessage(whic, DRV_FREE, 0, 0);
727 CloseDriver(whic->hdrv, 0, 0);
730 /* remove whic from list */
731 for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next))
740 HeapFree(GetProcessHeap(), 0, whic);
746 /***********************************************************************
747 * ICImageCompress [MSVFW32.@]
749 HANDLE VFWAPI ICImageCompress(
750 HIC hic, UINT uiFlags,
751 LPBITMAPINFO lpbiIn, LPVOID lpBits,
752 LPBITMAPINFO lpbiOut, LONG lQuality,
755 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
756 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
761 /***********************************************************************
762 * ICImageDecompress [MSVFW32.@]
765 HANDLE VFWAPI ICImageDecompress(
766 HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
767 LPVOID lpBits, LPBITMAPINFO lpbiOut)
771 BOOL bReleaseIC = FALSE;
774 BOOL bSucceeded = FALSE;
775 BOOL bInDecompress = FALSE;
778 TRACE("(%p,%08x,%p,%p,%p)\n",
779 hic, uiFlags, lpbiIn, lpBits, lpbiOut);
783 hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
786 WARN("no handler\n" );
793 FIXME( "unknown flag %08x\n", uiFlags );
796 if ( lpbiIn == NULL || lpBits == NULL )
798 WARN("invalid argument\n");
802 if ( lpbiOut != NULL )
804 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
806 cbHdr = sizeof(BITMAPINFOHEADER);
807 if ( lpbiOut->bmiHeader.biCompression == 3 )
808 cbHdr += sizeof(DWORD)*3;
810 if ( lpbiOut->bmiHeader.biBitCount <= 8 )
812 if ( lpbiOut->bmiHeader.biClrUsed == 0 )
813 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
815 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
820 TRACE( "get format\n" );
822 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
823 if ( cbHdr < sizeof(BITMAPINFOHEADER) )
825 pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256);
828 ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 );
829 if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK )
831 lpbiOut = (BITMAPINFO*)pHdr;
832 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
833 ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
834 lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
836 if ( lpbiIn->bmiHeader.biClrUsed == 0 )
837 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
839 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
841 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
842 lpbiOut->bmiHeader.biClrUsed == 0 )
843 lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
845 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
846 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
849 biSizeImage = lpbiOut->bmiHeader.biSizeImage;
850 if ( biSizeImage == 0 )
851 biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight);
853 TRACE( "call ICDecompressBegin\n" );
855 if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
857 bInDecompress = TRUE;
859 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage );
861 hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
864 WARN( "out of memory\n" );
867 pMem = (BYTE*)GlobalLock( hMem );
870 memcpy( pMem, lpbiOut, cbHdr );
872 TRACE( "call ICDecompress\n" );
873 if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
879 ICDecompressEnd( hic );
883 HeapFree(GetProcessHeap(),0,pHdr);
885 GlobalUnlock( hMem );
886 if ( !bSucceeded && hMem != NULL )
888 GlobalFree(hMem); hMem = NULL;