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.
35 #include "wine/winbase16.h"
36 #include "wine/debug.h"
37 #include "stackframe.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
41 /* ### start build ### */
42 extern LONG CALLBACK
MSVIDEO_CallTo16_long_lwwll(FARPROC16
,LONG
,WORD
,WORD
,LONG
,LONG
);
43 /* ### stop build ### */
45 LPVOID
MSVIDEO_MapMsg16To32(UINT msg
, LPDWORD lParam1
, LPDWORD lParam2
);
46 void MSVIDEO_UnmapMsg16To32(UINT msg
, LPVOID lpv
, LPDWORD lParam1
, LPDWORD lParam2
);
47 LRESULT
MSVIDEO_SendMessage(HIC hic
, UINT msg
, DWORD lParam1
, DWORD lParam2
, BOOL bFrom32
);
49 #define HDRVR_16(h32) (LOWORD(h32))
50 #define HWND_32(h16) ((HWND)(ULONG_PTR)(h16))
53 /***********************************************************************
54 * VideoForWindowsVersion [MSVFW32.2]
55 * VideoForWindowsVersion [MSVIDEO.2]
56 * Returns the version in major.minor form.
57 * In Windows95 this returns 0x040003b6 (4.950)
59 DWORD WINAPI
VideoForWindowsVersion(void) {
60 return 0x040003B6; /* 4.950 */
63 /***********************************************************************
64 * VideoCapDriverDescAndVer [MSVIDEO.22]
66 DWORD WINAPI
VideoCapDriverDescAndVer(
67 WORD nr
,LPSTR buf1
,WORD buf1len
,LPSTR buf2
,WORD buf2len
73 char *s
,buf
[2000],fn
[260];
77 TRACE("(%d,%p,%d,%p,%d)\n",nr
,buf1
,buf1len
,buf2
,buf2len
);
78 if (GetPrivateProfileStringA("drivers32",NULL
,NULL
,buf
,sizeof(buf
),"system.ini")) {
81 if (!strncasecmp(s
,"vid",3)) {
86 s
=s
+strlen(s
)+1; /* either next char or \0 */
89 return 20; /* hmm, out of entries even if we don't have any */
91 FIXME("No more VID* entries found\n");
94 GetPrivateProfileStringA("drivers32",s
,NULL
,fn
,sizeof(fn
),"system.ini");
95 infosize
= GetFileVersionInfoSizeA(fn
,&verhandle
);
97 TRACE("%s has no fileversioninfo.\n",fn
);
100 infobuf
= HeapAlloc(GetProcessHeap(),0,infosize
);
101 if (GetFileVersionInfoA(fn
,verhandle
,infosize
,infobuf
)) {
103 /* Yes, two space behind : */
104 /* FIXME: test for buflen */
105 sprintf(vbuf
,"Version: %d.%d.%d.%d\n",
106 ((WORD
*)infobuf
)[0x0f],
107 ((WORD
*)infobuf
)[0x0e],
108 ((WORD
*)infobuf
)[0x11],
109 ((WORD
*)infobuf
)[0x10]
111 TRACE("version of %s is %s\n",fn
,vbuf
);
112 strncpy(buf2
,vbuf
,buf2len
);
114 TRACE("GetFileVersionInfoA failed for %s.\n",fn
);
115 strncpy(buf2
,fn
,buf2len
); /* msvideo.dll appears to copy fn*/
117 /* FIXME: language problem? */
118 if (VerQueryValueA( infobuf
,
119 "\\StringFileInfo\\040904E4\\FileDescription",
123 TRACE("VQA returned %s\n",(LPCSTR
)subblock
);
124 strncpy(buf1
,subblock
,buf1len
);
126 TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
127 strncpy(buf1
,fn
,buf1len
); /* msvideo.dll appears to copy fn*/
129 HeapFree(GetProcessHeap(),0,infobuf
);
133 /* system.ini: [drivers] */
135 /***********************************************************************
137 * Get information about an installable compressor. Return TRUE if there
141 DWORD fccType
, /* [in] type of compressor ('vidc') */
142 DWORD fccHandler
, /* [in] <n>th compressor */
143 ICINFO
*lpicinfo
) /* [out] information about compressor */
145 char type
[5],buf
[2000];
147 memcpy(type
,&fccType
,4);type
[4]=0;
148 TRACE("(%s,%ld,%p).\n",type
,fccHandler
,lpicinfo
);
149 /* does OpenDriver/CloseDriver */
150 lpicinfo
->dwSize
= sizeof(ICINFO
);
151 lpicinfo
->fccType
= fccType
;
152 lpicinfo
->dwFlags
= 0;
153 if (GetPrivateProfileStringA("drivers32",NULL
,NULL
,buf
,2000,"system.ini")) {
156 if (!strncasecmp(type
,s
,4)) {
158 lpicinfo
->fccHandler
= mmioStringToFOURCCA(s
+5,0);
162 s
=s
+strlen(s
)+1; /* either next char or \0 */
168 /***********************************************************************
169 * ICInfo [MSVIDEO.200]
171 BOOL16 VFWAPI
ICInfo16(
172 DWORD fccType
, /* [in] */
173 DWORD fccHandler
, /* [in] */
174 ICINFO16
*lpicinfo
) /* [in/out] NOTE: SEGPTR */
178 DWORD lParam
= (DWORD
)lpicinfo
;
179 DWORD size
= ((ICINFO
*)(MapSL((SEGPTR
)lpicinfo
)))->dwSize
;
181 /* Use the mapping functions to map the ICINFO structure */
182 lpv
= MSVIDEO_MapMsg16To32(ICM_GETINFO
,&lParam
,&size
);
184 ret
= ICInfo(fccType
,fccHandler
,(ICINFO
*)lParam
);
186 MSVIDEO_UnmapMsg16To32(ICM_GETINFO
,lpv
,&lParam
,&size
);
191 /***********************************************************************
193 * Opens an installable compressor. Return special handle.
195 HIC VFWAPI
ICOpen(DWORD fccType
,DWORD fccHandler
,UINT wMode
) {
196 char type
[5],handler
[5],codecname
[20];
202 memcpy(type
,&fccType
,4);type
[4]=0;
203 memcpy(handler
,&fccHandler
,4);handler
[4]=0;
204 TRACE("(%s,%s,0x%08lx)\n",type
,handler
,(DWORD
)wMode
);
206 sprintf(codecname
,"%s.%s",type
,handler
);
208 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
209 * same layout as ICOPEN
211 icopen
.fccType
= fccType
;
212 icopen
.fccHandler
= fccHandler
;
213 icopen
.dwSize
= sizeof(ICOPEN
);
214 icopen
.dwFlags
= wMode
;
215 /* FIXME: do we need to fill out the rest too? */
216 hdrv
=OpenDriverA(codecname
,"drivers32",(LPARAM
)&icopen
);
218 if (!strcasecmp(type
,"vids")) {
219 sprintf(codecname
,"vidc.%s",handler
);
220 fccType
= mmioFOURCC('v','i','d','c');
222 hdrv
=OpenDriverA(codecname
,"drivers32",(LPARAM
)&icopen
);
226 /* The handle should be a valid 16-bit handle as well */
227 hic
= GlobalAlloc16(GHND
,sizeof(WINE_HIC
));
228 whic
= (WINE_HIC
*)GlobalLock16(hic
);
230 whic
->driverproc
= NULL
;
233 TRACE("=> 0x%08lx\n",(DWORD
)hic
);
237 HIC
MSVIDEO_OpenFunc(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
, BOOL bFrom32
) {
238 char type
[5],handler
[5],codecname
[20];
244 memcpy(type
,&fccType
,4);type
[4]=0;
245 memcpy(handler
,&fccHandler
,4);handler
[4]=0;
246 TRACE("(%s,%s,%d,%p,%d)\n",type
,handler
,wMode
,lpfnHandler
,bFrom32
?32:16);
248 icopen
.fccType
= fccType
;
249 icopen
.fccHandler
= fccHandler
;
250 icopen
.dwSize
= sizeof(ICOPEN
);
251 icopen
.dwFlags
= wMode
;
253 sprintf(codecname
,"%s.%s",type
,handler
);
255 hic
= GlobalAlloc16(GHND
,sizeof(WINE_HIC
));
258 whic
= GlobalLock16(hic
);
259 whic
->driverproc
= lpfnHandler
;
261 whic
->private = bFrom32
;
263 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
264 /* What if the function is used more than once? */
266 if (MSVIDEO_SendMessage(hic
,DRV_LOAD
,0L,0L,bFrom32
) != DRV_SUCCESS
) {
267 WARN("DRV_LOAD failed for hic 0x%08lx\n",(DWORD
)hic
);
271 /* return value is not checked */
272 MSVIDEO_SendMessage(hic
,DRV_ENABLE
,0L,0L,bFrom32
);
274 seg_icopen
= MapLS( &icopen
);
275 whic
->hdrv
= (HDRVR
)MSVIDEO_SendMessage(hic
,DRV_OPEN
,0,seg_icopen
,FALSE
);
276 UnMapLS( seg_icopen
);
277 if (whic
->hdrv
== 0) {
278 WARN("DRV_OPEN failed for hic 0x%08lx\n",(DWORD
)hic
);
284 TRACE("=> 0x%08lx\n",(DWORD
)hic
);
288 /***********************************************************************
289 * ICOpenFunction [MSVFW32.@]
291 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
) {
292 return MSVIDEO_OpenFunc(fccType
,fccHandler
,wMode
,lpfnHandler
,TRUE
);
295 /***********************************************************************
296 * ICOpenFunction [MSVIDEO.206]
298 HIC16 VFWAPI
ICOpenFunction16(DWORD fccType
, DWORD fccHandler
, UINT16 wMode
, FARPROC16 lpfnHandler
)
300 return MSVIDEO_OpenFunc(fccType
, fccHandler
, wMode
, (FARPROC
)lpfnHandler
,FALSE
);
303 /***********************************************************************
304 * ICGetInfo [MSVFW32.@]
306 LRESULT VFWAPI
ICGetInfo(HIC hic
,ICINFO
*picinfo
,DWORD cb
) {
309 TRACE("(0x%08lx,%p,%ld)\n",(DWORD
)hic
,picinfo
,cb
);
310 ret
= ICSendMessage(hic
,ICM_GETINFO
,(DWORD
)picinfo
,cb
);
311 TRACE(" -> 0x%08lx\n",ret
);
315 /***********************************************************************
316 * ICLocate [MSVFW32.@]
319 DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
320 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
322 char type
[5],handler
[5];
327 type
[4]=0;memcpy(type
,&fccType
,4);
328 handler
[4]=0;memcpy(handler
,&fccHandler
,4);
330 TRACE("(%s,%s,%p,%p,0x%04x)\n", type
, handler
, lpbiIn
, lpbiOut
, wMode
);
333 case ICMODE_FASTCOMPRESS
:
334 case ICMODE_COMPRESS
:
335 querymsg
= ICM_COMPRESS_QUERY
;
337 case ICMODE_FASTDECOMPRESS
:
338 case ICMODE_DECOMPRESS
:
339 querymsg
= ICM_DECOMPRESS_QUERY
;
342 querymsg
= ICM_DRAW_QUERY
;
345 WARN("Unknown mode (%d)\n",wMode
);
349 /* Easy case: handler/type match, we just fire a query and return */
350 hic
= ICOpen(fccType
,fccHandler
,wMode
);
352 if (!ICSendMessage(hic
,querymsg
,(DWORD
)lpbiIn
,(DWORD
)lpbiOut
))
357 type
[4]='.';memcpy(type
,&fccType
,4);
358 handler
[4]='.';memcpy(handler
,&fccHandler
,4);
360 /* Now try each driver in turn. 32 bit codecs only. */
361 /* FIXME: Move this to an init routine? */
363 pszBuffer
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,1024);
364 if (GetPrivateProfileSectionA("drivers32",pszBuffer
,1024,"system.ini")) {
367 if (!strncasecmp(type
,s
,5)) {
369 while (*s2
!= '\0' && *s2
!= '.') s2
++;
373 h
= ICOpen(fccType
,*(DWORD
*)s2
,wMode
);
375 if (!ICSendMessage(h
,querymsg
,(DWORD
)lpbiIn
,(DWORD
)lpbiOut
))
384 HeapFree(GetProcessHeap(),0,pszBuffer
);
386 if (fccType
==streamtypeVIDEO
) {
387 hic
= ICLocate(ICTYPE_VIDEO
,fccHandler
,lpbiIn
,lpbiOut
,wMode
);
392 type
[4] = handler
[4] = '\0';
393 WARN("(%.4s,%.4s,%p,%p,0x%04x) not found!\n",type
,handler
,lpbiIn
,lpbiOut
,wMode
);
397 /***********************************************************************
398 * ICGetDisplayFormat [MSVFW32.@]
400 HIC VFWAPI
ICGetDisplayFormat(
401 HIC hic
,LPBITMAPINFOHEADER lpbiIn
,LPBITMAPINFOHEADER lpbiOut
,
402 INT depth
,INT dx
,INT dy
)
406 FIXME("(0x%08lx,%p,%p,%d,%d,%d),stub!\n",(DWORD
)hic
,lpbiIn
,lpbiOut
,depth
,dx
,dy
);
408 tmphic
=ICLocate(ICTYPE_VIDEO
,0,lpbiIn
,NULL
,ICMODE_DECOMPRESS
);
412 if ((dy
== lpbiIn
->biHeight
) && (dx
== lpbiIn
->biWidth
))
413 dy
= dx
= 0; /* no resize needed */
415 /* Can we decompress it ? */
416 if (ICDecompressQuery(tmphic
,lpbiIn
,NULL
) != 0)
417 goto errout
; /* no, sorry */
419 ICDecompressGetFormat(tmphic
,lpbiIn
,lpbiOut
);
421 if (lpbiOut
->biCompression
!= 0) {
422 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
423 lpbiOut
->biCompression
);
425 if (lpbiOut
->biSize
< sizeof(*lpbiOut
)) {
426 FIXME("Ooch, size of output BIH is too small (%ld)\n",
428 lpbiOut
->biSize
= sizeof(*lpbiOut
);
434 depth
= GetDeviceCaps(hdc
,BITSPIXEL
)*GetDeviceCaps(hdc
,PLANES
);
436 if (depth
==15) depth
= 16;
437 if (depth
<8) depth
= 8;
439 if (lpbiIn
->biBitCount
== 8)
442 TRACE("=> 0x%08lx\n",(DWORD
)tmphic
);
452 /***********************************************************************
453 * ICCompress [MSVFW32.@]
457 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
458 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
459 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
460 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
464 TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD
)hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
466 iccmp
.dwFlags
= dwFlags
;
468 iccmp
.lpbiOutput
= lpbiOutput
;
469 iccmp
.lpOutput
= lpData
;
470 iccmp
.lpbiInput
= lpbiInput
;
471 iccmp
.lpInput
= lpBits
;
473 iccmp
.lpckid
= lpckid
;
474 iccmp
.lpdwFlags
= lpdwFlags
;
475 iccmp
.lFrameNum
= lFrameNum
;
476 iccmp
.dwFrameSize
= dwFrameSize
;
477 iccmp
.dwQuality
= dwQuality
;
478 iccmp
.lpbiPrev
= lpbiPrev
;
479 iccmp
.lpPrev
= lpPrev
;
480 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD
)&iccmp
,sizeof(iccmp
));
483 /***********************************************************************
484 * ICDecompress [MSVFW32.@]
486 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
487 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
492 TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD
)hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
494 TRACE("lpBits[0] == %ld\n",((LPDWORD
)lpBits
)[0]);
496 icd
.dwFlags
= dwFlags
;
497 icd
.lpbiInput
= lpbiFormat
;
498 icd
.lpInput
= lpData
;
500 icd
.lpbiOutput
= lpbi
;
501 icd
.lpOutput
= lpBits
;
503 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD
)&icd
,sizeof(ICDECOMPRESS
));
505 TRACE("lpBits[0] == %ld\n",((LPDWORD
)lpBits
)[0]);
507 TRACE("-> %ld\n",ret
);
512 #define COPY(x,y) (x->y = x##16->y);
513 #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
515 LPVOID
MSVIDEO_MapICDEX16To32(LPDWORD lParam
) {
518 ICDECOMPRESSEX
*icdx
= HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESSEX
));
519 ICDECOMPRESSEX16
*icdx16
= MapSL(*lParam
);
523 COPYPTR(icdx
,lpbiSrc
);
525 COPYPTR(icdx
,lpbiDst
);
536 *lParam
= (DWORD
)(icdx
);
540 LPVOID
MSVIDEO_MapMsg16To32(UINT msg
, LPDWORD lParam1
, LPDWORD lParam2
) {
543 TRACE("Mapping %d\n",msg
);
553 case ICM_COMPRESS_END
:
554 case ICM_DECOMPRESS_END
:
555 case ICM_DECOMPRESSEX_END
:
557 case ICM_DRAW_START_PLAY
:
558 case ICM_DRAW_STOP_PLAY
:
559 case ICM_DRAW_REALIZE
:
560 case ICM_DRAW_RENDERBUFFER
:
564 case ICM_GETDEFAULTQUALITY
:
567 case ICM_DRAW_WINDOW
:
568 case ICM_GETBUFFERSWANTED
:
569 *lParam1
= (DWORD
)MapSL(*lParam1
);
573 ICINFO
*ici
= HeapAlloc(GetProcessHeap(),0,sizeof(ICINFO
));
576 ici16
= MapSL(*lParam1
);
579 ici
->dwSize
= sizeof(ICINFO
);
581 COPY(ici
,fccHandler
);
584 COPY(ici
,dwVersionICM
);
585 MultiByteToWideChar( CP_ACP
, 0, ici16
->szName
, -1, ici
->szName
, 16 );
586 MultiByteToWideChar( CP_ACP
, 0, ici16
->szDescription
, -1, ici
->szDescription
, 128 );
587 MultiByteToWideChar( CP_ACP
, 0, ici16
->szDriver
, -1, ici
->szDriver
, 128 );
588 *lParam1
= (DWORD
)(ici
);
589 *lParam2
= sizeof(ICINFO
);
594 ICCOMPRESS
*icc
= HeapAlloc(GetProcessHeap(),0,sizeof(ICCOMPRESS
));
597 icc16
= MapSL(*lParam1
);
601 COPYPTR(icc
,lpbiOutput
);
602 COPYPTR(icc
,lpOutput
);
603 COPYPTR(icc
,lpbiInput
);
604 COPYPTR(icc
,lpInput
);
606 COPYPTR(icc
,lpdwFlags
);
608 COPY(icc
,dwFrameSize
);
610 COPYPTR(icc
,lpbiPrev
);
613 *lParam1
= (DWORD
)(icc
);
614 *lParam2
= sizeof(ICCOMPRESS
);
619 ICDECOMPRESS
*icd
= HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESS
));
620 ICDECOMPRESS
*icd16
; /* Same structure except for the pointers */
622 icd16
= MapSL(*lParam1
);
626 COPYPTR(icd
,lpbiInput
);
627 COPYPTR(icd
,lpInput
);
628 COPYPTR(icd
,lpbiOutput
);
629 COPYPTR(icd
,lpOutput
);
632 *lParam1
= (DWORD
)(icd
);
633 *lParam2
= sizeof(ICDECOMPRESS
);
636 case ICM_COMPRESS_BEGIN
:
637 case ICM_COMPRESS_GET_FORMAT
:
638 case ICM_COMPRESS_GET_SIZE
:
639 case ICM_COMPRESS_QUERY
:
640 case ICM_DECOMPRESS_GET_FORMAT
:
641 case ICM_DECOMPRESS_QUERY
:
642 case ICM_DECOMPRESS_BEGIN
:
643 case ICM_DECOMPRESS_SET_PALETTE
:
644 case ICM_DECOMPRESS_GET_PALETTE
:
645 *lParam1
= (DWORD
)MapSL(*lParam1
);
646 *lParam2
= (DWORD
)MapSL(*lParam2
);
648 case ICM_DECOMPRESSEX_QUERY
:
649 if ((*lParam2
!= sizeof(ICDECOMPRESSEX16
)) && (*lParam2
!= 0))
650 WARN("*lParam2 has unknown value %p\n",(ICDECOMPRESSEX16
*)*lParam2
);
651 /* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16)
652 * This is because of ICMessage(). Special case it?
654 LPVOID* addr = HeapAlloc(GetProcessHeap(),0,2*sizeof(LPVOID));
655 addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
657 addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
664 case ICM_DECOMPRESSEX_BEGIN
:
665 case ICM_DECOMPRESSEX
:
666 ret
= MSVIDEO_MapICDEX16To32(lParam1
);
667 *lParam2
= sizeof(ICDECOMPRESSEX
);
671 ICDRAWBEGIN
*icdb
= HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWBEGIN
));
672 ICDRAWBEGIN16
*icdb16
= MapSL(*lParam1
);
676 icdb
->hpal
= HPALETTE_32(icdb16
->hpal
);
677 icdb
->hwnd
= HWND_32(icdb16
->hwnd
);
691 *lParam1
= (DWORD
)(icdb
);
692 *lParam2
= sizeof(ICDRAWBEGIN
);
695 case ICM_DRAW_SUGGESTFORMAT
:
697 ICDRAWSUGGEST
*icds
= HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWSUGGEST
));
698 ICDRAWSUGGEST16
*icds16
= MapSL(*lParam1
);
703 COPYPTR(icds
,lpbiIn
);
704 COPYPTR(icds
,lpbiSuggest
);
709 COPY(icds
,hicDecompressor
);
711 *lParam1
= (DWORD
)(icds
);
712 *lParam2
= sizeof(ICDRAWSUGGEST
);
717 ICDRAW
*icd
= HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAW
));
718 ICDRAW
*icd16
= MapSL(*lParam1
);
722 COPYPTR(icd
,lpFormat
);
727 *lParam1
= (DWORD
)(icd
);
728 *lParam2
= sizeof(ICDRAW
);
735 FIXME("%d is not yet handled. Expect a crash.\n",msg
);
743 void MSVIDEO_UnmapMsg16To32(UINT msg
, LPVOID data16
, LPDWORD lParam1
, LPDWORD lParam2
) {
744 TRACE("Unmapping %d\n",msg
);
746 #define UNCOPY(x,y) (x##16->y = x->y);
751 ICINFO
*ici
= (ICINFO
*)(*lParam1
);
752 ICINFO16
*ici16
= (ICINFO16
*)data16
;
755 UNCOPY(ici
,fccHandler
);
757 UNCOPY(ici
,dwVersion
);
758 UNCOPY(ici
,dwVersionICM
);
759 WideCharToMultiByte( CP_ACP
, 0, ici
->szName
, -1, ici16
->szName
,
760 sizeof(ici16
->szName
), NULL
, NULL
);
761 ici16
->szName
[sizeof(ici16
->szName
)-1] = 0;
762 WideCharToMultiByte( CP_ACP
, 0, ici
->szDescription
, -1, ici16
->szDescription
,
763 sizeof(ici16
->szDescription
), NULL
, NULL
);
764 ici16
->szDescription
[sizeof(ici16
->szDescription
)-1] = 0;
765 /* This just gives garbage for some reason - BB
766 lstrcpynWtoA(ici16->szDriver,ici->szDriver,128);*/
768 HeapFree(GetProcessHeap(),0,ici
);
771 case ICM_DECOMPRESS_QUERY
:
774 HeapFree(GetProcessHeap(),0,x[0]);
776 HeapFree(GetProcessHeap(),0,x[1]);
781 case ICM_DECOMPRESSEX_QUERY
:
782 case ICM_DECOMPRESSEX_BEGIN
:
783 case ICM_DECOMPRESSEX
:
785 case ICM_DRAW_SUGGESTFORMAT
:
787 HeapFree(GetProcessHeap(),0,data16
);
790 ERR("Unmapping unmapped msg %d\n",msg
);
795 LRESULT
MSVIDEO_SendMessage(HIC hic
,UINT msg
,DWORD lParam1
,DWORD lParam2
, BOOL bFrom32
) {
797 WINE_HIC
*whic
= GlobalLock16(hic
);
801 #define XX(x) case x: TRACE("(0x%08lx,"#x",0x%08lx,0x%08lx,%d)\n",(DWORD)hic,lParam1,lParam2,bFrom32?32:16);break;
816 XX(ICM_GETDEFAULTQUALITY
);
823 XX(ICM_COMPRESS_FRAMES_INFO
);
824 XX(ICM_COMPRESS_GET_FORMAT
);
825 XX(ICM_COMPRESS_GET_SIZE
);
826 XX(ICM_COMPRESS_QUERY
);
827 XX(ICM_COMPRESS_BEGIN
);
829 XX(ICM_COMPRESS_END
);
830 XX(ICM_DECOMPRESS_GET_FORMAT
);
831 XX(ICM_DECOMPRESS_QUERY
);
832 XX(ICM_DECOMPRESS_BEGIN
);
834 XX(ICM_DECOMPRESS_END
);
835 XX(ICM_DECOMPRESS_SET_PALETTE
);
836 XX(ICM_DECOMPRESS_GET_PALETTE
);
839 XX(ICM_DRAW_GET_PALETTE
);
843 XX(ICM_DRAW_GETTIME
);
846 XX(ICM_DRAW_SETTIME
);
847 XX(ICM_DRAW_REALIZE
);
849 XX(ICM_DRAW_RENDERBUFFER
);
850 XX(ICM_DRAW_START_PLAY
);
851 XX(ICM_DRAW_STOP_PLAY
);
852 XX(ICM_DRAW_SUGGESTFORMAT
);
853 XX(ICM_DRAW_CHANGEPALETTE
);
854 XX(ICM_GETBUFFERSWANTED
);
855 XX(ICM_GETDEFAULTKEYFRAMERATE
);
856 XX(ICM_DECOMPRESSEX_BEGIN
);
857 XX(ICM_DECOMPRESSEX_QUERY
);
858 XX(ICM_DECOMPRESSEX
);
859 XX(ICM_DECOMPRESSEX_END
);
860 XX(ICM_SET_STATUS_PROC
);
862 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,%i) unknown message\n",(DWORD
)hic
,(DWORD
)msg
,lParam1
,lParam2
,bFrom32
?32:16);
867 if (!whic
) return ICERR_BADHANDLE
;
869 if (whic
->driverproc
) { /* IC is a function */
870 bDrv32
= whic
->private;
872 bDrv32
= ((GetDriverFlags(whic
->hdrv
) & (WINE_GDF_EXIST
|WINE_GDF_16BIT
)) == WINE_GDF_EXIST
);
877 data16
= MSVIDEO_MapMsg16To32(msg
,&lParam1
,&lParam2
);
880 ERR("Can't do 32->16 mappings\n");
886 if (whic
->driverproc
) {
888 ret
= whic
->driverproc(whic
->hdrv
,hic
,msg
,lParam1
,lParam2
);
890 ret
= MSVIDEO_CallTo16_long_lwwll((FARPROC16
)whic
->driverproc
,HDRVR_16(whic
->hdrv
),hic
,msg
,lParam1
,lParam2
);
893 ret
= SendDriverMessage(whic
->hdrv
,msg
,lParam1
,lParam2
);
897 MSVIDEO_UnmapMsg16To32(msg
,data16
,&lParam1
,&lParam2
);
902 TRACE(" -> 0x%08lx\n",ret
);
906 /***********************************************************************
907 * ICSendMessage [MSVFW32.@]
909 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD lParam1
, DWORD lParam2
) {
910 return MSVIDEO_SendMessage(hic
,msg
,lParam1
,lParam2
,TRUE
);
913 /***********************************************************************
914 * ICSendMessage [MSVIDEO.205]
916 LRESULT VFWAPI
ICSendMessage16(HIC16 hic
, UINT16 msg
, DWORD lParam1
, DWORD lParam2
) {
917 return MSVIDEO_SendMessage(hic
,msg
,lParam1
,lParam2
,FALSE
);
920 /***********************************************************************
921 * ICDrawBegin [MSVFW32.@]
923 DWORD VFWAPIV
ICDrawBegin(
925 DWORD dwFlags
, /* [in] flags */
926 HPALETTE hpal
, /* [in] palette to draw with */
927 HWND hwnd
, /* [in] window to draw to */
928 HDC hdc
, /* [in] HDC to draw to */
929 INT xDst
, /* [in] destination rectangle */
931 INT dxDst
, /* [in] */
932 INT dyDst
, /* [in] */
933 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
934 INT xSrc
, /* [in] source rectangle */
936 INT dxSrc
, /* [in] */
937 INT dySrc
, /* [in] */
938 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
939 DWORD dwScale
) /* [in] */
944 TRACE("(0x%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
945 (DWORD
)hic
, dwFlags
, (DWORD
)hpal
, (DWORD
)hwnd
, (DWORD
)hdc
, xDst
, yDst
, dxDst
, dyDst
,
946 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
948 icdb
.dwFlags
= dwFlags
;
961 icdb
.dwRate
= dwRate
;
962 icdb
.dwScale
= dwScale
;
963 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD
)&icdb
,sizeof(icdb
));
966 /***********************************************************************
969 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
972 TRACE("(0x%09lx,%ld,%p,%p,%ld,%ld)\n",(DWORD
)hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
974 icd
.dwFlags
= dwFlags
;
975 icd
.lpFormat
= lpFormat
;
980 return ICSendMessage(hic
,ICM_DRAW
,(DWORD
)&icd
,sizeof(icd
));
983 /***********************************************************************
984 * ICClose [MSVFW32.@]
986 LRESULT WINAPI
ICClose(HIC hic
) {
987 WINE_HIC
*whic
= GlobalLock16(hic
);
988 TRACE("(0x%08lx)\n",(DWORD
)hic
);
989 if (whic
->driverproc
) {
990 ICSendMessage(hic
,DRV_CLOSE
,0,0);
991 ICSendMessage(hic
,DRV_DISABLE
,0,0);
992 ICSendMessage(hic
,DRV_FREE
,0,0);
994 CloseDriver(whic
->hdrv
,0,0);
1004 /***********************************************************************
1005 * ICImageCompress [MSVFW32.@]
1007 HANDLE VFWAPI
ICImageCompress(
1008 HIC hic
, UINT uiFlags
,
1009 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
1010 LPBITMAPINFO lpbiOut
, LONG lQuality
,
1013 FIXME("(%08x,%08x,%p,%p,%p,%ld,%p)\n",
1014 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
1016 return (HANDLE
)NULL
;
1019 /***********************************************************************
1020 * ICImageDecompress [MSVFW32.@]
1023 HANDLE VFWAPI
ICImageDecompress(
1024 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
1025 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
1027 HGLOBAL hMem
= (HGLOBAL
)NULL
;
1029 BOOL bReleaseIC
= FALSE
;
1032 BOOL bSucceeded
= FALSE
;
1033 BOOL bInDecompress
= FALSE
;
1036 TRACE("(%08x,%08x,%p,%p,%p)\n",
1037 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
1039 if ( hic
== (HIC
)NULL
)
1041 hic
= ICDecompressOpen( mmioFOURCC('V','I','D','C'), 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
1042 if ( hic
== (HIC
)NULL
)
1044 WARN("no handler\n" );
1051 FIXME( "unknown flag %08x\n", uiFlags
);
1054 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1056 WARN("invalid argument\n");
1060 if ( lpbiOut
!= NULL
)
1062 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1064 cbHdr
= sizeof(BITMAPINFOHEADER
);
1065 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1066 cbHdr
+= sizeof(DWORD
)*3;
1068 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1070 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1071 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1073 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1078 TRACE( "get format\n" );
1080 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1081 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1083 pHdr
= (BYTE
*)HeapAlloc(GetProcessHeap(),0,cbHdr
+sizeof(RGBQUAD
)*256);
1086 ZeroMemory( pHdr
, cbHdr
+sizeof(RGBQUAD
)*256 );
1087 if ( ICDecompressGetFormat( hic
, lpbiIn
, (BITMAPINFO
*)pHdr
) != ICERR_OK
)
1089 lpbiOut
= (BITMAPINFO
*)pHdr
;
1090 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1091 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1092 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1094 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1095 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1097 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1099 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1100 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1101 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1103 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1104 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1107 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1108 if ( biSizeImage
== 0 )
1109 biSizeImage
= ((((lpbiOut
->bmiHeader
.biWidth
* lpbiOut
->bmiHeader
.biBitCount
+ 7) >> 3) + 3) & (~3)) * abs(lpbiOut
->bmiHeader
.biHeight
);
1111 TRACE( "call ICDecompressBegin\n" );
1113 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1115 bInDecompress
= TRUE
;
1117 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1119 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1120 if ( hMem
== (HGLOBAL
)NULL
)
1122 WARN( "out of memory\n" );
1125 pMem
= (BYTE
*)GlobalLock( hMem
);
1128 memcpy( pMem
, lpbiOut
, cbHdr
);
1130 TRACE( "call ICDecompress\n" );
1131 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1136 if ( bInDecompress
)
1137 ICDecompressEnd( hic
);
1141 HeapFree(GetProcessHeap(),0,pHdr
);
1143 GlobalUnlock( hMem
);
1144 if ( !bSucceeded
&& hMem
!= (HGLOBAL
)NULL
)
1146 GlobalFree(hMem
); hMem
= (HGLOBAL
)NULL
;
1149 return (HANDLE
)hMem
;