2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
5 * FIXME: This all assumes 32 bit codecs
6 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
7 * There is the ICOpenFunction16 to worry about still, though.
21 #include "wine/winbase16.h"
22 #include "debugtools.h"
23 #include "stackframe.h"
25 DEFAULT_DEBUG_CHANNEL(msvideo);
27 /* ### start build ### */
28 extern LONG CALLBACK MSVIDEO_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
29 /* ### stop build ### */
31 LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2);
32 void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID lpv, LPDWORD lParam1, LPDWORD lParam2);
33 LRESULT MSVIDEO_SendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2, BOOL bFrom32);
35 /***********************************************************************
36 * VideoForWindowsVersion [MSVFW32.2]
37 * VideoForWindowsVersion [MSVIDEO.2]
38 * Returns the version in major.minor form.
39 * In Windows95 this returns 0x040003b6 (4.950)
41 DWORD WINAPI VideoForWindowsVersion(void) {
42 return 0x040003B6; /* 4.950 */
45 /***********************************************************************
46 * VideoCapDriverDescAndVer [MSVIDEO.22]
48 DWORD WINAPI VideoCapDriverDescAndVer(
49 WORD nr,LPSTR buf1,WORD buf1len,LPSTR buf2,WORD buf2len
55 char *s,buf[2000],fn[260];
59 TRACE("(%d,%p,%d,%p,%d)\n",nr,buf1,buf1len,buf2,buf2len);
60 if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,sizeof(buf),"system.ini")) {
63 if (!strncasecmp(s,"vid",3)) {
68 s=s+strlen(s)+1; /* either next char or \0 */
71 return 20; /* hmm, out of entries even if we don't have any */
73 FIXME("No more VID* entries found\n");
76 GetPrivateProfileStringA("drivers32",s,NULL,fn,sizeof(fn),"system.ini");
77 infosize = GetFileVersionInfoSizeA(fn,&verhandle);
79 TRACE("%s has no fileversioninfo.\n",fn);
82 infobuf = HeapAlloc(GetProcessHeap(),0,infosize);
83 if (GetFileVersionInfoA(fn,verhandle,infosize,infobuf)) {
85 /* Yes, two space behind : */
86 /* FIXME: test for buflen */
87 sprintf(vbuf,"Version: %d.%d.%d.%d\n",
88 ((WORD*)infobuf)[0x0f],
89 ((WORD*)infobuf)[0x0e],
90 ((WORD*)infobuf)[0x11],
91 ((WORD*)infobuf)[0x10]
93 TRACE("version of %s is %s\n",fn,vbuf);
94 strncpy(buf2,vbuf,buf2len);
96 TRACE("GetFileVersionInfoA failed for %s.\n",fn);
97 strncpy(buf2,fn,buf2len); /* msvideo.dll appears to copy fn*/
99 /* FIXME: language problem? */
100 if (VerQueryValueA( infobuf,
101 "\\StringFileInfo\\040904E4\\FileDescription",
105 TRACE("VQA returned %s\n",(LPCSTR)subblock);
106 strncpy(buf1,subblock,buf1len);
108 TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
109 strncpy(buf1,fn,buf1len); /* msvideo.dll appears to copy fn*/
111 HeapFree(GetProcessHeap(),0,infobuf);
115 /* system.ini: [drivers] */
117 /***********************************************************************
119 * Get information about an installable compressor. Return TRUE if there
123 DWORD fccType, /* [in] type of compressor ('vidc') */
124 DWORD fccHandler, /* [in] <n>th compressor */
125 ICINFO *lpicinfo) /* [out] information about compressor */
127 char type[5],buf[2000];
129 memcpy(type,&fccType,4);type[4]=0;
130 TRACE("(%s,%ld,%p).\n",type,fccHandler,lpicinfo);
131 /* does OpenDriver/CloseDriver */
132 lpicinfo->dwSize = sizeof(ICINFO);
133 lpicinfo->fccType = fccType;
134 lpicinfo->dwFlags = 0;
135 if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,2000,"system.ini")) {
138 if (!strncasecmp(type,s,4)) {
140 lpicinfo->fccHandler = mmioStringToFOURCCA(s+5,0);
144 s=s+strlen(s)+1; /* either next char or \0 */
150 /***********************************************************************
151 * ICInfo [MSVIDEO.200]
153 BOOL16 VFWAPI ICInfo16(
154 DWORD fccType, /* [in] */
155 DWORD fccHandler, /* [in] */
156 ICINFO16 *lpicinfo) /* [in/out] NOTE: SEGPTR */
160 DWORD lParam = (DWORD)lpicinfo;
161 DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;
163 /* Use the mapping functions to map the ICINFO structure */
164 lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO,&lParam,&size);
166 ret = ICInfo(fccType,fccHandler,(ICINFO*)lParam);
168 MSVIDEO_UnmapMsg16To32(ICM_GETINFO,lpv,&lParam,&size);
173 /***********************************************************************
175 * Opens an installable compressor. Return special handle.
177 HIC VFWAPI ICOpen(DWORD fccType,DWORD fccHandler,UINT wMode) {
178 char type[5],handler[5],codecname[20];
184 memcpy(type,&fccType,4);type[4]=0;
185 memcpy(handler,&fccHandler,4);handler[4]=0;
186 TRACE("(%s,%s,0x%08lx)\n",type,handler,(DWORD)wMode);
188 sprintf(codecname,"%s.%s",type,handler);
190 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
191 * same layout as ICOPEN
193 icopen.fccType = fccType;
194 icopen.fccHandler = fccHandler;
195 icopen.dwSize = sizeof(ICOPEN);
196 icopen.dwFlags = wMode;
197 /* FIXME: do we need to fill out the rest too? */
198 hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
200 if (!strcasecmp(type,"vids")) {
201 sprintf(codecname,"vidc.%s",handler);
202 fccType = mmioFOURCC('v','i','d','c');
204 hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
208 /* The handle should be a valid 16-bit handle as well */
209 hic = GlobalAlloc16(GHND,sizeof(WINE_HIC));
210 whic = (WINE_HIC*)GlobalLock16(hic);
212 whic->driverproc= NULL;
215 TRACE("=> 0x%08lx\n",(DWORD)hic);
219 HIC MSVIDEO_OpenFunc(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler, BOOL bFrom32) {
220 char type[5],handler[5],codecname[20];
226 memcpy(type,&fccType,4);type[4]=0;
227 memcpy(handler,&fccHandler,4);handler[4]=0;
228 TRACE("(%s,%s,%d,%p,%d)\n",type,handler,wMode,lpfnHandler,bFrom32?32:16);
230 icopen.fccType = fccType;
231 icopen.fccHandler = fccHandler;
232 icopen.dwSize = sizeof(ICOPEN);
233 icopen.dwFlags = wMode;
235 sprintf(codecname,"%s.%s",type,handler);
237 hic = GlobalAlloc16(GHND,sizeof(WINE_HIC));
240 whic = GlobalLock16(hic);
241 whic->driverproc = lpfnHandler;
243 whic->private = bFrom32;
245 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
246 /* What if the function is used more than once? */
248 if (MSVIDEO_SendMessage(hic,DRV_LOAD,0L,0L,bFrom32) != DRV_SUCCESS) {
249 WARN("DRV_LOAD failed for hic 0x%08lx\n",(DWORD)hic);
253 /* return value is not checked */
254 MSVIDEO_SendMessage(hic,DRV_ENABLE,0L,0L,bFrom32);
256 seg_icopen = MapLS( &icopen );
257 whic->hdrv = MSVIDEO_SendMessage(hic,DRV_OPEN,0,seg_icopen,FALSE);
258 UnMapLS( seg_icopen );
259 if (whic->hdrv == 0) {
260 WARN("DRV_OPEN failed for hic 0x%08lx\n",(DWORD)hic);
266 TRACE("=> 0x%08lx\n",(DWORD)hic);
270 /***********************************************************************
271 * ICOpenFunction [MSVFW32.@]
273 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) {
274 return MSVIDEO_OpenFunc(fccType,fccHandler,wMode,lpfnHandler,TRUE);
277 /***********************************************************************
278 * ICOpen [MSVIDEO.203]
280 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode) {
281 return (HIC16)ICOpen(fccType, fccHandler, wMode);
284 /***********************************************************************
285 * ICOpenFunction [MSVIDEO.206]
287 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
289 return MSVIDEO_OpenFunc(fccType, fccHandler, wMode, (FARPROC)lpfnHandler,FALSE);
292 /***********************************************************************
293 * ICGetInfo [MSVFW32.@]
295 LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) {
298 TRACE("(0x%08lx,%p,%ld)\n",(DWORD)hic,picinfo,cb);
299 ret = ICSendMessage(hic,ICM_GETINFO,(DWORD)picinfo,cb);
300 TRACE(" -> 0x%08lx\n",ret);
304 /***********************************************************************
305 * ICGetInfo [MSVIDEO.212]
307 LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 *picinfo,DWORD cb) {
310 TRACE("(0x%08lx,%p,%ld)\n",(DWORD)hic,picinfo,cb);
311 ret = ICSendMessage16(hic,ICM_GETINFO,(DWORD)picinfo,cb);
312 TRACE(" -> 0x%08lx\n",ret);
316 /***********************************************************************
317 * ICLocate [MSVFW32.@]
320 DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
321 LPBITMAPINFOHEADER lpbiOut, WORD wMode)
323 char type[5],handler[5];
328 type[4]=0;memcpy(type,&fccType,4);
329 handler[4]=0;memcpy(handler,&fccHandler,4);
331 TRACE("(%s,%s,%p,%p,0x%04x)\n", type, handler, lpbiIn, lpbiOut, wMode);
334 case ICMODE_FASTCOMPRESS:
335 case ICMODE_COMPRESS:
336 querymsg = ICM_COMPRESS_QUERY;
338 case ICMODE_FASTDECOMPRESS:
339 case ICMODE_DECOMPRESS:
340 querymsg = ICM_DECOMPRESS_QUERY;
343 querymsg = ICM_DRAW_QUERY;
346 WARN("Unknown mode (%d)\n",wMode);
350 /* Easy case: handler/type match, we just fire a query and return */
351 hic = ICOpen(fccType,fccHandler,wMode);
353 if (!ICSendMessage(hic,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
358 type[4]='.';memcpy(type,&fccType,4);
359 handler[4]='.';memcpy(handler,&fccHandler,4);
361 /* Now try each driver in turn. 32 bit codecs only. */
362 /* FIXME: Move this to an init routine? */
364 pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(),0,1024);
365 if (GetPrivateProfileSectionA("drivers32",pszBuffer,1024,"system.ini")) {
368 if (!strncasecmp(type,s,5)) {
370 while (*s2 != '\0' && *s2 != '.') s2++;
374 h = ICOpen(fccType,*(DWORD*)s2,wMode);
376 if (!ICSendMessage(h,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
385 HeapFree(GetProcessHeap(),0,pszBuffer);
387 if (fccType==streamtypeVIDEO) {
388 hic = ICLocate(ICTYPE_VIDEO,fccHandler,lpbiIn,lpbiOut,wMode);
393 type[4] = handler[4] = '\0';
394 WARN("(%.4s,%.4s,%p,%p,0x%04x) not found!\n",type,handler,lpbiIn,lpbiOut,wMode);
398 /***********************************************************************
399 * ICLocate [MSVIDEO.213]
401 HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
402 LPBITMAPINFOHEADER lpbiOut, WORD wFlags) {
403 return (HIC16)ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags);
406 /***********************************************************************
407 * ICGetDisplayFormat [MSVFW32.@]
409 HIC VFWAPI ICGetDisplayFormat(
410 HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
411 INT depth,INT dx,INT dy)
415 FIXME("(0x%08lx,%p,%p,%d,%d,%d),stub!\n",(DWORD)hic,lpbiIn,lpbiOut,depth,dx,dy);
417 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
421 if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
422 dy = dx = 0; /* no resize needed */
424 /* Can we decompress it ? */
425 if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
426 goto errout; /* no, sorry */
428 ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
430 if (lpbiOut->biCompression != 0) {
431 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
432 lpbiOut->biCompression);
434 if (lpbiOut->biSize < sizeof(*lpbiOut)) {
435 FIXME("Ooch, size of output BIH is too small (%ld)\n",
437 lpbiOut->biSize = sizeof(*lpbiOut);
443 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
445 if (depth==15) depth = 16;
446 if (depth<8) depth = 8;
448 if (lpbiIn->biBitCount == 8)
451 TRACE("=> 0x%08lx\n",(DWORD)tmphic);
461 /***********************************************************************
462 * ICGetDisplayFormat [MSVIDEO.239]
464 HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn,
465 LPBITMAPINFOHEADER lpbiOut, INT16 depth, INT16 dx, INT16 dy) {
466 return (HIC16)ICGetDisplayFormat(hic,lpbiIn,lpbiOut,depth,dx,dy);
469 /***********************************************************************
470 * ICCompress [MSVFW32.@]
474 HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
475 LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
476 LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
477 LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
481 TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
483 iccmp.dwFlags = dwFlags;
485 iccmp.lpbiOutput = lpbiOutput;
486 iccmp.lpOutput = lpData;
487 iccmp.lpbiInput = lpbiInput;
488 iccmp.lpInput = lpBits;
490 iccmp.lpckid = lpckid;
491 iccmp.lpdwFlags = lpdwFlags;
492 iccmp.lFrameNum = lFrameNum;
493 iccmp.dwFrameSize = dwFrameSize;
494 iccmp.dwQuality = dwQuality;
495 iccmp.lpbiPrev = lpbiPrev;
496 iccmp.lpPrev = lpPrev;
497 return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp));
500 /***********************************************************************
501 * _ICCompress [MSVIDEO.224]
503 DWORD VFWAPIV ICCompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData,
504 LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits, LPDWORD lpckid,
505 LPDWORD lpdwFlags, LONG lFrameNum, DWORD dwFrameSize, DWORD dwQuality,
506 LPBITMAPINFOHEADER lpbiPrev, LPVOID lpPrev) {
512 TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
514 iccmp.dwFlags = dwFlags;
516 iccmp.lpbiOutput = lpbiOutput;
517 iccmp.lpOutput = lpData;
518 iccmp.lpbiInput = lpbiInput;
519 iccmp.lpInput = lpBits;
521 iccmp.lpckid = lpckid;
522 iccmp.lpdwFlags = lpdwFlags;
523 iccmp.lFrameNum = lFrameNum;
524 iccmp.dwFrameSize = dwFrameSize;
525 iccmp.dwQuality = dwQuality;
526 iccmp.lpbiPrev = lpbiPrev;
527 iccmp.lpPrev = lpPrev;
528 seg_iccmp = MapLS( &iccmp );
529 ret = ICSendMessage16(hic,ICM_COMPRESS,seg_iccmp,sizeof(ICCOMPRESS));
530 UnMapLS( seg_iccmp );
534 /***********************************************************************
535 * ICDecompress [MSVFW32.@]
537 DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
538 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
543 TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
545 TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
547 icd.dwFlags = dwFlags;
548 icd.lpbiInput = lpbiFormat;
549 icd.lpInput = lpData;
551 icd.lpbiOutput = lpbi;
552 icd.lpOutput = lpBits;
554 ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
556 TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
558 TRACE("-> %ld\n",ret);
563 /***********************************************************************
564 * _ICDecompress [MSVIDEO.230]
566 DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat,
567 LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
573 TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
575 icd.dwFlags = dwFlags;
576 icd.lpbiInput = lpbiFormat;
577 icd.lpInput = lpData;
578 icd.lpbiOutput = lpbi;
579 icd.lpOutput = lpBits;
581 segptr = MapLS( &icd );
582 ret = ICSendMessage16(hic,ICM_DECOMPRESS,segptr,sizeof(ICDECOMPRESS));
587 #define COPY(x,y) (x->y = x##16->y);
588 #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
590 LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam) {
593 ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESSEX));
594 ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam);
598 COPYPTR(icdx,lpbiSrc);
600 COPYPTR(icdx,lpbiDst);
611 *lParam = (DWORD)(icdx);
615 LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2) {
618 TRACE("Mapping %d\n",msg);
628 case ICM_COMPRESS_END:
629 case ICM_DECOMPRESS_END:
630 case ICM_DECOMPRESSEX_END:
632 case ICM_DRAW_START_PLAY:
633 case ICM_DRAW_STOP_PLAY:
634 case ICM_DRAW_REALIZE:
635 case ICM_DRAW_RENDERBUFFER:
639 case ICM_GETDEFAULTQUALITY:
642 case ICM_DRAW_WINDOW:
643 case ICM_GETBUFFERSWANTED:
644 *lParam1 = (DWORD)MapSL(*lParam1);
648 ICINFO *ici = HeapAlloc(GetProcessHeap(),0,sizeof(ICINFO));
651 ici16 = MapSL(*lParam1);
654 ici->dwSize = sizeof(ICINFO);
656 COPY(ici,fccHandler);
659 COPY(ici,dwVersionICM);
660 MultiByteToWideChar( CP_ACP, 0, ici16->szName, -1, ici->szName, 16 );
661 MultiByteToWideChar( CP_ACP, 0, ici16->szDescription, -1, ici->szDescription, 128 );
662 MultiByteToWideChar( CP_ACP, 0, ici16->szDriver, -1, ici->szDriver, 128 );
663 *lParam1 = (DWORD)(ici);
664 *lParam2 = sizeof(ICINFO);
669 ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(),0,sizeof(ICCOMPRESS));
672 icc16 = MapSL(*lParam1);
676 COPYPTR(icc,lpbiOutput);
677 COPYPTR(icc,lpOutput);
678 COPYPTR(icc,lpbiInput);
679 COPYPTR(icc,lpInput);
681 COPYPTR(icc,lpdwFlags);
683 COPY(icc,dwFrameSize);
685 COPYPTR(icc,lpbiPrev);
688 *lParam1 = (DWORD)(icc);
689 *lParam2 = sizeof(ICCOMPRESS);
694 ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESS));
695 ICDECOMPRESS *icd16; /* Same structure except for the pointers */
697 icd16 = MapSL(*lParam1);
701 COPYPTR(icd,lpbiInput);
702 COPYPTR(icd,lpInput);
703 COPYPTR(icd,lpbiOutput);
704 COPYPTR(icd,lpOutput);
707 *lParam1 = (DWORD)(icd);
708 *lParam2 = sizeof(ICDECOMPRESS);
711 case ICM_COMPRESS_BEGIN:
712 case ICM_COMPRESS_GET_FORMAT:
713 case ICM_COMPRESS_GET_SIZE:
714 case ICM_COMPRESS_QUERY:
715 case ICM_DECOMPRESS_GET_FORMAT:
716 case ICM_DECOMPRESS_QUERY:
717 case ICM_DECOMPRESS_BEGIN:
718 case ICM_DECOMPRESS_SET_PALETTE:
719 case ICM_DECOMPRESS_GET_PALETTE:
720 *lParam1 = (DWORD)MapSL(*lParam1);
721 *lParam2 = (DWORD)MapSL(*lParam2);
723 case ICM_DECOMPRESSEX_QUERY:
724 if ((*lParam2 != sizeof(ICDECOMPRESSEX16)) && (*lParam2 != 0))
725 WARN("*lParam2 has unknown value %p\n",(ICDECOMPRESSEX16*)*lParam2);
726 /* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16)
727 * This is because of ICMessage(). Special case it?
729 LPVOID* addr = HeapAlloc(GetProcessHeap(),0,2*sizeof(LPVOID));
730 addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
732 addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
739 case ICM_DECOMPRESSEX_BEGIN:
740 case ICM_DECOMPRESSEX:
741 ret = MSVIDEO_MapICDEX16To32(lParam1);
742 *lParam2 = sizeof(ICDECOMPRESSEX);
746 ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWBEGIN));
747 ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1);
766 *lParam1 = (DWORD)(icdb);
767 *lParam2 = sizeof(ICDRAWBEGIN);
770 case ICM_DRAW_SUGGESTFORMAT:
772 ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWSUGGEST));
773 ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1);
778 COPYPTR(icds,lpbiIn);
779 COPYPTR(icds,lpbiSuggest);
784 COPY(icds,hicDecompressor);
786 *lParam1 = (DWORD)(icds);
787 *lParam2 = sizeof(ICDRAWSUGGEST);
792 ICDRAW *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAW));
793 ICDRAW *icd16 = MapSL(*lParam1);
797 COPYPTR(icd,lpFormat);
802 *lParam1 = (DWORD)(icd);
803 *lParam2 = sizeof(ICDRAW);
810 FIXME("%d is not yet handled. Expect a crash.\n",msg);
818 void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2) {
819 TRACE("Unmapping %d\n",msg);
821 #define UNCOPY(x,y) (x##16->y = x->y);
826 ICINFO *ici = (ICINFO*)(*lParam1);
827 ICINFO16 *ici16 = (ICINFO16*)data16;
830 UNCOPY(ici,fccHandler);
832 UNCOPY(ici,dwVersion);
833 UNCOPY(ici,dwVersionICM);
834 WideCharToMultiByte( CP_ACP, 0, ici->szName, -1, ici16->szName,
835 sizeof(ici16->szName), NULL, NULL );
836 ici16->szName[sizeof(ici16->szName)-1] = 0;
837 WideCharToMultiByte( CP_ACP, 0, ici->szDescription, -1, ici16->szDescription,
838 sizeof(ici16->szDescription), NULL, NULL );
839 ici16->szDescription[sizeof(ici16->szDescription)-1] = 0;
840 /* This just gives garbage for some reason - BB
841 lstrcpynWtoA(ici16->szDriver,ici->szDriver,128);*/
843 HeapFree(GetProcessHeap(),0,ici);
846 case ICM_DECOMPRESS_QUERY:
849 HeapFree(GetProcessHeap(),0,x[0]);
851 HeapFree(GetProcessHeap(),0,x[1]);
856 case ICM_DECOMPRESSEX_QUERY:
857 case ICM_DECOMPRESSEX_BEGIN:
858 case ICM_DECOMPRESSEX:
860 case ICM_DRAW_SUGGESTFORMAT:
862 HeapFree(GetProcessHeap(),0,data16);
865 ERR("Unmapping unmapped msg %d\n",msg);
870 LRESULT MSVIDEO_SendMessage(HIC hic,UINT msg,DWORD lParam1,DWORD lParam2, BOOL bFrom32) {
872 WINE_HIC *whic = GlobalLock16(hic);
876 #define XX(x) case x: TRACE("(0x%08lx,"#x",0x%08lx,0x%08lx,%d)\n",(DWORD)hic,lParam1,lParam2,bFrom32?32:16);break;
891 XX(ICM_GETDEFAULTQUALITY);
898 XX(ICM_COMPRESS_FRAMES_INFO);
899 XX(ICM_COMPRESS_GET_FORMAT);
900 XX(ICM_COMPRESS_GET_SIZE);
901 XX(ICM_COMPRESS_QUERY);
902 XX(ICM_COMPRESS_BEGIN);
904 XX(ICM_COMPRESS_END);
905 XX(ICM_DECOMPRESS_GET_FORMAT);
906 XX(ICM_DECOMPRESS_QUERY);
907 XX(ICM_DECOMPRESS_BEGIN);
909 XX(ICM_DECOMPRESS_END);
910 XX(ICM_DECOMPRESS_SET_PALETTE);
911 XX(ICM_DECOMPRESS_GET_PALETTE);
914 XX(ICM_DRAW_GET_PALETTE);
918 XX(ICM_DRAW_GETTIME);
921 XX(ICM_DRAW_SETTIME);
922 XX(ICM_DRAW_REALIZE);
924 XX(ICM_DRAW_RENDERBUFFER);
925 XX(ICM_DRAW_START_PLAY);
926 XX(ICM_DRAW_STOP_PLAY);
927 XX(ICM_DRAW_SUGGESTFORMAT);
928 XX(ICM_DRAW_CHANGEPALETTE);
929 XX(ICM_GETBUFFERSWANTED);
930 XX(ICM_GETDEFAULTKEYFRAMERATE);
931 XX(ICM_DECOMPRESSEX_BEGIN);
932 XX(ICM_DECOMPRESSEX_QUERY);
933 XX(ICM_DECOMPRESSEX);
934 XX(ICM_DECOMPRESSEX_END);
935 XX(ICM_SET_STATUS_PROC);
937 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,%i) unknown message\n",(DWORD)hic,(DWORD)msg,lParam1,lParam2,bFrom32?32:16);
942 if (!whic) return ICERR_BADHANDLE;
944 if (whic->driverproc) { /* IC is a function */
945 bDrv32 = whic->private;
947 bDrv32 = ((GetDriverFlags(whic->hdrv) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) == WINE_GDF_EXIST);
952 data16 = MSVIDEO_MapMsg16To32(msg,&lParam1,&lParam2);
955 ERR("Can't do 32->16 mappings\n");
961 if (whic->driverproc) {
963 ret = whic->driverproc(whic->hdrv,hic,msg,lParam1,lParam2);
965 ret = MSVIDEO_CallTo16_long_lwwll((FARPROC16)whic->driverproc,whic->hdrv,hic,msg,lParam1,lParam2);
968 ret = SendDriverMessage(whic->hdrv,msg,lParam1,lParam2);
972 MSVIDEO_UnmapMsg16To32(msg,data16,&lParam1,&lParam2);
977 TRACE(" -> 0x%08lx\n",ret);
981 /***********************************************************************
982 * ICSendMessage [MSVFW32.@]
984 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2) {
985 return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,TRUE);
988 /***********************************************************************
989 * ICSendMessage [MSVIDEO.205]
991 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) {
992 return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,FALSE);
995 /***********************************************************************
996 * _ICMessage [MSVIDEO.207]
998 LRESULT VFWAPIV ICMessage16(void) {
1010 hic = VA_ARG16(valist, HIC16);
1011 msg = VA_ARG16(valist, UINT16);
1012 cb = VA_ARG16(valist, UINT16);
1014 lpData = HeapAlloc( GetProcessHeap(), 0, cb );
1016 TRACE("0x%08lx, %u, %u, ...)\n",(DWORD)hic,msg,cb);
1018 for(i=0;i<cb/sizeof(WORD);i++) {
1019 lpData[i] = VA_ARG16(valist, WORD);
1023 segData = MapLS( lpData );
1024 ret = ICSendMessage16(hic, msg, segData, (DWORD)cb);
1026 HeapFree( GetProcessHeap(), 0, lpData );
1030 /***********************************************************************
1031 * ICDrawBegin [MSVFW32.@]
1033 DWORD VFWAPIV ICDrawBegin(
1035 DWORD dwFlags, /* [in] flags */
1036 HPALETTE hpal, /* [in] palette to draw with */
1037 HWND hwnd, /* [in] window to draw to */
1038 HDC hdc, /* [in] HDC to draw to */
1039 INT xDst, /* [in] destination rectangle */
1040 INT yDst, /* [in] */
1041 INT dxDst, /* [in] */
1042 INT dyDst, /* [in] */
1043 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */
1044 INT xSrc, /* [in] source rectangle */
1045 INT ySrc, /* [in] */
1046 INT dxSrc, /* [in] */
1047 INT dySrc, /* [in] */
1048 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
1049 DWORD dwScale) /* [in] */
1054 TRACE("(0x%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
1055 (DWORD)hic, dwFlags, (DWORD)hpal, (DWORD)hwnd, (DWORD)hdc, xDst, yDst, dxDst, dyDst,
1056 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
1058 icdb.dwFlags = dwFlags;
1071 icdb.dwRate = dwRate;
1072 icdb.dwScale = dwScale;
1073 return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
1076 /***********************************************************************
1077 * _ICDrawBegin [MSVIDEO.232]
1079 DWORD VFWAPIV ICDrawBegin16(
1080 HIC16 hic, /* [in] */
1081 DWORD dwFlags, /* [in] flags */
1082 HPALETTE16 hpal, /* [in] palette to draw with */
1083 HWND16 hwnd, /* [in] window to draw to */
1084 HDC16 hdc, /* [in] HDC to draw to */
1085 INT16 xDst, /* [in] destination rectangle */
1086 INT16 yDst, /* [in] */
1087 INT16 dxDst, /* [in] */
1088 INT16 dyDst, /* [in] */
1089 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw NOTE: SEGPTR */
1090 INT16 xSrc, /* [in] source rectangle */
1091 INT16 ySrc, /* [in] */
1092 INT16 dxSrc, /* [in] */
1093 INT16 dySrc, /* [in] */
1094 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
1095 DWORD dwScale) /* [in] */
1101 TRACE("(0x%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
1102 (DWORD)hic, dwFlags, (DWORD)hpal, (DWORD)hwnd, (DWORD)hdc, xDst, yDst, dxDst, dyDst,
1103 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
1105 icdb.dwFlags = dwFlags;
1113 icdb.lpbi = lpbi; /* Keep this as SEGPTR for the mapping code to deal with */
1118 icdb.dwRate = dwRate;
1119 icdb.dwScale = dwScale;
1120 seg_icdb = MapLS( &icdb );
1121 ret = (DWORD)ICSendMessage16(hic,ICM_DRAW_BEGIN,seg_icdb,sizeof(ICDRAWBEGIN16));
1122 UnMapLS( seg_icdb );
1126 /***********************************************************************
1127 * ICDraw [MSVFW32.@]
1129 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
1132 TRACE("(0x%09lx,%ld,%p,%p,%ld,%ld)\n",(DWORD)hic,dwFlags,lpFormat,lpData,cbData,lTime);
1134 icd.dwFlags = dwFlags;
1135 icd.lpFormat = lpFormat;
1136 icd.lpData = lpData;
1137 icd.cbData = cbData;
1140 return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
1143 /***********************************************************************
1144 * _ICDraw [MSVIDEO.234]
1146 DWORD VFWAPIV ICDraw16(
1149 LPVOID lpFormat, /* [???] NOTE: SEGPTR */
1150 LPVOID lpData, /* [???] NOTE: SEGPTR */
1158 TRACE("(0x%08lx,0x%08lx,%p,%p,%ld,%ld)\n",(DWORD)hic,dwFlags,lpFormat,lpData,cbData,lTime);
1159 icd.dwFlags = dwFlags;
1160 icd.lpFormat = lpFormat;
1161 icd.lpData = lpData;
1162 icd.cbData = cbData;
1164 seg_icd = MapLS( &icd );
1165 ret = ICSendMessage16(hic,ICM_DRAW,seg_icd,sizeof(ICDRAW));
1170 /***********************************************************************
1171 * ICClose [MSVFW32.@]
1173 LRESULT WINAPI ICClose(HIC hic) {
1174 WINE_HIC *whic = GlobalLock16(hic);
1175 TRACE("(0x%08lx)\n",(DWORD)hic);
1176 if (whic->driverproc) {
1177 ICSendMessage(hic,DRV_CLOSE,0,0);
1178 ICSendMessage(hic,DRV_DISABLE,0,0);
1179 ICSendMessage(hic,DRV_FREE,0,0);
1181 CloseDriver(whic->hdrv,0,0);
1184 GlobalUnlock16(hic);
1189 /***********************************************************************
1190 * ICClose [MSVIDEO.204]
1192 LRESULT WINAPI ICClose16(HIC16 hic) {
1193 return ICClose(hic);
1198 /***********************************************************************
1199 * ICImageCompress [MSVFW32.@]
1201 HANDLE VFWAPI ICImageCompress(
1202 HIC hic, UINT uiFlags,
1203 LPBITMAPINFO lpbiIn, LPVOID lpBits,
1204 LPBITMAPINFO lpbiOut, LONG lQuality,
1207 FIXME("(%08x,%08x,%p,%p,%p,%ld,%p)\n",
1208 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
1210 return (HANDLE)NULL;
1213 /***********************************************************************
1214 * ICImageDecompress [MSVFW32.@]
1217 HANDLE VFWAPI ICImageDecompress(
1218 HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
1219 LPVOID lpBits, LPBITMAPINFO lpbiOut)
1221 HGLOBAL hMem = (HGLOBAL)NULL;
1223 BOOL bReleaseIC = FALSE;
1226 BOOL bSucceeded = FALSE;
1227 BOOL bInDecompress = FALSE;
1230 TRACE("(%08x,%08x,%p,%p,%p)\n",
1231 hic, uiFlags, lpbiIn, lpBits, lpbiOut);
1233 if ( hic == (HIC)NULL )
1235 hic = ICDecompressOpen( mmioFOURCC('V','I','D','C'), 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
1236 if ( hic == (HIC)NULL )
1238 WARN("no handler\n" );
1245 FIXME( "unknown flag %08x\n", uiFlags );
1248 if ( lpbiIn == NULL || lpBits == NULL )
1250 WARN("invalid argument\n");
1254 if ( lpbiOut != NULL )
1256 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
1258 cbHdr = sizeof(BITMAPINFOHEADER);
1259 if ( lpbiOut->bmiHeader.biCompression == 3 )
1260 cbHdr += sizeof(DWORD)*3;
1262 if ( lpbiOut->bmiHeader.biBitCount <= 8 )
1264 if ( lpbiOut->bmiHeader.biClrUsed == 0 )
1265 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
1267 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
1272 TRACE( "get format\n" );
1274 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
1275 if ( cbHdr < sizeof(BITMAPINFOHEADER) )
1277 pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256);
1280 ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 );
1281 if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK )
1283 lpbiOut = (BITMAPINFO*)pHdr;
1284 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1285 ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
1286 lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
1288 if ( lpbiIn->bmiHeader.biClrUsed == 0 )
1289 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
1291 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
1293 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1294 lpbiOut->bmiHeader.biClrUsed == 0 )
1295 lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
1297 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1298 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
1301 biSizeImage = lpbiOut->bmiHeader.biSizeImage;
1302 if ( biSizeImage == 0 )
1303 biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight);
1305 TRACE( "call ICDecompressBegin\n" );
1307 if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
1309 bInDecompress = TRUE;
1311 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage );
1313 hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
1314 if ( hMem == (HGLOBAL)NULL )
1316 WARN( "out of memory\n" );
1319 pMem = (BYTE*)GlobalLock( hMem );
1322 memcpy( pMem, lpbiOut, cbHdr );
1324 TRACE( "call ICDecompress\n" );
1325 if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
1330 if ( bInDecompress )
1331 ICDecompressEnd( hic );
1335 HeapFree(GetProcessHeap(),0,pHdr);
1337 GlobalUnlock( hMem );
1338 if ( !bSucceeded && hMem != (HGLOBAL)NULL )
1340 GlobalFree(hMem); hMem = (HGLOBAL)NULL;
1343 return (HANDLE)hMem;