Moved all Win16 definitions out of the standard Windows headers.
[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 "wingdi.h"
16 #include "winuser.h"
17 #include "vfw.h"
18 #include "vfw16.h"
19 #include "wine/winbase16.h"
20 #include "wine/winestring.h"
21 #include "debugtools.h"
22 #include "ldt.h"
23 #include "heap.h"
24 #include "stackframe.h"
25
26 DEFAULT_DEBUG_CHANNEL(msvideo);
27
28 /* ### start build ### */
29 extern LONG CALLBACK MSVIDEO_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
30 /* ### stop build ### */
31
32 LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2);
33 void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID lpv, LPDWORD lParam1, LPDWORD lParam2);
34 LRESULT MSVIDEO_SendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2, BOOL bFrom32);
35
36 /***********************************************************************
37  *              VideoForWindowsVersion          [MSVFW.2][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(WORD nr,LPVOID buf1,WORD buf1len,LPVOID buf2,WORD buf2len) {
49         FIXME("(%d,%p,%d,%p,%d), stub!\n",nr,buf1,buf1len,buf2,buf2len);
50         return 0;
51 }
52
53 /* system.ini: [drivers] */
54
55 /***********************************************************************
56  *              ICInfo                          [MSVFW.33]
57  * Get information about an installable compressor. Return TRUE if there
58  * is one.
59  */
60 BOOL VFWAPI ICInfo(
61         DWORD fccType,          /* [in] type of compressor ('vidc') */
62         DWORD fccHandler,       /* [in] <n>th compressor */
63                                    ICINFO *lpicinfo)    /* [out] information about compressor */
64 {
65         char    type[5],buf[2000];
66
67         memcpy(type,&fccType,4);type[4]=0;
68         TRACE("(%s,%ld,%p).\n",type,fccHandler,lpicinfo);
69         /* does OpenDriver/CloseDriver */
70         lpicinfo->dwSize = sizeof(ICINFO);
71         lpicinfo->fccType = fccType;
72         lpicinfo->dwFlags = 0;
73         if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,2000,"system.ini")) {
74                 char *s = buf;
75                 while (*s) {
76                         if (!strncasecmp(type,s,4)) {
77                                 if(!fccHandler--) {
78                                         lpicinfo->fccHandler = mmioStringToFOURCCA(s+5,0);
79                                         return TRUE;
80                                 }
81                         }
82                         s=s+strlen(s)+1; /* either next char or \0 */
83                 }
84         }
85         return FALSE;
86 }
87
88 BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16* /*SEGPTR*/ lpicinfo) {
89         BOOL16 ret;
90         LPVOID lpv;
91         DWORD lParam = (DWORD)lpicinfo;
92         DWORD size = ((ICINFO*)(PTR_SEG_TO_LIN(lpicinfo)))->dwSize;
93
94         /* Use the mapping functions to map the ICINFO structure */
95         lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO,&lParam,&size);
96
97         ret = ICInfo(fccType,fccHandler,(ICINFO*)lParam);
98
99         MSVIDEO_UnmapMsg16To32(ICM_GETINFO,lpv,&lParam,&size);
100         
101         return ret;
102 }
103
104 /***********************************************************************
105  *              ICOpen                          [MSVFW.37]
106  * Opens an installable compressor. Return special handle.
107  */
108 HIC VFWAPI ICOpen(DWORD fccType,DWORD fccHandler,UINT wMode) {
109         char            type[5],handler[5],codecname[20];
110         ICOPEN          icopen;
111         HDRVR           hdrv;
112         HIC16           hic;
113         WINE_HIC        *whic;
114
115         memcpy(type,&fccType,4);type[4]=0;
116         memcpy(handler,&fccHandler,4);handler[4]=0;
117         TRACE("(%s,%s,0x%08lx)\n",type,handler,(DWORD)wMode);
118
119         sprintf(codecname,"%s.%s",type,handler);
120
121         /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the 
122          * same layout as ICOPEN
123          */
124         icopen.fccType          = fccType;
125         icopen.fccHandler       = fccHandler;
126         icopen.dwSize           = sizeof(ICOPEN);
127         icopen.dwFlags          = wMode;
128         /* FIXME: do we need to fill out the rest too? */
129         hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
130         if (!hdrv) {
131             if (!strcasecmp(type,"vids")) {
132                 sprintf(codecname,"vidc.%s",handler);
133                 fccType = mmioFOURCC('v','i','d','c');
134             }
135             hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
136             if (!hdrv)
137                     return 0;
138         }
139         /* The handle should be a valid 16-bit handle as well */
140         hic = GlobalAlloc16(GHND,sizeof(WINE_HIC));
141         whic = (WINE_HIC*)GlobalLock16(hic);
142         whic->hdrv      = hdrv;
143         whic->driverproc= NULL;
144         whic->private   = 0;
145         GlobalUnlock16(hic);
146         TRACE("=> 0x%08lx\n",(DWORD)hic);
147         return hic;
148 }
149
150 HIC MSVIDEO_OpenFunc(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler, BOOL bFrom32) {
151         char    type[5],handler[5],codecname[20];
152         HIC16   hic;
153         ICOPEN*  icopen = SEGPTR_NEW(ICOPEN);
154         WINE_HIC        *whic;
155
156         memcpy(type,&fccType,4);type[4]=0;
157         memcpy(handler,&fccHandler,4);handler[4]=0;
158         TRACE("(%s,%s,%d,%p,%d)\n",type,handler,wMode,lpfnHandler,bFrom32?32:16);
159         
160         icopen->fccType         = fccType;
161         icopen->fccHandler      = fccHandler;
162         icopen->dwSize          = sizeof(ICOPEN);
163         icopen->dwFlags         = wMode;
164         
165         sprintf(codecname,"%s.%s",type,handler);
166
167         hic = GlobalAlloc16(GHND,sizeof(WINE_HIC));
168         if (!hic)
169                 return 0;
170         whic = GlobalLock16(hic);
171         whic->driverproc = lpfnHandler;
172         
173         whic->private = bFrom32;
174         
175         /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
176         /* What if the function is used more than once? */
177         
178         if (MSVIDEO_SendMessage(hic,DRV_LOAD,0L,0L,bFrom32) != DRV_SUCCESS) {
179                 WARN("DRV_LOAD failed for hic 0x%08lx\n",(DWORD)hic);
180                 GlobalFree16(hic);
181                 return 0;
182         }
183         if (MSVIDEO_SendMessage(hic,DRV_ENABLE,0L,0L,bFrom32) != DRV_SUCCESS) {
184                 WARN("DRV_ENABLE failed for hic 0x%08lx\n",(DWORD)hic);
185                 GlobalFree16(hic);
186                 return 0;
187         }
188         whic->hdrv = MSVIDEO_SendMessage(hic,DRV_OPEN,0,(LPARAM)(SEGPTR_GET(icopen)),FALSE);
189         if (whic->hdrv == 0) {
190                 WARN("DRV_OPEN failed for hic 0x%08lx\n",(DWORD)hic);
191                 GlobalFree16(hic);
192                 return 0;
193         }
194
195         GlobalUnlock16(hic);
196         TRACE("=> 0x%08lx\n",(DWORD)hic);
197         return hic;
198 }
199
200 /***********************************************************************
201  *              ICOpenFunction                  [MSVFW.38]
202  */
203 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) {
204         return MSVIDEO_OpenFunc(fccType,fccHandler,wMode,lpfnHandler,TRUE);
205 }
206
207 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode) {
208         return (HIC16)ICOpen(fccType, fccHandler, wMode);
209 }
210
211 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler) {
212         return MSVIDEO_OpenFunc(fccType, fccHandler, wMode, lpfnHandler,FALSE);
213 }
214
215 /***********************************************************************
216  *              ICGetInfo                       [MSVFW.30]
217  */
218 LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) {
219         LRESULT         ret;
220
221         TRACE("(0x%08lx,%p,%ld)\n",(DWORD)hic,picinfo,cb);
222         ret = ICSendMessage(hic,ICM_GETINFO,(DWORD)picinfo,cb);
223         TRACE(" -> 0x%08lx\n",ret);
224         return ret;
225 }
226
227 LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 *picinfo,DWORD cb) {
228         LRESULT         ret;
229
230         TRACE("(0x%08lx,%p,%ld)\n",(DWORD)hic,picinfo,cb);
231         ret = ICSendMessage16(hic,ICM_GETINFO,(DWORD)picinfo,cb);
232         TRACE(" -> 0x%08lx\n",ret);
233         return ret;
234 }
235
236 /***********************************************************************
237  *              ICLocate                        [MSVFW.35]
238  */
239 HIC VFWAPI ICLocate(
240         DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
241         LPBITMAPINFOHEADER lpbiOut, WORD wMode)
242 {
243         char    type[5],handler[5];
244         HIC     hic;
245         DWORD   querymsg;
246         LPSTR pszBuffer;
247
248         TRACE("(0x%08lx,0x%08lx,%p,%p,0x%04x)\n", fccType, fccHandler, lpbiIn, lpbiOut, wMode);
249
250         switch (wMode) {
251         case ICMODE_FASTCOMPRESS:
252         case ICMODE_COMPRESS: 
253                 querymsg = ICM_COMPRESS_QUERY;
254                 break;
255         case ICMODE_FASTDECOMPRESS:
256         case ICMODE_DECOMPRESS:
257                 querymsg = ICM_DECOMPRESS_QUERY;
258                 break;
259         case ICMODE_DRAW:
260                 querymsg = ICM_DRAW_QUERY;
261                 break;
262         default:
263                 WARN("Unknown mode (%d)\n",wMode);
264                 return 0;
265         }
266
267         /* Easy case: handler/type match, we just fire a query and return */
268         hic = ICOpen(fccType,fccHandler,wMode);
269         if (hic) {
270                 if (!ICSendMessage(hic,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
271                         return hic;
272                 ICClose(hic);
273         }
274
275         type[4]='.';memcpy(type,&fccType,4);
276         handler[4]='.';memcpy(handler,&fccHandler,4);
277
278         /* Now try each driver in turn. 32 bit codecs only. */
279         /* FIXME: Move this to an init routine? */
280         
281         pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(),0,1024);
282         if (GetPrivateProfileSectionA("drivers32",pszBuffer,1024,"system.ini")) {
283                 char* s = pszBuffer;
284                 while (*s) {
285                         if (!strncasecmp(type,s,5)) {
286                                 char *s2 = s;
287                                 while (*s2 != '\0' && *s2 != '.') s2++;
288                                 if (*s2) {
289                                         HIC h;
290
291                                         *s2++ = '\0';
292                                         h = ICOpen(fccType,*(DWORD*)s2,wMode);
293                                         if (h) {
294                                                 if (!ICSendMessage(h,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
295                                                         return h;
296                                                 ICClose(h);
297                                         }
298                                 }
299                         }
300                         s += strlen(s) + 1;
301                 }
302         }
303         HeapFree(GetProcessHeap(),0,pszBuffer);
304         
305         if (fccType==streamtypeVIDEO) {
306                 hic = ICLocate(ICTYPE_VIDEO,fccHandler,lpbiIn,lpbiOut,wMode);
307                 if (hic)
308                         return hic;
309         }
310
311         type[4] = handler[4] = '\0';
312         FIXME("(%.4s,%.4s,%p,%p,0x%04x),unhandled!\n",type,handler,lpbiIn,lpbiOut,wMode);
313         return 0;
314 }
315
316 HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
317                                                 LPBITMAPINFOHEADER lpbiOut, WORD wFlags) {
318         return (HIC16)ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags);
319 }
320
321 /***********************************************************************
322  *              ICGetDisplayFormat                      [MSVFW.29]
323  */
324 HIC VFWAPI ICGetDisplayFormat(
325         HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
326         INT depth,INT dx,INT dy)
327 {
328         HIC     tmphic = hic; 
329         LRESULT lres;
330
331         FIXME("(0x%08lx,%p,%p,%d,%d,%d),stub!\n",(DWORD)hic,lpbiIn,lpbiOut,depth,dx,dy);
332         if (!tmphic) {
333                 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
334                 if (!tmphic)
335                         return tmphic;
336         }
337         if ((dy == lpbiIn->biHeight) || (dx == lpbiIn->biWidth))
338                 dy = dx = 0; /* no resize needed */
339         /* Can we decompress it ? */
340         lres = ICDecompressQuery(tmphic,lpbiIn,NULL);
341         if (lres)
342                 goto errout; /* no, sorry */
343         ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
344         *lpbiOut=*lpbiIn;
345         lpbiOut->biCompression = 0;
346         lpbiOut->biSize = sizeof(*lpbiOut);
347         if (!depth) {
348                 HDC     hdc;
349
350                 hdc = GetDC(0);
351                 depth = GetDeviceCaps(hdc,12)*GetDeviceCaps(hdc,14);
352                 ReleaseDC(0,hdc);
353                 if (depth==15)  depth = 16;
354                 if (depth<8)    depth =  8;
355         }
356         if (lpbiIn->biBitCount == 8)
357                 depth = 8;
358         
359         TRACE("=> 0x%08lx\n",(DWORD)tmphic);
360         return tmphic;
361 errout:
362         if (hic!=tmphic)
363                 ICClose(tmphic);
364
365         TRACE("=> 0\n");
366         return 0;
367 }
368
369 HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn,
370                                                                   LPBITMAPINFOHEADER lpbiOut, INT16 depth, INT16 dx, INT16 dy) {
371         return (HIC16)ICGetDisplayFormat(hic,lpbiIn,lpbiOut,depth,dx,dy);
372 }
373
374 /***********************************************************************
375  *              ICCompress                      [MSVFW.23]
376  */
377 DWORD VFWAPIV
378 ICCompress(
379         HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
380         LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
381         LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
382         LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
383 {
384         ICCOMPRESS      iccmp;
385
386         TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
387
388         iccmp.dwFlags           = dwFlags;
389
390         iccmp.lpbiOutput        = lpbiOutput;
391         iccmp.lpOutput          = lpData;
392         iccmp.lpbiInput         = lpbiInput;
393         iccmp.lpInput           = lpBits;
394
395         iccmp.lpckid            = lpckid;
396         iccmp.lpdwFlags         = lpdwFlags;
397         iccmp.lFrameNum         = lFrameNum;
398         iccmp.dwFrameSize       = dwFrameSize;
399         iccmp.dwQuality         = dwQuality;
400         iccmp.lpbiPrev          = lpbiPrev;
401         iccmp.lpPrev            = lpPrev;
402         return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp));
403 }
404
405 DWORD VFWAPIV ICCompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData,
406                                                    LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits, LPDWORD lpckid,
407                                                    LPDWORD lpdwFlags, LONG lFrameNum, DWORD dwFrameSize, DWORD dwQuality,
408                                                    LPBITMAPINFOHEADER lpbiPrev, LPVOID lpPrev) {
409
410         DWORD ret;
411         ICCOMPRESS *iccmp = SEGPTR_NEW(ICCOMPRESS);
412
413         TRACE("(0x%08lx,%ld,%p,%p,%p,%p,...)\n",(DWORD)hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
414
415         iccmp->dwFlags          = dwFlags;
416
417         iccmp->lpbiOutput       = lpbiOutput;
418         iccmp->lpOutput         = lpData;
419         iccmp->lpbiInput                = lpbiInput;
420         iccmp->lpInput          = lpBits;
421
422         iccmp->lpckid           = lpckid;
423         iccmp->lpdwFlags                = lpdwFlags;
424         iccmp->lFrameNum                = lFrameNum;
425         iccmp->dwFrameSize      = dwFrameSize;
426         iccmp->dwQuality                = dwQuality;
427         iccmp->lpbiPrev         = lpbiPrev;
428         iccmp->lpPrev           = lpPrev;
429         ret = ICSendMessage16(hic,ICM_COMPRESS,(DWORD)SEGPTR_GET(iccmp),sizeof(ICCOMPRESS));
430         SEGPTR_FREE(iccmp);
431         return ret;
432 }
433
434 /***********************************************************************
435  *              ICDecompress                    [MSVFW.26]
436  */
437 DWORD VFWAPIV  ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
438                                 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
439 {
440         ICDECOMPRESS    icd;
441         DWORD ret;
442
443         TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
444
445         TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
446
447         icd.dwFlags     = dwFlags;
448         icd.lpbiInput   = lpbiFormat;
449         icd.lpInput     = lpData;
450
451         icd.lpbiOutput  = lpbi;
452         icd.lpOutput    = lpBits;
453         icd.ckid        = 0;
454         ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
455
456         TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
457
458         TRACE("-> %ld\n",ret);
459
460         return ret;
461 }
462
463 DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat,
464                                                          LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits) {
465
466         ICDECOMPRESS *icd = SEGPTR_NEW(ICDECOMPRESS);
467         DWORD ret;
468         
469         TRACE("(0x%08lx,%ld,%p,%p,%p,%p)\n",(DWORD)hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
470
471         icd->dwFlags = dwFlags;
472         icd->lpbiInput = lpbiFormat;
473         icd->lpInput = lpData;
474         icd->lpbiOutput = lpbi;
475         icd->lpOutput = lpBits;
476         icd->ckid = 0;
477
478         ret = ICSendMessage16(hic,ICM_DECOMPRESS,(DWORD)SEGPTR_GET(icd),sizeof(ICDECOMPRESS));
479
480         SEGPTR_FREE(icd);
481         return ret;
482 }
483
484 #define COPY(x,y) (##x##->##y = ##x##16->##y);
485 #define COPYPTR(x,y) (##x##->##y = PTR_SEG_TO_LIN(##x##16->##y));
486
487 LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam) {
488         LPVOID ret;
489
490         ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESSEX));
491         ICDECOMPRESSEX16 *icdx16 = (ICDECOMPRESSEX16*)PTR_SEG_TO_LIN(*lParam);
492         ret = icdx16;
493         
494         COPY(icdx,dwFlags);
495         COPYPTR(icdx,lpbiSrc);
496         COPYPTR(icdx,lpSrc);
497         COPYPTR(icdx,lpbiDst);
498         COPYPTR(icdx,lpDst);
499         COPY(icdx,xDst);
500         COPY(icdx,yDst);
501         COPY(icdx,dxDst);
502         COPY(icdx,dyDst);
503         COPY(icdx,xSrc);
504         COPY(icdx,ySrc);
505         COPY(icdx,dxSrc);
506         COPY(icdx,dySrc);
507         
508         *lParam = (DWORD)(icdx);
509         return ret;
510 }
511
512 LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2) {
513         LPVOID ret = 0;
514         
515         TRACE("Mapping %d\n",msg);
516
517         switch (msg) {
518         case DRV_LOAD:
519         case DRV_ENABLE:
520         case DRV_CLOSE:
521         case DRV_DISABLE:
522         case DRV_FREE:
523         case ICM_ABOUT:
524         case ICM_CONFIGURE:
525         case ICM_COMPRESS_END:
526         case ICM_DECOMPRESS_END:
527         case ICM_DECOMPRESSEX_END:
528         case ICM_SETQUALITY:
529                 break;
530         case DRV_OPEN:
531         case ICM_GETDEFAULTQUALITY:
532         case ICM_GETQUALITY:
533                 *lParam1 = (DWORD)PTR_SEG_TO_LIN(*lParam1);
534                 break;
535         case ICM_GETINFO:
536                 {
537                         ICINFO *ici = HeapAlloc(GetProcessHeap(),0,sizeof(ICINFO));
538                         ICINFO16 *ici16;
539
540                         ici16 = (ICINFO16*)PTR_SEG_TO_LIN(*lParam1);
541                         ret = ici16;
542
543                         ici->dwSize = sizeof(ICINFO);
544                         COPY(ici,fccType);
545                         COPY(ici,fccHandler);
546                         COPY(ici,dwFlags);
547                         COPY(ici,dwVersion);
548                         COPY(ici,dwVersionICM);
549                         lstrcpynAtoW(ici->szName,ici16->szName,16);
550                         lstrcpynAtoW(ici->szDescription,ici16->szDescription,128);
551                         lstrcpynAtoW(ici->szDriver,ici16->szDriver,128);
552
553                         *lParam1 = (DWORD)(ici);
554                         *lParam2 = sizeof(ICINFO);
555                 }
556                 break;
557         case ICM_COMPRESS:
558                 {
559                         ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(),0,sizeof(ICCOMPRESS));
560                         ICCOMPRESS *icc16;
561
562                         icc16 = (ICCOMPRESS*)PTR_SEG_TO_LIN(*lParam1);
563                         ret = icc16;
564
565                         COPY(icc,dwFlags);
566                         COPYPTR(icc,lpbiOutput);
567                         COPYPTR(icc,lpOutput);
568                         COPYPTR(icc,lpbiInput);
569                         COPYPTR(icc,lpInput);
570                         COPYPTR(icc,lpckid);
571                         COPYPTR(icc,lpdwFlags);
572                         COPY(icc,lFrameNum);
573                         COPY(icc,dwFrameSize);
574                         COPY(icc,dwQuality);
575                         COPYPTR(icc,lpbiPrev);
576                         COPYPTR(icc,lpPrev);
577                         
578                         *lParam1 = (DWORD)(icc);
579                         *lParam2 = sizeof(ICCOMPRESS);
580                 }
581                 break;
582         case ICM_DECOMPRESS:
583                 {
584                         ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDECOMPRESS));
585                         ICDECOMPRESS *icd16; /* Same structure except for the pointers */
586                         
587                         icd16 = (ICDECOMPRESS*)PTR_SEG_TO_LIN(*lParam1);
588                         ret = icd16;
589                         
590                         COPY(icd,dwFlags);
591                         COPYPTR(icd,lpbiInput);
592                         COPYPTR(icd,lpInput);
593                         COPYPTR(icd,lpbiOutput);
594                         COPYPTR(icd,lpOutput);
595                         COPY(icd,ckid);
596                         
597                         *lParam1 = (DWORD)(icd);
598                         *lParam2 = sizeof(ICDECOMPRESS);
599                 }
600                 break;
601         case ICM_COMPRESS_BEGIN:
602         case ICM_COMPRESS_GET_FORMAT:
603         case ICM_COMPRESS_GET_SIZE:
604         case ICM_COMPRESS_QUERY:
605         case ICM_DECOMPRESS_GET_FORMAT:
606         case ICM_DECOMPRESS_QUERY:
607         case ICM_DECOMPRESS_BEGIN:
608         case ICM_DECOMPRESS_SET_PALETTE:
609         case ICM_DECOMPRESS_GET_PALETTE:
610                 *lParam1 = (DWORD)PTR_SEG_TO_LIN(*lParam1);
611                 *lParam2 = (DWORD)PTR_SEG_TO_LIN(*lParam2);
612                 break;
613         case ICM_DECOMPRESSEX_QUERY:
614                 if ((*lParam2 != sizeof(ICDECOMPRESSEX16)) && (*lParam2 != 0))
615                         WARN("*lParam2 has unknown value %p\n",(ICDECOMPRESSEX16*)*lParam2);
616                 /* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16)
617                  * This is because of ICMessage(). Special case it?
618                  {
619                  LPVOID* addr = HeapAlloc(GetProcessHeap(),0,2*sizeof(LPVOID));
620                  addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
621                  if (*lParam2)
622                  addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
623                  else
624                  addr[1] = 0;
625                  
626                  ret = addr;
627                  }
628                  break;*/
629         case ICM_DECOMPRESSEX_BEGIN:
630         case ICM_DECOMPRESSEX:
631                 ret = MSVIDEO_MapICDEX16To32(lParam1);
632                 *lParam2 = sizeof(ICDECOMPRESSEX);
633                 break;
634         case ICM_DRAW_BEGIN:
635                 {
636                         ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWBEGIN));
637                         ICDRAWBEGIN16 *icdb16 = (ICDRAWBEGIN16*)PTR_SEG_TO_LIN(*lParam1);
638                         ret = icdb16;
639
640                         COPY(icdb,dwFlags);
641                         COPY(icdb,hpal);
642                         COPY(icdb,hwnd);
643                         COPY(icdb,hdc);
644                         COPY(icdb,xDst);
645                         COPY(icdb,yDst);
646                         COPY(icdb,dxDst);
647                         COPY(icdb,dyDst);
648                         COPYPTR(icdb,lpbi);
649                         COPY(icdb,xSrc);
650                         COPY(icdb,ySrc);
651                         COPY(icdb,dxSrc);
652                         COPY(icdb,dySrc);
653                         COPY(icdb,dwRate);
654                         COPY(icdb,dwScale);
655
656                         *lParam1 = (DWORD)(icdb);
657                         *lParam2 = sizeof(ICDRAWBEGIN);
658                 }
659                 break;
660         case ICM_DRAW_SUGGESTFORMAT:
661                 {
662                         ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAWSUGGEST));
663                         ICDRAWSUGGEST16 *icds16 = (ICDRAWSUGGEST16*)PTR_SEG_TO_LIN(*lParam1);
664                         
665                         ret = icds16;
666
667                         COPY(icds,dwFlags);
668                         COPYPTR(icds,lpbiIn);
669                         COPYPTR(icds,lpbiSuggest);
670                         COPY(icds,dxSrc);
671                         COPY(icds,dySrc);
672                         COPY(icds,dxDst);
673                         COPY(icds,dyDst);
674                         COPY(icds,hicDecompressor);
675
676                         *lParam1 = (DWORD)(icds);
677                         *lParam2 = sizeof(ICDRAWSUGGEST);
678                 }
679                 break;
680         case ICM_DRAW:
681                 {
682                         ICDRAW *icd = HeapAlloc(GetProcessHeap(),0,sizeof(ICDRAW));
683                         ICDRAW *icd16 = (ICDRAW*)PTR_SEG_TO_LIN(*lParam1);
684                         ret = icd16;
685
686                         COPY(icd,dwFlags);
687                         COPYPTR(icd,lpFormat);
688                         COPYPTR(icd,lpData);
689                         COPY(icd,cbData);
690                         COPY(icd,lTime);
691
692                         *lParam1 = (DWORD)(icd);
693                         *lParam2 = sizeof(ICDRAW);
694                 }
695                 break;
696         default:
697                 FIXME("%d is not yet handled. Expect a crash.\n",msg);
698         }
699         return ret;
700 }
701
702 #undef COPY
703 #undef COPYPTR
704
705 void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2) {
706         TRACE("Unmapping %d\n",msg);
707
708 #define UNCOPY(x,y) (##x##16->##y = ##x##->##y);
709
710         switch (msg) {
711         case ICM_GETINFO:
712                 {
713                         ICINFO *ici = (ICINFO*)(*lParam1);
714                         ICINFO16 *ici16 = (ICINFO16*)data16;
715
716                         UNCOPY(ici,fccType);
717                         UNCOPY(ici,fccHandler);
718                         UNCOPY(ici,dwFlags);
719                         UNCOPY(ici,dwVersion);
720                         UNCOPY(ici,dwVersionICM);
721                         lstrcpynWtoA(ici16->szName,ici->szName,16);
722                         lstrcpynWtoA(ici16->szDescription,ici->szDescription,128);
723                         /* This just gives garbage for some reason - BB
724                            lstrcpynWtoA(ici16->szDriver,ici->szDriver,128);*/
725
726                         HeapFree(GetProcessHeap(),0,ici);
727                 }
728                 break;
729         case ICM_DECOMPRESS_QUERY:
730                 /*{
731                   LPVOID* x = data16;
732                   HeapFree(GetProcessHeap(),0,x[0]);
733                   if (x[1])
734                   HeapFree(GetProcessHeap(),0,x[1]);
735                   }
736                   break;*/
737         case ICM_COMPRESS:
738         case ICM_DECOMPRESS:
739         case ICM_DECOMPRESSEX_QUERY:
740         case ICM_DECOMPRESSEX_BEGIN:
741         case ICM_DECOMPRESSEX:
742         case ICM_DRAW_BEGIN:
743         case ICM_DRAW_SUGGESTFORMAT:
744         case ICM_DRAW:
745                 HeapFree(GetProcessHeap(),0,data16);
746                 break;
747         default:
748                 ERR("Unmapping unmapped msg %d\n",msg);
749         }
750 #undef UNCOPY           
751 }
752
753 LRESULT MSVIDEO_SendMessage(HIC hic,UINT msg,DWORD lParam1,DWORD lParam2, BOOL bFrom32) {
754         LRESULT         ret;
755         WINE_HIC        *whic = GlobalLock16(hic);
756         LPVOID data16 = 0;
757         BOOL bDrv32;
758
759 #define XX(x) case x: TRACE("(0x%08lx,"#x",0x%08lx,0x%08lx,%d)\n",(DWORD)hic,lParam1,lParam2,bFrom32?32:16);break;
760
761         switch (msg) {
762                 /* DRV_* */
763                 XX(DRV_LOAD);
764                 XX(DRV_ENABLE);
765                 XX(DRV_OPEN);
766                 XX(DRV_CLOSE);
767                 XX(DRV_DISABLE);
768                 XX(DRV_FREE);
769                 /* ICM_RESERVED+X */
770                 XX(ICM_ABOUT);
771                 XX(ICM_CONFIGURE);
772                 XX(ICM_GET);
773                 XX(ICM_GETINFO);
774                 XX(ICM_GETDEFAULTQUALITY);
775                 XX(ICM_GETQUALITY);
776                 XX(ICM_GETSTATE);
777                 XX(ICM_SETQUALITY);
778                 XX(ICM_SET);
779                 XX(ICM_SETSTATE);
780                 /* ICM_USER+X */
781                 XX(ICM_COMPRESS_FRAMES_INFO);
782                 XX(ICM_COMPRESS_GET_FORMAT);
783                 XX(ICM_COMPRESS_GET_SIZE);
784                 XX(ICM_COMPRESS_QUERY);
785                 XX(ICM_COMPRESS_BEGIN);
786                 XX(ICM_COMPRESS);
787                 XX(ICM_COMPRESS_END);
788                 XX(ICM_DECOMPRESS_GET_FORMAT);
789                 XX(ICM_DECOMPRESS_QUERY);
790                 XX(ICM_DECOMPRESS_BEGIN);
791                 XX(ICM_DECOMPRESS);
792                 XX(ICM_DECOMPRESS_END);
793                 XX(ICM_DECOMPRESS_SET_PALETTE);
794                 XX(ICM_DECOMPRESS_GET_PALETTE);
795                 XX(ICM_DRAW_QUERY);
796                 XX(ICM_DRAW_BEGIN);
797                 XX(ICM_DRAW_GET_PALETTE);
798                 XX(ICM_DRAW_START);
799                 XX(ICM_DRAW_STOP);
800                 XX(ICM_DRAW_END);
801                 XX(ICM_DRAW_GETTIME);
802                 XX(ICM_DRAW);
803                 XX(ICM_DRAW_WINDOW);
804                 XX(ICM_DRAW_SETTIME);
805                 XX(ICM_DRAW_REALIZE);
806                 XX(ICM_DRAW_FLUSH);
807                 XX(ICM_DRAW_RENDERBUFFER);
808                 XX(ICM_DRAW_START_PLAY);
809                 XX(ICM_DRAW_STOP_PLAY);
810                 XX(ICM_DRAW_SUGGESTFORMAT);
811                 XX(ICM_DRAW_CHANGEPALETTE);
812                 XX(ICM_GETBUFFERSWANTED);
813                 XX(ICM_GETDEFAULTKEYFRAMERATE);
814                 XX(ICM_DECOMPRESSEX_BEGIN);
815                 XX(ICM_DECOMPRESSEX_QUERY);
816                 XX(ICM_DECOMPRESSEX);
817                 XX(ICM_DECOMPRESSEX_END);
818                 XX(ICM_SET_STATUS_PROC);
819         default:
820                 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,%i) unknown message\n",(DWORD)hic,(DWORD)msg,lParam1,lParam2,bFrom32?32:16);
821         }
822
823 #undef XX
824
825         if (whic->driverproc) { /* IC is a function */
826                 bDrv32 = whic->private;
827         } else {
828                 bDrv32 = ((GetDriverFlags(whic->hdrv) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) == WINE_GDF_EXIST);
829         }
830
831         if (!bFrom32) {
832                 if (bDrv32)
833                         data16 = MSVIDEO_MapMsg16To32(msg,&lParam1,&lParam2);
834         } else {
835                 if (!bDrv32) {
836                         ERR("Can't do 32->16 mappings\n");
837                         ret = -1;
838                         goto out;
839                 }
840         }
841         
842         if (whic->driverproc) {
843                 if (bDrv32) {
844                         ret = whic->driverproc(whic->hdrv,hic,msg,lParam1,lParam2);
845                 } else {
846                         ret = MSVIDEO_CallTo16_long_lwwll((FARPROC16)whic->driverproc,whic->hdrv,hic,msg,lParam1,lParam2);
847                 }
848         } else {
849                 ret = SendDriverMessage(whic->hdrv,msg,lParam1,lParam2);
850         }
851
852         if (data16)
853                 MSVIDEO_UnmapMsg16To32(msg,data16,&lParam1,&lParam2);
854  
855  out:
856         GlobalUnlock16(hic);
857         
858         TRACE(" -> 0x%08lx\n",ret);
859         return ret;
860 }
861
862 /***********************************************************************
863  *              ICSendMessage                   [MSVFW.40]
864  */
865 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2) {
866         return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,TRUE);
867 }
868
869 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) {
870         return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2,FALSE);
871 }
872
873 LRESULT VFWAPIV ICMessage16(void) {
874         HIC16 hic;
875         UINT16 msg;
876         UINT16 cb;
877         LPWORD lpData;
878         LRESULT ret;
879         UINT16 i;
880
881         VA_LIST16 valist;
882         
883         VA_START16(valist);
884         hic = VA_ARG16(valist, HIC16);
885         msg = VA_ARG16(valist, UINT16);
886         cb  = VA_ARG16(valist, UINT16);
887
888         lpData = SEGPTR_ALLOC(cb);
889
890         TRACE("0x%08lx, %u, %u, ...)\n",(DWORD)hic,msg,cb);
891
892         for(i=0;i<cb/sizeof(WORD);i++) {
893                 lpData[i] = VA_ARG16(valist, WORD);
894         }
895                 
896         VA_END16(valist);
897         ret = ICSendMessage16(hic, msg, (DWORD)(SEGPTR_GET(lpData)), (DWORD)cb);
898
899         SEGPTR_FREE(lpData);
900         return ret;
901 }
902
903 /***********************************************************************
904  *              ICDrawBegin             [MSVFW.28]
905  */
906 DWORD   VFWAPIV ICDrawBegin(
907         HIC                     hic,
908         DWORD                   dwFlags,/* flags */
909         HPALETTE                hpal,   /* palette to draw with */
910         HWND                    hwnd,   /* window to draw to */
911         HDC                     hdc,    /* HDC to draw to */
912         INT                     xDst,   /* destination rectangle */
913         INT                     yDst,
914         INT                     dxDst,
915         INT                     dyDst,
916         LPBITMAPINFOHEADER      lpbi,   /* format of frame to draw */
917         INT                     xSrc,   /* source rectangle */
918         INT                     ySrc,
919         INT                     dxSrc,
920         INT                     dySrc,
921         DWORD                   dwRate, /* frames/second = (dwRate/dwScale) */
922         DWORD                   dwScale) {
923         
924         ICDRAWBEGIN     icdb;
925
926         TRACE("(0x%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
927                   (DWORD)hic, dwFlags, (DWORD)hpal, (DWORD)hwnd, (DWORD)hdc, xDst, yDst, dxDst, dyDst,
928                   lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
929
930         icdb.dwFlags = dwFlags;
931         icdb.hpal = hpal;
932         icdb.hwnd = hwnd;
933         icdb.hdc = hdc;
934         icdb.xDst = xDst;
935         icdb.yDst = yDst;
936         icdb.dxDst = dxDst;
937         icdb.dyDst = dyDst;
938         icdb.lpbi = lpbi;
939         icdb.xSrc = xSrc;
940         icdb.ySrc = ySrc;
941         icdb.dxSrc = dxSrc;
942         icdb.dySrc = dySrc;
943         icdb.dwRate = dwRate;
944         icdb.dwScale = dwScale;
945         return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
946 }
947
948 DWORD VFWAPIV ICDrawBegin16(
949                                                         HIC16                   hic,
950                                                         DWORD                   dwFlags,/* flags */
951                                                         HPALETTE16              hpal,   /* palette to draw with */
952                                                         HWND16                  hwnd,   /* window to draw to */
953                                                         HDC16                   hdc,    /* HDC to draw to */
954                                                         INT16                   xDst,   /* destination rectangle */
955                                                         INT16                   yDst,
956                                                         INT16                   dxDst,
957                                                         INT16                   dyDst,
958                                                         LPBITMAPINFOHEADER /*SEGPTR*/ lpbi,     /* format of frame to draw */
959                                                         INT16                   xSrc,   /* source rectangle */
960                                                         INT16                   ySrc,
961                                                         INT16                   dxSrc,
962                                                         INT16                   dySrc,
963                                                         DWORD                   dwRate, /* frames/second = (dwRate/dwScale) */
964                                                         DWORD                   dwScale) {
965
966         DWORD ret;
967         ICDRAWBEGIN16* icdb = SEGPTR_NEW(ICDRAWBEGIN16); /* SEGPTR for mapper to deal with */
968
969         TRACE("(0x%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
970                   (DWORD)hic, dwFlags, (DWORD)hpal, (DWORD)hwnd, (DWORD)hdc, xDst, yDst, dxDst, dyDst,
971                   lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
972
973         icdb->dwFlags = dwFlags;
974         icdb->hpal = hpal;
975         icdb->hwnd = hwnd;
976         icdb->hdc = hdc;
977         icdb->xDst = xDst;
978         icdb->yDst = yDst;
979         icdb->dxDst = dxDst;
980         icdb->dyDst = dyDst;
981         icdb->lpbi = lpbi; /* Keep this as SEGPTR for the mapping code to deal with */
982         icdb->xSrc = xSrc;
983         icdb->ySrc = ySrc;
984         icdb->dxSrc = dxSrc;
985         icdb->dySrc = dySrc;
986         icdb->dwRate = dwRate;
987         icdb->dwScale = dwScale;
988         
989         ret = (DWORD)ICSendMessage16(hic,ICM_DRAW_BEGIN,(DWORD)SEGPTR_GET(icdb),sizeof(ICDRAWBEGIN16));
990         SEGPTR_FREE(icdb);
991         return ret;
992 }
993
994 /***********************************************************************
995  *              ICDraw                  [MSVFW.27]
996  */
997 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
998         ICDRAW  icd;
999
1000         TRACE("(0x%09lx,%ld,%p,%p,%ld,%ld)\n",(DWORD)hic,dwFlags,lpFormat,lpData,cbData,lTime);
1001
1002         icd.dwFlags = dwFlags;
1003         icd.lpFormat = lpFormat;
1004         icd.lpData = lpData;
1005         icd.cbData = cbData;
1006         icd.lTime = lTime;
1007
1008         return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
1009 }
1010
1011 DWORD VFWAPIV ICDraw16(HIC16 hic, DWORD dwFlags, LPVOID /*SEGPTR*/ lpFormat,
1012                                            LPVOID /*SEGPTR*/ lpData, DWORD cbData, LONG lTime) {
1013
1014         ICDRAW* icd = SEGPTR_NEW(ICDRAW); /* SEGPTR for mapper to deal with */
1015
1016         TRACE("(0x%08lx,0x%08lx,%p,%p,%ld,%ld)\n",(DWORD)hic,dwFlags,lpFormat,lpData,cbData,lTime);
1017         icd->dwFlags = dwFlags;
1018         icd->lpFormat = lpFormat;
1019         icd->lpData = lpData;
1020         icd->cbData = cbData;
1021         icd->lTime = lTime;
1022
1023         return ICSendMessage16(hic,ICM_DRAW,(DWORD)SEGPTR_GET(icd),sizeof(ICDRAW));
1024 }
1025
1026 /***********************************************************************
1027  *              ICClose                 [MSVFW.22]
1028  */
1029 LRESULT WINAPI ICClose(HIC hic) {
1030         WINE_HIC *whic = GlobalLock16(hic);
1031         TRACE("(0x%08lx)\n",(DWORD)hic);
1032         if (whic->driverproc) {
1033                 ICSendMessage16(hic,DRV_CLOSE,0,0);
1034                 ICSendMessage16(hic,DRV_DISABLE,0,0);
1035                 ICSendMessage16(hic,DRV_FREE,0,0);
1036         } else {
1037                 CloseDriver(whic->hdrv,0,0);
1038 }
1039
1040         GlobalUnlock16(hic);
1041         GlobalFree16(hic);
1042         return 0;
1043 }
1044
1045 LRESULT WINAPI ICClose16(HIC16 hic) {
1046         return ICClose(hic);
1047 }
1048
1049 /***********************************************************************
1050  *              MCIWndCreateA           [MSVFW.44 & MSVFW.45]
1051  */
1052 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
1053                       DWORD dwStyle,LPCSTR szFile)
1054 {
1055         FIXME("%x %x %lx %s\n",hwndParent, hInstance, dwStyle, szFile);
1056         return 0;
1057 }
1058
1059 /***********************************************************************
1060  *              MCIWndCreateW           [MSVFW.46]
1061  */
1062 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
1063                       DWORD dwStyle,LPCWSTR szFile)
1064 {
1065         FIXME("%x %x %lx %s\n",hwndParent, hInstance, dwStyle, debugstr_w(szFile));
1066         return 0;
1067 }