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