Fixed cut&paste problem in SETRTS.
[wine] / dlls / msvideo / msvideo_main.c
1 /*
2  * Copyright 1998 Marcus Meissner
3  * Copyright 2000 Bradley Baetz 
4  *
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.
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "winbase.h"
14 #include "windef.h"
15 #include "winnls.h"
16 #include "wingdi.h"
17 #include "winuser.h"
18 #include "winver.h"
19 #include "vfw.h"
20 #include "vfw16.h"
21 #include "wine/winbase16.h"
22 #include "debugtools.h"
23 #include "stackframe.h"
24
25 DEFAULT_DEBUG_CHANNEL(msvideo);
26
27 /* ### start build ### */
28 extern LONG CALLBACK MSVIDEO_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
29 /* ### stop build ### */
30
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);
34
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)
40  */
41 DWORD WINAPI VideoForWindowsVersion(void) {
42         return 0x040003B6; /* 4.950 */
43 }
44
45 /***********************************************************************
46  *              VideoCapDriverDescAndVer        [MSVIDEO.22]
47  */
48 DWORD WINAPI VideoCapDriverDescAndVer(
49         WORD nr,LPSTR buf1,WORD buf1len,LPSTR buf2,WORD buf2len
50 ) {
51         DWORD   verhandle;
52         WORD    xnr = nr;
53         DWORD   infosize;
54         UINT    subblocklen;
55         char    *s,buf[2000],fn[260];
56         LPBYTE  infobuf;
57         LPVOID  subblock;
58
59         TRACE("(%d,%p,%d,%p,%d)\n",nr,buf1,buf1len,buf2,buf2len);
60         if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,sizeof(buf),"system.ini")) {
61                 s = buf;
62                 while (*s) {
63                         if (!strncasecmp(s,"vid",3)) {
64                             if (!xnr)
65                                 break;
66                             xnr--;
67                         }
68                         s=s+strlen(s)+1; /* either next char or \0 */
69                 }
70         } else
71             return 20; /* hmm, out of entries even if we don't have any */
72         if (xnr) {
73                 FIXME("No more VID* entries found\n");
74                 return 20;
75         }
76         GetPrivateProfileStringA("drivers32",s,NULL,fn,sizeof(fn),"system.ini");
77         infosize = GetFileVersionInfoSizeA(fn,&verhandle);
78         if (!infosize) {
79             TRACE("%s has no fileversioninfo.\n",fn);
80             return 18;
81         }
82         infobuf = HeapAlloc(GetProcessHeap(),0,infosize);
83         if (GetFileVersionInfoA(fn,verhandle,infosize,infobuf)) {
84             char        vbuf[200];
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]
92             );
93             TRACE("version of %s is %s\n",fn,vbuf);
94             strncpy(buf2,vbuf,buf2len);
95         } else {
96             TRACE("GetFileVersionInfoA failed for %s.\n",fn);
97             strncpy(buf2,fn,buf2len); /* msvideo.dll appears to copy fn*/
98         }
99         /* FIXME: language problem? */
100         if (VerQueryValueA(     infobuf,
101                                 "\\StringFileInfo\\040904E4\\FileDescription",
102                                 &subblock,
103                                 &subblocklen
104         )) {
105             TRACE("VQA returned %s\n",(LPCSTR)subblock);
106             strncpy(buf1,subblock,buf1len);
107         } else {
108             TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
109             strncpy(buf1,fn,buf1len); /* msvideo.dll appears to copy fn*/
110         }
111         HeapFree(GetProcessHeap(),0,infobuf);
112         return 0;
113 }
114
115 /* system.ini: [drivers] */
116
117 /***********************************************************************
118  *              ICInfo                          [MSVFW32.@]
119  * Get information about an installable compressor. Return TRUE if there
120  * is one.
121  */
122 BOOL VFWAPI ICInfo(
123         DWORD fccType,          /* [in] type of compressor ('vidc') */
124         DWORD fccHandler,       /* [in] <n>th compressor */
125         ICINFO *lpicinfo)       /* [out] information about compressor */
126 {
127         char    type[5],buf[2000];
128
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")) {
136                 char *s = buf;
137                 while (*s) {
138                         if (!strncasecmp(type,s,4)) {
139                                 if(!fccHandler--) {
140                                         lpicinfo->fccHandler = mmioStringToFOURCCA(s+5,0);
141                                         return TRUE;
142                                 }
143                         }
144                         s=s+strlen(s)+1; /* either next char or \0 */
145                 }
146         }
147         return FALSE;
148 }
149
150 /***********************************************************************
151  *              ICInfo                          [MSVIDEO.200]
152  */
153 BOOL16 VFWAPI ICInfo16(
154         DWORD     fccType,    /* [in] */
155         DWORD     fccHandler, /* [in] */
156         ICINFO16 *lpicinfo)   /* [in/out] NOTE: SEGPTR */
157 {
158         BOOL16 ret;
159         LPVOID lpv;
160         DWORD lParam = (DWORD)lpicinfo;
161         DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;
162
163         /* Use the mapping functions to map the ICINFO structure */
164         lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO,&lParam,&size);
165
166         ret = ICInfo(fccType,fccHandler,(ICINFO*)lParam);
167
168         MSVIDEO_UnmapMsg16To32(ICM_GETINFO,lpv,&lParam,&size);
169         
170         return ret;
171 }
172
173 /***********************************************************************
174  *              ICOpen                          [MSVFW32.@]
175  * Opens an installable compressor. Return special handle.
176  */
177 HIC VFWAPI ICOpen(DWORD fccType,DWORD fccHandler,UINT wMode) {
178         char            type[5],handler[5],codecname[20];
179         ICOPEN          icopen;
180         HDRVR           hdrv;
181         HIC16           hic;
182         WINE_HIC        *whic;
183
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);
187
188         sprintf(codecname,"%s.%s",type,handler);
189
190         /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the 
191          * same layout as ICOPEN
192          */
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);
199         if (!hdrv) {
200             if (!strcasecmp(type,"vids")) {
201                 sprintf(codecname,"vidc.%s",handler);
202                 fccType = mmioFOURCC('v','i','d','c');
203             }
204             hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
205             if (!hdrv)
206                     return 0;
207         }
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);
211         whic->hdrv      = hdrv;
212         whic->driverproc= NULL;
213         whic->private   = 0;
214         GlobalUnlock16(hic);
215         TRACE("=> 0x%08lx\n",(DWORD)hic);
216         return hic;
217 }
218
219 HIC MSVIDEO_OpenFunc(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler, BOOL bFrom32) {
220         char    type[5],handler[5],codecname[20];
221         HIC16   hic;
222         ICOPEN icopen;
223         SEGPTR seg_icopen;
224         WINE_HIC        *whic;
225
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);
229
230         icopen.fccType    = fccType;
231         icopen.fccHandler = fccHandler;
232         icopen.dwSize     = sizeof(ICOPEN);
233         icopen.dwFlags    = wMode;
234
235         sprintf(codecname,"%s.%s",type,handler);
236
237         hic = GlobalAlloc16(GHND,sizeof(WINE_HIC));
238         if (!hic)
239                 return 0;
240         whic = GlobalLock16(hic);
241         whic->driverproc = lpfnHandler;
242         
243         whic->private = bFrom32;
244         
245         /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
246         /* What if the function is used more than once? */
247         
248         if (MSVIDEO_SendMessage(hic,DRV_LOAD,0L,0L,bFrom32) != DRV_SUCCESS) {
249                 WARN("DRV_LOAD failed for hic 0x%08lx\n",(DWORD)hic);
250                 GlobalFree16(hic);
251                 return 0;
252         }
253         /* return value is not checked */
254         MSVIDEO_SendMessage(hic,DRV_ENABLE,0L,0L,bFrom32);
255
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);
261                 GlobalFree16(hic);
262                 return 0;
263         }
264
265         GlobalUnlock16(hic);
266         TRACE("=> 0x%08lx\n",(DWORD)hic);
267         return hic;
268 }
269
270 /***********************************************************************
271  *              ICOpenFunction                  [MSVFW32.@]
272  */
273 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) {
274         return MSVIDEO_OpenFunc(fccType,fccHandler,wMode,lpfnHandler,TRUE);
275 }
276
277 /***********************************************************************
278  *              ICOpen                          [MSVIDEO.203]
279  */
280 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode) {
281         return (HIC16)ICOpen(fccType, fccHandler, wMode);
282 }
283
284 /***********************************************************************
285  *              ICOpenFunction                  [MSVIDEO.206]
286  */
287 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
288 {
289         return MSVIDEO_OpenFunc(fccType, fccHandler, wMode, (FARPROC)lpfnHandler,FALSE);
290 }
291
292 /***********************************************************************
293  *              ICGetInfo                       [MSVFW32.@]
294  */
295 LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) {
296         LRESULT         ret;
297
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);
301         return ret;
302 }
303
304 /***********************************************************************
305  *              ICGetInfo                       [MSVIDEO.212]
306  */
307 LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 *picinfo,DWORD cb) {
308         LRESULT         ret;
309
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);
313         return ret;
314 }
315
316 /***********************************************************************
317  *              ICLocate                        [MSVFW32.@]
318  */
319 HIC VFWAPI ICLocate(
320         DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
321         LPBITMAPINFOHEADER lpbiOut, WORD wMode)
322 {
323         char    type[5],handler[5];
324         HIC     hic;
325         DWORD   querymsg;
326         LPSTR pszBuffer;
327
328         type[4]=0;memcpy(type,&fccType,4);
329         handler[4]=0;memcpy(handler,&fccHandler,4);
330
331         TRACE("(%s,%s,%p,%p,0x%04x)\n", type, handler, lpbiIn, lpbiOut, wMode);
332
333         switch (wMode) {
334         case ICMODE_FASTCOMPRESS:
335         case ICMODE_COMPRESS: 
336                 querymsg = ICM_COMPRESS_QUERY;
337                 break;
338         case ICMODE_FASTDECOMPRESS:
339         case ICMODE_DECOMPRESS:
340                 querymsg = ICM_DECOMPRESS_QUERY;
341                 break;
342         case ICMODE_DRAW:
343                 querymsg = ICM_DRAW_QUERY;
344                 break;
345         default:
346                 WARN("Unknown mode (%d)\n",wMode);
347                 return 0;
348         }
349
350         /* Easy case: handler/type match, we just fire a query and return */
351         hic = ICOpen(fccType,fccHandler,wMode);
352         if (hic) {
353                 if (!ICSendMessage(hic,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
354                         return hic;
355                 ICClose(hic);
356         }
357
358         type[4]='.';memcpy(type,&fccType,4);
359         handler[4]='.';memcpy(handler,&fccHandler,4);
360
361         /* Now try each driver in turn. 32 bit codecs only. */
362         /* FIXME: Move this to an init routine? */
363         
364         pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(),0,1024);
365         if (GetPrivateProfileSectionA("drivers32",pszBuffer,1024,"system.ini")) {
366                 char* s = pszBuffer;
367                 while (*s) {
368                         if (!strncasecmp(type,s,5)) {
369                                 char *s2 = s;
370                                 while (*s2 != '\0' && *s2 != '.') s2++;
371                                 if (*s2++) {
372                                         HIC h;
373
374                                         h = ICOpen(fccType,*(DWORD*)s2,wMode);
375                                         if (h) {
376                                                 if (!ICSendMessage(h,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
377                                                         return h;
378                                                 ICClose(h);
379                                         }
380                                 }
381                         }
382                         s += strlen(s) + 1;
383                 }
384         }
385         HeapFree(GetProcessHeap(),0,pszBuffer);
386         
387         if (fccType==streamtypeVIDEO) {
388                 hic = ICLocate(ICTYPE_VIDEO,fccHandler,lpbiIn,lpbiOut,wMode);
389                 if (hic)
390                         return hic;
391         }
392
393         type[4] = handler[4] = '\0';
394         WARN("(%.4s,%.4s,%p,%p,0x%04x) not found!\n",type,handler,lpbiIn,lpbiOut,wMode);
395         return 0;
396 }
397
398 /***********************************************************************
399  *              ICLocate                        [MSVIDEO.213]
400  */
401 HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
402                                                 LPBITMAPINFOHEADER lpbiOut, WORD wFlags) {
403         return (HIC16)ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags);
404 }
405
406 /***********************************************************************
407  *              ICGetDisplayFormat                      [MSVFW32.@]
408  */
409 HIC VFWAPI ICGetDisplayFormat(
410         HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
411         INT depth,INT dx,INT dy)
412 {
413         HIC     tmphic = hic; 
414
415         FIXME("(0x%08lx,%p,%p,%d,%d,%d),stub!\n",(DWORD)hic,lpbiIn,lpbiOut,depth,dx,dy);
416         if (!tmphic) {
417                 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
418                 if (!tmphic)
419                         return tmphic;
420         }
421         if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
422                 dy = dx = 0; /* no resize needed */
423
424         /* Can we decompress it ? */
425         if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
426                 goto errout; /* no, sorry */
427
428         ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
429
430         if (lpbiOut->biCompression != 0) {
431            FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
432                          lpbiOut->biCompression);
433         }
434         if (lpbiOut->biSize < sizeof(*lpbiOut)) {
435            FIXME("Ooch, size of output BIH is too small (%ld)\n",
436                          lpbiOut->biSize);
437            lpbiOut->biSize = sizeof(*lpbiOut);
438         }
439         if (!depth) {
440                 HDC     hdc;
441
442                 hdc = GetDC(0);
443                 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
444                 ReleaseDC(0,hdc);
445                 if (depth==15)  depth = 16;
446                 if (depth<8)    depth =  8;
447         }
448         if (lpbiIn->biBitCount == 8)
449                 depth = 8;
450         
451         TRACE("=> 0x%08lx\n",(DWORD)tmphic);
452         return tmphic;
453 errout:
454         if (hic!=tmphic)
455                 ICClose(tmphic);
456
457         TRACE("=> 0\n");
458         return 0;
459 }
460
461 /***********************************************************************
462  *              ICGetDisplayFormat                      [MSVIDEO.239]
463  */
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);
467 }
468
469 /***********************************************************************
470  *              ICCompress                      [MSVFW32.@]
471  */
472 DWORD VFWAPIV
473 ICCompress(
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)
478 {
479         ICCOMPRESS      iccmp;
480
481         TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
482
483         iccmp.dwFlags           = dwFlags;
484
485         iccmp.lpbiOutput        = lpbiOutput;
486         iccmp.lpOutput          = lpData;
487         iccmp.lpbiInput         = lpbiInput;
488         iccmp.lpInput           = lpBits;
489
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));
498 }
499
500 /***********************************************************************
501  *              _ICCompress                     [MSVIDEO.224]
502  */
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) {
507
508         DWORD ret;
509         ICCOMPRESS iccmp;
510         SEGPTR seg_iccmp;
511
512         TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
513
514         iccmp.dwFlags     = dwFlags;
515
516         iccmp.lpbiOutput  = lpbiOutput;
517         iccmp.lpOutput    = lpData;
518         iccmp.lpbiInput   = lpbiInput;
519         iccmp.lpInput     = lpBits;
520
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 );
531         return ret;
532 }
533
534 /***********************************************************************
535  *              ICDecompress                    [MSVFW32.@]
536  */
537 DWORD VFWAPIV  ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
538                                 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
539 {
540         ICDECOMPRESS    icd;
541         DWORD ret;
542
543         TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
544
545         TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
546
547         icd.dwFlags     = dwFlags;
548         icd.lpbiInput   = lpbiFormat;
549         icd.lpInput     = lpData;
550
551         icd.lpbiOutput  = lpbi;
552         icd.lpOutput    = lpBits;
553         icd.ckid        = 0;
554         ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
555
556         TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
557
558         TRACE("-> %ld\n",ret);
559
560         return ret;
561 }
562
563 /***********************************************************************
564  *              _ICDecompress                   [MSVIDEO.230]
565  */
566 DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat,
567                              LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
568 {
569         ICDECOMPRESS icd;
570         SEGPTR segptr;
571         DWORD ret;
572         
573         TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
574
575         icd.dwFlags = dwFlags;
576         icd.lpbiInput = lpbiFormat;
577         icd.lpInput = lpData;
578         icd.lpbiOutput = lpbi;
579         icd.lpOutput = lpBits;
580         icd.ckid = 0;
581         segptr = MapLS( &icd );
582         ret = ICSendMessage16(hic,ICM_DECOMPRESS,segptr,sizeof(ICDECOMPRESS));
583         UnMapLS( segptr );
584         return ret;
585 }
586
587 #define COPY(x,y) (x->y = x##16->y);
588 #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
589
590 LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam) {
591         LPVOID ret;
592
593         ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESSEX));
594         ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam);
595         ret = icdx16;
596         
597         COPY(icdx,dwFlags);
598         COPYPTR(icdx,lpbiSrc);
599         COPYPTR(icdx,lpSrc);
600         COPYPTR(icdx,lpbiDst);
601         COPYPTR(icdx,lpDst);
602         COPY(icdx,xDst);
603         COPY(icdx,yDst);
604         COPY(icdx,dxDst);
605         COPY(icdx,dyDst);
606         COPY(icdx,xSrc);
607         COPY(icdx,ySrc);
608         COPY(icdx,dxSrc);
609         COPY(icdx,dySrc);
610         
611         *lParam = (DWORD)(icdx);
612         return ret;
613 }
614
615 LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2) {
616         LPVOID ret = 0;
617         
618         TRACE("Mapping %d\n",msg);
619
620         switch (msg) {
621         case DRV_LOAD:
622         case DRV_ENABLE:
623         case DRV_CLOSE:
624         case DRV_DISABLE:
625         case DRV_FREE:
626         case ICM_ABOUT:
627         case ICM_CONFIGURE:
628         case ICM_COMPRESS_END:
629         case ICM_DECOMPRESS_END:
630         case ICM_DECOMPRESSEX_END:
631         case ICM_SETQUALITY:
632         case ICM_DRAW_START_PLAY:
633         case ICM_DRAW_STOP_PLAY:
634         case ICM_DRAW_REALIZE:
635         case ICM_DRAW_RENDERBUFFER:
636         case ICM_DRAW_END:
637                 break;
638         case DRV_OPEN:
639         case ICM_GETDEFAULTQUALITY:
640         case ICM_GETQUALITY:
641         case ICM_SETSTATE:
642         case ICM_DRAW_WINDOW:
643         case ICM_GETBUFFERSWANTED:
644                 *lParam1 = (DWORD)MapSL(*lParam1);
645                 break;
646         case ICM_GETINFO:
647                 {
648                         ICINFO *ici = HeapAlloc(GetProcessHeap(),0,sizeof(ICINFO));
649                         ICINFO16 *ici16;
650
651                         ici16 = MapSL(*lParam1);
652                         ret = ici16;
653
654                         ici->dwSize = sizeof(ICINFO);
655                         COPY(ici,fccType);
656                         COPY(ici,fccHandler);
657                         COPY(ici,dwFlags);
658                         COPY(ici,dwVersion);
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);
665                 }
666                 break;
667         case ICM_COMPRESS:
668                 {
669                         ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(),0,sizeof(ICCOMPRESS));
670                         ICCOMPRESS *icc16;
671
672                         icc16 = MapSL(*lParam1);
673                         ret = icc16;
674
675                         COPY(icc,dwFlags);
676                         COPYPTR(icc,lpbiOutput);
677                         COPYPTR(icc,lpOutput);
678                         COPYPTR(icc,lpbiInput);
679                         COPYPTR(icc,lpInput);
680                         COPYPTR(icc,lpckid);
681                         COPYPTR(icc,lpdwFlags);
682                         COPY(icc,lFrameNum);
683                         COPY(icc,dwFrameSize);
684                         COPY(icc,dwQuality);
685                         COPYPTR(icc,lpbiPrev);
686                         COPYPTR(icc,lpPrev);
687                         
688                         *lParam1 = (DWORD)(icc);
689                         *lParam2 = sizeof(ICCOMPRESS);
690                 }
691                 break;
692         case ICM_DECOMPRESS:
693                 {
694                         ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESS));
695                         ICDECOMPRESS *icd16; /* Same structure except for the pointers */
696                         
697                         icd16 = MapSL(*lParam1);
698                         ret = icd16;
699                         
700                         COPY(icd,dwFlags);
701                         COPYPTR(icd,lpbiInput);
702                         COPYPTR(icd,lpInput);
703                         COPYPTR(icd,lpbiOutput);
704                         COPYPTR(icd,lpOutput);
705                         COPY(icd,ckid);
706                         
707                         *lParam1 = (DWORD)(icd);
708                         *lParam2 = sizeof(ICDECOMPRESS);
709                 }
710                 break;
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);
722                 break;
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?
728                  {
729                  LPVOID* addr = HeapAlloc(GetProcessHeap(),0,2*sizeof(LPVOID));
730                  addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
731                  if (*lParam2)
732                  addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
733                  else
734                  addr[1] = 0;
735                  
736                  ret = addr;
737                  }
738                  break;*/
739         case ICM_DECOMPRESSEX_BEGIN:
740         case ICM_DECOMPRESSEX:
741                 ret = MSVIDEO_MapICDEX16To32(lParam1);
742                 *lParam2 = sizeof(ICDECOMPRESSEX);
743                 break;
744         case ICM_DRAW_BEGIN:
745                 {
746                         ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWBEGIN));
747                         ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1);
748                         ret = icdb16;
749
750                         COPY(icdb,dwFlags);
751                         COPY(icdb,hpal);
752                         COPY(icdb,hwnd);
753                         COPY(icdb,hdc);
754                         COPY(icdb,xDst);
755                         COPY(icdb,yDst);
756                         COPY(icdb,dxDst);
757                         COPY(icdb,dyDst);
758                         COPYPTR(icdb,lpbi);
759                         COPY(icdb,xSrc);
760                         COPY(icdb,ySrc);
761                         COPY(icdb,dxSrc);
762                         COPY(icdb,dySrc);
763                         COPY(icdb,dwRate);
764                         COPY(icdb,dwScale);
765
766                         *lParam1 = (DWORD)(icdb);
767                         *lParam2 = sizeof(ICDRAWBEGIN);
768                 }
769                 break;
770         case ICM_DRAW_SUGGESTFORMAT:
771                 {
772                         ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWSUGGEST));
773                         ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1);
774                         
775                         ret = icds16;
776
777                         COPY(icds,dwFlags);
778                         COPYPTR(icds,lpbiIn);
779                         COPYPTR(icds,lpbiSuggest);
780                         COPY(icds,dxSrc);
781                         COPY(icds,dySrc);
782                         COPY(icds,dxDst);
783                         COPY(icds,dyDst);
784                         COPY(icds,hicDecompressor);
785
786                         *lParam1 = (DWORD)(icds);
787                         *lParam2 = sizeof(ICDRAWSUGGEST);
788                 }
789                 break;
790         case ICM_DRAW:
791                 {
792                         ICDRAW *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAW));
793                         ICDRAW *icd16 = MapSL(*lParam1);
794                         ret = icd16;
795
796                         COPY(icd,dwFlags);
797                         COPYPTR(icd,lpFormat);
798                         COPYPTR(icd,lpData);
799                         COPY(icd,cbData);
800                         COPY(icd,lTime);
801
802                         *lParam1 = (DWORD)(icd);
803                         *lParam2 = sizeof(ICDRAW);
804                 }
805                 break;
806         case ICM_DRAW_START:
807         case ICM_DRAW_STOP:
808                 break;
809         default:
810                 FIXME("%d is not yet handled. Expect a crash.\n",msg);
811         }
812         return ret;
813 }
814
815 #undef COPY
816 #undef COPYPTR
817
818 void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2) {
819         TRACE("Unmapping %d\n",msg);
820
821 #define UNCOPY(x,y) (x##16->y = x->y);
822
823         switch (msg) {
824         case ICM_GETINFO:
825                 {
826                         ICINFO *ici = (ICINFO*)(*lParam1);
827                         ICINFO16 *ici16 = (ICINFO16*)data16;
828
829                         UNCOPY(ici,fccType);
830                         UNCOPY(ici,fccHandler);
831                         UNCOPY(ici,dwFlags);
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);*/
842
843                         HeapFree(GetProcessHeap(),0,ici);
844                 }
845                 break;
846         case ICM_DECOMPRESS_QUERY:
847                 /*{
848                   LPVOID* x = data16;
849                   HeapFree(GetProcessHeap(),0,x[0]);
850                   if (x[1])
851                   HeapFree(GetProcessHeap(),0,x[1]);
852                   }
853                   break;*/
854         case ICM_COMPRESS:
855         case ICM_DECOMPRESS:
856         case ICM_DECOMPRESSEX_QUERY:
857         case ICM_DECOMPRESSEX_BEGIN:
858         case ICM_DECOMPRESSEX:
859         case ICM_DRAW_BEGIN:
860         case ICM_DRAW_SUGGESTFORMAT:
861         case ICM_DRAW:
862                 HeapFree(GetProcessHeap(),0,data16);
863                 break;
864         default:
865                 ERR("Unmapping unmapped msg %d\n",msg);
866         }
867 #undef UNCOPY           
868 }
869
870 LRESULT MSVIDEO_SendMessage(HIC hic,UINT msg,DWORD lParam1,DWORD lParam2, BOOL bFrom32) {
871         LRESULT         ret;
872         WINE_HIC        *whic = GlobalLock16(hic);
873         LPVOID data16 = 0;
874         BOOL bDrv32;
875
876 #define XX(x) case x: TRACE("(0x%08lx,"#x",0x%08lx,0x%08lx,%d)\n",(DWORD)hic,lParam1,lParam2,bFrom32?32:16);break;
877
878         switch (msg) {
879                 /* DRV_* */
880                 XX(DRV_LOAD);
881                 XX(DRV_ENABLE);
882                 XX(DRV_OPEN);
883                 XX(DRV_CLOSE);
884                 XX(DRV_DISABLE);
885                 XX(DRV_FREE);
886                 /* ICM_RESERVED+X */
887                 XX(ICM_ABOUT);
888                 XX(ICM_CONFIGURE);
889                 XX(ICM_GET);
890                 XX(ICM_GETINFO);
891                 XX(ICM_GETDEFAULTQUALITY);
892                 XX(ICM_GETQUALITY);
893                 XX(ICM_GETSTATE);
894                 XX(ICM_SETQUALITY);
895                 XX(ICM_SET);
896                 XX(ICM_SETSTATE);
897                 /* ICM_USER+X */
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);
903                 XX(ICM_COMPRESS);
904                 XX(ICM_COMPRESS_END);
905                 XX(ICM_DECOMPRESS_GET_FORMAT);
906                 XX(ICM_DECOMPRESS_QUERY);
907                 XX(ICM_DECOMPRESS_BEGIN);
908                 XX(ICM_DECOMPRESS);
909                 XX(ICM_DECOMPRESS_END);
910                 XX(ICM_DECOMPRESS_SET_PALETTE);
911                 XX(ICM_DECOMPRESS_GET_PALETTE);
912                 XX(ICM_DRAW_QUERY);
913                 XX(ICM_DRAW_BEGIN);
914                 XX(ICM_DRAW_GET_PALETTE);
915                 XX(ICM_DRAW_START);
916                 XX(ICM_DRAW_STOP);
917                 XX(ICM_DRAW_END);
918                 XX(ICM_DRAW_GETTIME);
919                 XX(ICM_DRAW);
920                 XX(ICM_DRAW_WINDOW);
921                 XX(ICM_DRAW_SETTIME);
922                 XX(ICM_DRAW_REALIZE);
923                 XX(ICM_DRAW_FLUSH);
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);
936         default:
937                 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,%i) unknown message\n",(DWORD)hic,(DWORD)msg,lParam1,lParam2,bFrom32?32:16);
938         }
939
940 #undef XX
941
942         if (!whic) return ICERR_BADHANDLE;
943
944         if (whic->driverproc) { /* IC is a function */
945                 bDrv32 = whic->private;
946         } else {
947                 bDrv32 = ((GetDriverFlags(whic->hdrv) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) == WINE_GDF_EXIST);
948         }
949
950         if (!bFrom32) {
951                 if (bDrv32)
952                         data16 = MSVIDEO_MapMsg16To32(msg,&lParam1,&lParam2);
953         } else {
954                 if (!bDrv32) {
955                         ERR("Can't do 32->16 mappings\n");
956                         ret = -1;
957                         goto out;
958                 }
959         }
960         
961         if (whic->driverproc) {
962                 if (bDrv32) {
963                         ret = whic->driverproc(whic->hdrv,hic,msg,lParam1,lParam2);
964                 } else {
965                         ret = MSVIDEO_CallTo16_long_lwwll((FARPROC16)whic->driverproc,whic->hdrv,hic,msg,lParam1,lParam2);
966                 }
967         } else {
968                 ret = SendDriverMessage(whic->hdrv,msg,lParam1,lParam2);
969         }
970
971         if (data16)
972                 MSVIDEO_UnmapMsg16To32(msg,data16,&lParam1,&lParam2);
973  
974  out:
975         GlobalUnlock16(hic);
976         
977         TRACE(" -> 0x%08lx\n",ret);
978         return ret;
979 }
980
981 /***********************************************************************
982  *              ICSendMessage                   [MSVFW32.@]
983  */
984 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2) {
985         return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,TRUE);
986 }
987
988 /***********************************************************************
989  *              ICSendMessage                   [MSVIDEO.205]
990  */
991 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) {
992         return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,FALSE);
993 }
994
995 /***********************************************************************
996  *              _ICMessage                      [MSVIDEO.207]
997  */
998 LRESULT VFWAPIV ICMessage16(void) {
999         HIC16 hic;
1000         UINT16 msg;
1001         UINT16 cb;
1002         LPWORD lpData;
1003         SEGPTR segData;
1004         LRESULT ret;
1005         UINT16 i;
1006
1007         VA_LIST16 valist;
1008         
1009         VA_START16(valist);
1010         hic = VA_ARG16(valist, HIC16);
1011         msg = VA_ARG16(valist, UINT16);
1012         cb  = VA_ARG16(valist, UINT16);
1013
1014         lpData = HeapAlloc( GetProcessHeap(), 0, cb );
1015
1016         TRACE("0x%08lx, %u, %u, ...)\n",(DWORD)hic,msg,cb);
1017
1018         for(i=0;i<cb/sizeof(WORD);i++) {
1019                 lpData[i] = VA_ARG16(valist, WORD);
1020         }
1021                 
1022         VA_END16(valist);
1023         segData = MapLS( lpData );
1024         ret = ICSendMessage16(hic, msg, segData, (DWORD)cb);
1025         UnMapLS( segData );
1026         HeapFree( GetProcessHeap(), 0, lpData );
1027         return ret;
1028 }
1029
1030 /***********************************************************************
1031  *              ICDrawBegin             [MSVFW32.@]
1032  */
1033 DWORD VFWAPIV ICDrawBegin(
1034         HIC                hic,     /* [in] */
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] */
1050 {
1051         
1052         ICDRAWBEGIN     icdb;
1053
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);
1057
1058         icdb.dwFlags = dwFlags;
1059         icdb.hpal = hpal;
1060         icdb.hwnd = hwnd;
1061         icdb.hdc = hdc;
1062         icdb.xDst = xDst;
1063         icdb.yDst = yDst;
1064         icdb.dxDst = dxDst;
1065         icdb.dyDst = dyDst;
1066         icdb.lpbi = lpbi;
1067         icdb.xSrc = xSrc;
1068         icdb.ySrc = ySrc;
1069         icdb.dxSrc = dxSrc;
1070         icdb.dySrc = dySrc;
1071         icdb.dwRate = dwRate;
1072         icdb.dwScale = dwScale;
1073         return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
1074 }
1075
1076 /***********************************************************************
1077  *              _ICDrawBegin            [MSVIDEO.232]
1078  */
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] */
1096 {
1097         DWORD ret;
1098         ICDRAWBEGIN16 icdb;
1099         SEGPTR seg_icdb;
1100
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);
1104
1105         icdb.dwFlags = dwFlags;
1106         icdb.hpal = hpal;
1107         icdb.hwnd = hwnd;
1108         icdb.hdc = hdc;
1109         icdb.xDst = xDst;
1110         icdb.yDst = yDst;
1111         icdb.dxDst = dxDst;
1112         icdb.dyDst = dyDst;
1113         icdb.lpbi = lpbi; /* Keep this as SEGPTR for the mapping code to deal with */
1114         icdb.xSrc = xSrc;
1115         icdb.ySrc = ySrc;
1116         icdb.dxSrc = dxSrc;
1117         icdb.dySrc = dySrc;
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 );
1123         return ret;
1124 }
1125
1126 /***********************************************************************
1127  *              ICDraw                  [MSVFW32.@]
1128  */
1129 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
1130         ICDRAW  icd;
1131
1132         TRACE("(0x%09lx,%ld,%p,%p,%ld,%ld)\n",(DWORD)hic,dwFlags,lpFormat,lpData,cbData,lTime);
1133
1134         icd.dwFlags = dwFlags;
1135         icd.lpFormat = lpFormat;
1136         icd.lpData = lpData;
1137         icd.cbData = cbData;
1138         icd.lTime = lTime;
1139
1140         return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
1141 }
1142
1143 /***********************************************************************
1144  *              _ICDraw                 [MSVIDEO.234]
1145  */
1146 DWORD VFWAPIV ICDraw16(
1147         HIC16 hic,
1148         DWORD dwFlags,
1149         LPVOID lpFormat, /* [???] NOTE: SEGPTR */
1150         LPVOID lpData,   /* [???] NOTE: SEGPTR */
1151         DWORD cbData, 
1152         LONG lTime) 
1153 {
1154         DWORD ret;
1155         ICDRAW icd;
1156         SEGPTR seg_icd;
1157
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;
1163         icd.lTime = lTime;
1164         seg_icd = MapLS( &icd );
1165         ret = ICSendMessage16(hic,ICM_DRAW,seg_icd,sizeof(ICDRAW));
1166         UnMapLS( seg_icd );
1167         return ret;
1168 }
1169
1170 /***********************************************************************
1171  *              ICClose                 [MSVFW32.@]
1172  */
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);
1180         } else {
1181                 CloseDriver(whic->hdrv,0,0);
1182         }
1183
1184         GlobalUnlock16(hic);
1185         GlobalFree16(hic);
1186         return 0;
1187 }
1188
1189 /***********************************************************************
1190  *              ICClose                 [MSVIDEO.204]
1191  */
1192 LRESULT WINAPI ICClose16(HIC16 hic) {
1193         return ICClose(hic);
1194 }
1195
1196
1197
1198 /***********************************************************************
1199  *              ICImageCompress [MSVFW32.@]
1200  */
1201 HANDLE VFWAPI ICImageCompress(
1202         HIC hic, UINT uiFlags,
1203         LPBITMAPINFO lpbiIn, LPVOID lpBits,
1204         LPBITMAPINFO lpbiOut, LONG lQuality,
1205         LONG* plSize)
1206 {
1207         FIXME("(%08x,%08x,%p,%p,%p,%ld,%p)\n",
1208                 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
1209
1210         return (HANDLE)NULL;
1211 }
1212
1213 /***********************************************************************
1214  *              ICImageDecompress       [MSVFW32.@]
1215  */
1216
1217 HANDLE VFWAPI ICImageDecompress(
1218         HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
1219         LPVOID lpBits, LPBITMAPINFO lpbiOut)
1220 {
1221         HGLOBAL hMem = (HGLOBAL)NULL;
1222         BYTE*   pMem = NULL;
1223         BOOL    bReleaseIC = FALSE;
1224         BYTE*   pHdr = NULL;
1225         LONG    cbHdr = 0;
1226         BOOL    bSucceeded = FALSE;
1227         BOOL    bInDecompress = FALSE;
1228         DWORD   biSizeImage;
1229
1230         TRACE("(%08x,%08x,%p,%p,%p)\n",
1231                 hic, uiFlags, lpbiIn, lpBits, lpbiOut);
1232
1233         if ( hic == (HIC)NULL )
1234         {
1235                 hic = ICDecompressOpen( mmioFOURCC('V','I','D','C'), 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
1236                 if ( hic == (HIC)NULL )
1237                 {
1238                         WARN("no handler\n" );
1239                         goto err;
1240                 }
1241                 bReleaseIC = TRUE;
1242         }
1243         if ( uiFlags != 0 )
1244         {
1245                 FIXME( "unknown flag %08x\n", uiFlags );
1246                 goto err;
1247         }
1248         if ( lpbiIn == NULL || lpBits == NULL )
1249         {
1250                 WARN("invalid argument\n");
1251                 goto err;
1252         }
1253
1254         if ( lpbiOut != NULL )
1255         {
1256                 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
1257                         goto err;
1258                 cbHdr = sizeof(BITMAPINFOHEADER);
1259                 if ( lpbiOut->bmiHeader.biCompression == 3 )
1260                         cbHdr += sizeof(DWORD)*3;
1261                 else
1262                 if ( lpbiOut->bmiHeader.biBitCount <= 8 )
1263                 {
1264                         if ( lpbiOut->bmiHeader.biClrUsed == 0 )
1265                                 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
1266                         else
1267                                 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
1268                 }
1269         }
1270         else
1271         {
1272                 TRACE( "get format\n" );
1273
1274                 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
1275                 if ( cbHdr < sizeof(BITMAPINFOHEADER) )
1276                         goto err;
1277                 pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256);
1278                 if ( pHdr == NULL )
1279                         goto err;
1280                 ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 );
1281                 if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK )
1282                         goto err;
1283                 lpbiOut = (BITMAPINFO*)pHdr;
1284                 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1285                          ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
1286                          lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
1287                 {
1288                         if ( lpbiIn->bmiHeader.biClrUsed == 0 )
1289                                 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
1290                         else
1291                                 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
1292                 }
1293                 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1294                          lpbiOut->bmiHeader.biClrUsed == 0 )
1295                         lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
1296
1297                 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1298                 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
1299         }
1300
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);
1304
1305         TRACE( "call ICDecompressBegin\n" );
1306
1307         if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
1308                 goto err;
1309         bInDecompress = TRUE;
1310
1311         TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage );
1312
1313         hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
1314         if ( hMem == (HGLOBAL)NULL )
1315         {
1316                 WARN( "out of memory\n" );
1317                 goto err;
1318         }
1319         pMem = (BYTE*)GlobalLock( hMem );
1320         if ( pMem == NULL )
1321                 goto err;
1322         memcpy( pMem, lpbiOut, cbHdr );
1323
1324         TRACE( "call ICDecompress\n" );
1325         if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
1326                 goto err;
1327
1328         bSucceeded = TRUE;
1329 err:
1330         if ( bInDecompress )
1331                 ICDecompressEnd( hic );
1332         if ( bReleaseIC )
1333                 ICClose(hic);
1334         if ( pHdr != NULL )
1335                 HeapFree(GetProcessHeap(),0,pHdr);
1336         if ( pMem != NULL )
1337                 GlobalUnlock( hMem );
1338         if ( !bSucceeded && hMem != (HGLOBAL)NULL )
1339         {
1340                 GlobalFree(hMem); hMem = (HGLOBAL)NULL;
1341         }
1342
1343         return (HANDLE)hMem;
1344 }