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