winex11: Sync the window attributes when switching a window to embedded.
[wine] / dlls / msvideo.dll16 / msvideo16.c
1 /*
2  * msvideo 16-bit functions
3  *
4  * Copyright 1998 Marcus Meissner
5  * Copyright 2000 Bradley Baetz
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winver.h"
29 #include "winnls.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "wine/winbase16.h"
33 #include "wownt32.h"
34 #include "vfw16.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
38
39 /* Drivers32 settings */
40 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
41
42 /* handle16 --> handle conversions */
43 #define HDRAWDIB_32(h16)        ((HDRAWDIB)(ULONG_PTR)(h16))
44 #define HIC_32(h16)             ((HIC)(ULONG_PTR)(h16))
45
46 /* handle --> handle16 conversions */
47 #define HDRVR_16(h32)           (LOWORD(h32))
48 #define HDRAWDIB_16(h32)        (LOWORD(h32))
49 #define HIC_16(h32)             (LOWORD(h32))
50
51 /***********************************************************************
52  *              DrawDibOpen             [MSVIDEO.102]
53  */
54 HDRAWDIB16 VFWAPI DrawDibOpen16(void)
55 {
56     return HDRAWDIB_16(DrawDibOpen());
57 }
58
59 /***********************************************************************
60  *              DrawDibClose            [MSVIDEO.103]
61  */
62 BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd)
63 {
64     return DrawDibClose(HDRAWDIB_32(hdd));
65 }
66
67 /************************************************************************
68  *              DrawDibBegin            [MSVIDEO.104]
69  */
70 BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd, HDC16 hdc, INT16 dxDst,
71                              INT16 dyDst, LPBITMAPINFOHEADER lpbi, INT16 dxSrc,
72                              INT16 dySrc, UINT16 wFlags)
73 {
74     return DrawDibBegin(HDRAWDIB_32(hdd), HDC_32(hdc), dxDst, dyDst, lpbi,
75                         dxSrc, dySrc, wFlags);
76 }
77
78 /***********************************************************************
79  *              DrawDibEnd              [MSVIDEO.105]
80  */
81 BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd)
82 {
83     return DrawDibEnd(HDRAWDIB_32(hdd));
84 }
85
86 /**********************************************************************
87  *              DrawDibDraw             [MSVIDEO.106]
88  */
89 BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd, HDC16 hdc, INT16 xDst, INT16 yDst,
90                             INT16 dxDst, INT16 dyDst, LPBITMAPINFOHEADER lpbi,
91                             LPVOID lpBits, INT16 xSrc, INT16 ySrc, INT16 dxSrc,
92                             INT16 dySrc, UINT16 wFlags)
93 {
94     return DrawDibDraw(HDRAWDIB_32(hdd), HDC_32(hdc), xDst, yDst, dxDst,
95                        dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
96 }
97
98 /***********************************************************************
99  *              DrawDibGetPalette       [MSVIDEO.108]
100  */
101 HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd)
102 {
103     return HPALETTE_16(DrawDibGetPalette(HDRAWDIB_32(hdd)));
104 }
105
106 /***********************************************************************
107  *              DrawDibSetPalette       [MSVIDEO.110]
108  */
109 BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal)
110 {
111     return DrawDibSetPalette(HDRAWDIB_32(hdd), HPALETTE_32(hpal));
112 }
113
114 /***********************************************************************
115  *              DrawDibRealize          [MSVIDEO.112]
116  */
117 UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc,
118                                BOOL16 fBackground)
119 {
120     return (UINT16)DrawDibRealize(HDRAWDIB_32(hdd), HDC_32(hdc), fBackground);
121 }
122
123 /*************************************************************************
124  *              DrawDibStart            [MSVIDEO.118]
125  */
126 BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate)
127 {
128     return DrawDibStart(HDRAWDIB_32(hdd), rate);
129 }
130
131 /*************************************************************************
132  *              DrawDibStop             [MSVIDEO.119]
133  */
134 BOOL16 VFWAPI DrawDibStop16(HDRAWDIB16 hdd)
135 {
136     return DrawDibStop(HDRAWDIB_32(hdd));
137 }
138
139 /***********************************************************************
140  *              ICOpen                          [MSVIDEO.203]
141  */
142 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode)
143 {
144     return HIC_16(ICOpen(fccType, fccHandler, wMode));
145 }
146
147 /***********************************************************************
148  *              _ICMessage                      [MSVIDEO.207]
149  */
150 LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist )
151 {
152     LPWORD lpData;
153     SEGPTR segData;
154     LRESULT ret;
155     UINT16 i;
156
157     lpData = HeapAlloc(GetProcessHeap(), 0, cb);
158
159     TRACE("0x%08x, %u, %u, ...)\n", (DWORD) hic, msg, cb);
160
161     for (i = 0; i < cb / sizeof(WORD); i++)
162     {
163         lpData[i] = VA_ARG16(valist, WORD);
164     }
165
166     segData = MapLS(lpData);
167     ret = ICSendMessage16(hic, msg, segData, (DWORD) cb);
168     UnMapLS(segData);
169     HeapFree(GetProcessHeap(), 0, lpData);
170     return ret;
171 }
172
173 /***********************************************************************
174  *              ICGetInfo                       [MSVIDEO.212]
175  */
176 LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 * picinfo, DWORD cb)
177 {
178     LRESULT ret;
179
180     TRACE("(0x%08x,%p,%d)\n", (DWORD) hic, picinfo, cb);
181     ret = ICSendMessage16(hic, ICM_GETINFO, (DWORD) picinfo, cb);
182     TRACE("     -> 0x%08lx\n", ret);
183     return ret;
184 }
185
186 /***********************************************************************
187  *              ICLocate                        [MSVIDEO.213]
188  */
189 HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler,
190                         LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut,
191                         WORD wFlags)
192 {
193     return HIC_16(ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags));
194 }
195
196 /***********************************************************************
197  *              _ICCompress                     [MSVIDEO.224]
198  */
199 DWORD VFWAPIV ICCompress16(HIC16 hic, DWORD dwFlags,
200                            LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData,
201                            LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits,
202                            LPDWORD lpckid, LPDWORD lpdwFlags,
203                            LONG lFrameNum, DWORD dwFrameSize,
204                            DWORD dwQuality, LPBITMAPINFOHEADER lpbiPrev,
205                            LPVOID lpPrev)
206 {
207     DWORD ret;
208     ICCOMPRESS iccmp;
209     SEGPTR seg_iccmp;
210
211     TRACE("(0x%08x,%d,%p,%p,%p,%p,...)\n", (DWORD) hic, dwFlags,
212           lpbiOutput, lpData, lpbiInput, lpBits);
213
214     iccmp.dwFlags = dwFlags;
215
216     iccmp.lpbiOutput = lpbiOutput;
217     iccmp.lpOutput = lpData;
218     iccmp.lpbiInput = lpbiInput;
219     iccmp.lpInput = lpBits;
220
221     iccmp.lpckid = lpckid;
222     iccmp.lpdwFlags = lpdwFlags;
223     iccmp.lFrameNum = lFrameNum;
224     iccmp.dwFrameSize = dwFrameSize;
225     iccmp.dwQuality = dwQuality;
226     iccmp.lpbiPrev = lpbiPrev;
227     iccmp.lpPrev = lpPrev;
228     seg_iccmp = MapLS(&iccmp);
229     ret = ICSendMessage16(hic, ICM_COMPRESS, seg_iccmp, sizeof(ICCOMPRESS));
230     UnMapLS(seg_iccmp);
231     return ret;
232 }
233
234 /***********************************************************************
235  *              _ICDecompress                   [MSVIDEO.230]
236  */
237 DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags,
238                              LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData,
239                              LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
240 {
241     ICDECOMPRESS icd;
242     SEGPTR segptr;
243     DWORD ret;
244
245     TRACE("(0x%08x,%d,%p,%p,%p,%p)\n", (DWORD) hic, dwFlags, lpbiFormat,
246           lpData, lpbi, lpBits);
247
248     icd.dwFlags = dwFlags;
249     icd.lpbiInput = lpbiFormat;
250     icd.lpInput = lpData;
251     icd.lpbiOutput = lpbi;
252     icd.lpOutput = lpBits;
253     icd.ckid = 0;
254     segptr = MapLS(&icd);
255     ret = ICSendMessage16(hic, ICM_DECOMPRESS, segptr, sizeof(ICDECOMPRESS));
256     UnMapLS(segptr);
257     return ret;
258 }
259
260 /***********************************************************************
261  *              _ICDrawBegin            [MSVIDEO.232]
262  */
263 DWORD VFWAPIV ICDrawBegin16(HIC16 hic,          /* [in] */
264                             DWORD dwFlags,      /* [in] flags */
265                             HPALETTE16 hpal,    /* [in] palette to draw with */
266                             HWND16 hwnd,        /* [in] window to draw to */
267                             HDC16 hdc,          /* [in] HDC to draw to */
268                             INT16 xDst,         /* [in] destination rectangle */
269                             INT16 yDst,         /* [in] */
270                             INT16 dxDst,        /* [in] */
271                             INT16 dyDst,        /* [in] */
272                             LPBITMAPINFOHEADER lpbi,    /* [in] format of frame to draw NOTE: SEGPTR */
273                             INT16 xSrc,         /* [in] source rectangle */
274                             INT16 ySrc,         /* [in] */
275                             INT16 dxSrc,        /* [in] */
276                             INT16 dySrc,        /* [in] */
277                             DWORD dwRate,       /* [in] frames/second = (dwRate/dwScale) */
278                             DWORD dwScale)      /* [in] */
279 {
280     DWORD ret;
281     ICDRAWBEGIN16 icdb;
282     SEGPTR seg_icdb;
283
284     TRACE ("(0x%08x,%d,0x%08x,0x%08x,0x%08x,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n",
285            (DWORD) hic, dwFlags, (DWORD) hpal, (DWORD) hwnd, (DWORD) hdc,
286            xDst, yDst, dxDst, dyDst, lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate,
287            dwScale);
288
289     icdb.dwFlags = dwFlags;
290     icdb.hpal = hpal;
291     icdb.hwnd = hwnd;
292     icdb.hdc = hdc;
293     icdb.xDst = xDst;
294     icdb.yDst = yDst;
295     icdb.dxDst = dxDst;
296     icdb.dyDst = dyDst;
297     icdb.lpbi = lpbi;           /* Keep this as SEGPTR for the mapping code to deal with */
298     icdb.xSrc = xSrc;
299     icdb.ySrc = ySrc;
300     icdb.dxSrc = dxSrc;
301     icdb.dySrc = dySrc;
302     icdb.dwRate = dwRate;
303     icdb.dwScale = dwScale;
304     seg_icdb = MapLS(&icdb);
305     ret = (DWORD) ICSendMessage16(hic, ICM_DRAW_BEGIN, seg_icdb,
306                                   sizeof(ICDRAWBEGIN16));
307     UnMapLS(seg_icdb);
308     return ret;
309 }
310
311 /***********************************************************************
312  *              _ICDraw                 [MSVIDEO.234]
313  */
314 DWORD VFWAPIV ICDraw16(HIC16 hic, DWORD dwFlags,
315                        LPVOID lpFormat, /* [???] NOTE: SEGPTR */
316                        LPVOID lpData,   /* [???] NOTE: SEGPTR */
317                        DWORD cbData, LONG lTime)
318 {
319     DWORD ret;
320     ICDRAW icd;
321     SEGPTR seg_icd;
322
323     TRACE("(0x%08x,0x%08x,%p,%p,%d,%d)\n", (DWORD) hic, dwFlags,
324           lpFormat, lpData, cbData, lTime);
325     icd.dwFlags = dwFlags;
326     icd.lpFormat = lpFormat;
327     icd.lpData = lpData;
328     icd.cbData = cbData;
329     icd.lTime = lTime;
330     seg_icd = MapLS(&icd);
331     ret = ICSendMessage16(hic, ICM_DRAW, seg_icd, sizeof(ICDRAW));
332     UnMapLS(seg_icd);
333     return ret;
334 }
335
336 /***********************************************************************
337  *              ICGetDisplayFormat                      [MSVIDEO.239]
338  */
339 HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn,
340                                   LPBITMAPINFOHEADER lpbiOut, INT16 depth,
341                                   INT16 dx, INT16 dy)
342 {
343     return HIC_16(ICGetDisplayFormat(HIC_32(hic), lpbiIn, lpbiOut, depth,
344                                      dx, dy));
345 }
346
347 #define COPY(x,y) (x->y = x##16->y);
348 #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
349
350 /******************************************************************
351  *              MSVIDEO_MapICDEX16To32
352  *
353  *
354  */
355 static LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam)
356 {
357     LPVOID ret;
358
359     ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESSEX));
360     ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam);
361     ret = icdx16;
362
363     COPY(icdx, dwFlags);
364     COPYPTR(icdx, lpbiSrc);
365     COPYPTR(icdx, lpSrc);
366     COPYPTR(icdx, lpbiDst);
367     COPYPTR(icdx, lpDst);
368     COPY(icdx, xDst);
369     COPY(icdx, yDst);
370     COPY(icdx, dxDst);
371     COPY(icdx, dyDst);
372     COPY(icdx, xSrc);
373     COPY(icdx, ySrc);
374     COPY(icdx, dxSrc);
375     COPY(icdx, dySrc);
376
377     *lParam = (DWORD)(icdx);
378     return ret;
379 }
380
381 /******************************************************************
382  *              MSVIDEO_MapMsg16To32
383  *
384  *
385  */
386 static LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2)
387 {
388     LPVOID ret = 0;
389
390     TRACE("Mapping %d\n", msg);
391
392     switch (msg)
393     {
394     case DRV_LOAD:
395     case DRV_ENABLE:
396     case DRV_CLOSE:
397     case DRV_DISABLE:
398     case DRV_FREE:
399     case ICM_ABOUT:
400     case ICM_CONFIGURE:
401     case ICM_COMPRESS_END:
402     case ICM_DECOMPRESS_END:
403     case ICM_DECOMPRESSEX_END:
404     case ICM_SETQUALITY:
405     case ICM_DRAW_START_PLAY:
406     case ICM_DRAW_STOP_PLAY:
407     case ICM_DRAW_REALIZE:
408     case ICM_DRAW_RENDERBUFFER:
409     case ICM_DRAW_END:
410         break;
411     case DRV_OPEN:
412     case ICM_GETDEFAULTQUALITY:
413     case ICM_GETQUALITY:
414     case ICM_SETSTATE:
415     case ICM_DRAW_WINDOW:
416     case ICM_GETBUFFERSWANTED:
417         *lParam1 = (DWORD)MapSL(*lParam1);
418         break;
419     case ICM_GETINFO:
420         {
421             ICINFO *ici = HeapAlloc(GetProcessHeap(), 0, sizeof(ICINFO));
422             ICINFO16 *ici16;
423
424             ici16 = MapSL(*lParam1);
425             ret = ici16;
426
427             ici->dwSize = sizeof(ICINFO);
428             COPY(ici, fccType);
429             COPY(ici, fccHandler);
430             COPY(ici, dwFlags);
431             COPY(ici, dwVersion);
432             COPY(ici, dwVersionICM);
433             MultiByteToWideChar( CP_ACP, 0, ici16->szName, -1, ici->szName, 16 );
434             MultiByteToWideChar( CP_ACP, 0, ici16->szDescription, -1, ici->szDescription, 128 );
435             MultiByteToWideChar( CP_ACP, 0, ici16->szDriver, -1, ici->szDriver, 128 );
436             *lParam1 = (DWORD)(ici);
437             *lParam2 = sizeof(ICINFO);
438         }
439         break;
440     case ICM_COMPRESS:
441         {
442             ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS));
443             ICCOMPRESS *icc16;
444
445             icc16 = MapSL(*lParam1);
446             ret = icc16;
447
448             COPY(icc, dwFlags);
449             COPYPTR(icc, lpbiOutput);
450             COPYPTR(icc, lpOutput);
451             COPYPTR(icc, lpbiInput);
452             COPYPTR(icc, lpInput);
453             COPYPTR(icc, lpckid);
454             COPYPTR(icc, lpdwFlags);
455             COPY(icc, lFrameNum);
456             COPY(icc, dwFrameSize);
457             COPY(icc, dwQuality);
458             COPYPTR(icc, lpbiPrev);
459             COPYPTR(icc, lpPrev);
460
461             *lParam1 = (DWORD)(icc);
462             *lParam2 = sizeof(ICCOMPRESS);
463         }
464         break;
465     case ICM_DECOMPRESS:
466         {
467             ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESS));
468             ICDECOMPRESS *icd16; /* Same structure except for the pointers */
469
470             icd16 = MapSL(*lParam1);
471             ret = icd16;
472
473             COPY(icd, dwFlags);
474             COPYPTR(icd, lpbiInput);
475             COPYPTR(icd, lpInput);
476             COPYPTR(icd, lpbiOutput);
477             COPYPTR(icd, lpOutput);
478             COPY(icd, ckid);
479
480             *lParam1 = (DWORD)(icd);
481             *lParam2 = sizeof(ICDECOMPRESS);
482         }
483         break;
484     case ICM_COMPRESS_BEGIN:
485     case ICM_COMPRESS_GET_FORMAT:
486     case ICM_COMPRESS_GET_SIZE:
487     case ICM_COMPRESS_QUERY:
488     case ICM_DECOMPRESS_GET_FORMAT:
489     case ICM_DECOMPRESS_QUERY:
490     case ICM_DECOMPRESS_BEGIN:
491     case ICM_DECOMPRESS_SET_PALETTE:
492     case ICM_DECOMPRESS_GET_PALETTE:
493         *lParam1 = (DWORD)MapSL(*lParam1);
494         *lParam2 = (DWORD)MapSL(*lParam2);
495         break;
496     case ICM_DECOMPRESSEX_QUERY:
497         if ((*lParam2 != sizeof(ICDECOMPRESSEX16)) && (*lParam2 != 0))
498             WARN("*lParam2 has unknown value %p\n", (ICDECOMPRESSEX16*)*lParam2);
499         /* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16)
500          * This is because of ICMessage(). Special case it?
501          {
502          LPVOID* addr = HeapAlloc(GetProcessHeap(), 0, 2*sizeof(LPVOID));
503          addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
504          if (*lParam2)
505          addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
506          else
507          addr[1] = 0;
508
509          ret = addr;
510          }
511          break;*/
512     case ICM_DECOMPRESSEX_BEGIN:
513     case ICM_DECOMPRESSEX:
514         ret = MSVIDEO_MapICDEX16To32(lParam1);
515         *lParam2 = sizeof(ICDECOMPRESSEX);
516         break;
517     case ICM_DRAW_BEGIN:
518         {
519             ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWBEGIN));
520             ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1);
521             ret = icdb16;
522
523             COPY(icdb, dwFlags);
524             icdb->hpal = HPALETTE_32(icdb16->hpal);
525             icdb->hwnd = HWND_32(icdb16->hwnd);
526             icdb->hdc = HDC_32(icdb16->hdc);
527             COPY(icdb, xDst);
528             COPY(icdb, yDst);
529             COPY(icdb, dxDst);
530             COPY(icdb, dyDst);
531             COPYPTR(icdb, lpbi);
532             COPY(icdb, xSrc);
533             COPY(icdb, ySrc);
534             COPY(icdb, dxSrc);
535             COPY(icdb, dySrc);
536             COPY(icdb, dwRate);
537             COPY(icdb, dwScale);
538
539             *lParam1 = (DWORD)(icdb);
540             *lParam2 = sizeof(ICDRAWBEGIN);
541         }
542         break;
543     case ICM_DRAW_SUGGESTFORMAT:
544         {
545             ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWSUGGEST));
546             ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1);
547
548             ret = icds16;
549
550             COPY(icds, dwFlags);
551             COPYPTR(icds, lpbiIn);
552             COPYPTR(icds, lpbiSuggest);
553             COPY(icds, dxSrc);
554             COPY(icds, dySrc);
555             COPY(icds, dxDst);
556             COPY(icds, dyDst);
557             icds->hicDecompressor = HIC_32(icds16->hicDecompressor);
558
559             *lParam1 = (DWORD)(icds);
560             *lParam2 = sizeof(ICDRAWSUGGEST);
561         }
562         break;
563     case ICM_DRAW:
564         {
565             ICDRAW *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAW));
566             ICDRAW *icd16 = MapSL(*lParam1);
567             ret = icd16;
568
569             COPY(icd, dwFlags);
570             COPYPTR(icd, lpFormat);
571             COPYPTR(icd, lpData);
572             COPY(icd, cbData);
573             COPY(icd, lTime);
574
575             *lParam1 = (DWORD)(icd);
576             *lParam2 = sizeof(ICDRAW);
577         }
578         break;
579     case ICM_DRAW_START:
580     case ICM_DRAW_STOP:
581         break;
582     default:
583         FIXME("%d is not yet handled. Expect a crash.\n", msg);
584     }
585     return ret;
586 }
587
588 #undef COPY
589 #undef COPYPTR
590
591 /******************************************************************
592  *              MSVIDEO_UnmapMsg16To32
593  *
594  *
595  */
596 static void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2)
597 {
598     TRACE("Unmapping %d\n", msg);
599
600 #define UNCOPY(x, y) (x##16->y = x->y);
601
602     switch (msg)
603     {
604     case ICM_GETINFO:
605         {
606             ICINFO *ici = (ICINFO*)(*lParam1);
607             ICINFO16 *ici16 = data16;
608
609             UNCOPY(ici, fccType);
610             UNCOPY(ici, fccHandler);
611             UNCOPY(ici, dwFlags);
612             UNCOPY(ici, dwVersion);
613             UNCOPY(ici, dwVersionICM);
614             WideCharToMultiByte( CP_ACP, 0, ici->szName, -1, ici16->szName,
615                                  sizeof(ici16->szName), NULL, NULL );
616             ici16->szName[sizeof(ici16->szName)-1] = 0;
617             WideCharToMultiByte( CP_ACP, 0, ici->szDescription, -1, ici16->szDescription,
618                                  sizeof(ici16->szDescription), NULL, NULL );
619             ici16->szDescription[sizeof(ici16->szDescription)-1] = 0;
620             /* This just gives garbage for some reason - BB
621                lstrcpynWtoA(ici16->szDriver, ici->szDriver, 128);*/
622
623             HeapFree(GetProcessHeap(), 0, ici);
624         }
625         break;
626     case ICM_DECOMPRESS_QUERY:
627         /*{
628           LPVOID* x = data16;
629           HeapFree(GetProcessHeap(), 0, x[0]);
630           if (x[1])
631           HeapFree(GetProcessHeap(), 0, x[1]);
632           }
633           break;*/
634     case ICM_COMPRESS:
635     case ICM_DECOMPRESS:
636     case ICM_DECOMPRESSEX_QUERY:
637     case ICM_DECOMPRESSEX_BEGIN:
638     case ICM_DECOMPRESSEX:
639     case ICM_DRAW_BEGIN:
640     case ICM_DRAW_SUGGESTFORMAT:
641     case ICM_DRAW:
642         HeapFree(GetProcessHeap(), 0, data16);
643         break;
644     default:
645         ERR("Unmapping unmapped msg %d\n", msg);
646     }
647 #undef UNCOPY
648 }
649
650 /***********************************************************************
651  *              ICInfo                          [MSVIDEO.200]
652  */
653 BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo)
654 {
655     BOOL16 ret;
656     LPVOID lpv;
657     DWORD lParam = (DWORD)lpicinfo;
658     DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;
659
660     /* Use the mapping functions to map the ICINFO structure */
661     lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO, &lParam, &size);
662
663     ret = ICInfo(fccType, fccHandler, (ICINFO*)lParam);
664
665     MSVIDEO_UnmapMsg16To32(ICM_GETINFO, lpv, &lParam, &size);
666
667     return ret;
668 }
669
670 /******************************************************************
671  *              IC_Callback3216
672  *
673  *
674  */
675 static  LRESULT CALLBACK  IC_Callback3216(DWORD pfn16, HIC hic, HDRVR hdrv, UINT msg, LPARAM lp1, LPARAM lp2)
676 {
677     WORD args[8];
678     DWORD ret = 0;
679
680     switch (msg)
681     {
682     case DRV_OPEN:
683         lp2 = (DWORD)MapLS((void*)lp2);
684         break;
685     }
686     args[7] = HIWORD(hic);
687     args[6] = LOWORD(hic);
688     args[5] = HDRVR_16(hdrv);
689     args[4] = msg;
690     args[3] = HIWORD(lp1);
691     args[2] = LOWORD(lp1);
692     args[1] = HIWORD(lp2);
693     args[0] = LOWORD(lp2);
694     WOWCallback16Ex( pfn16, WCB16_PASCAL, sizeof(args), args, &ret );
695
696     switch (msg)
697     {
698     case DRV_OPEN:
699         UnMapLS(lp2);
700         break;
701     }
702     return ret;
703 }
704
705 #define MAX_THUNKS      32
706
707 #include "pshpack1.h"
708 static struct msvideo_thunk
709 {
710     BYTE        popl_eax;        /* popl  %eax (return address) */
711     BYTE        pushl_func;      /* pushl $pfn16 (16bit callback function) */
712     DWORD       pfn16;
713     BYTE        pushl_eax;       /* pushl %eax */
714     BYTE        jmp;             /* ljmp WDML_InvokeCallback16 */
715     DWORD       callback;
716     HIC16       hIC16;           /* driver's handle */
717 } *MSVIDEO_Thunks;
718 #include "poppack.h"
719
720 static CRITICAL_SECTION msvideo_cs;
721 static CRITICAL_SECTION_DEBUG critsect_debug =
722 {
723     0, 0, &msvideo_cs,
724     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
725       0, 0, { (DWORD_PTR)(__FILE__ ": msvideo_cs") }
726 };
727 static CRITICAL_SECTION msvideo_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
728
729 static struct msvideo_thunk*      MSVIDEO_AddThunk(DWORD pfn16)
730 {
731     struct msvideo_thunk* thunk;
732
733     if (!MSVIDEO_Thunks)
734     {
735         MSVIDEO_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*MSVIDEO_Thunks), MEM_COMMIT,
736                                       PAGE_EXECUTE_READWRITE);
737         if (!MSVIDEO_Thunks) return NULL;
738         for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
739         {
740             thunk->popl_eax     = 0x58;   /* popl  %eax */
741             thunk->pushl_func   = 0x68;   /* pushl $pfn16 */
742             thunk->pfn16        = 0;
743             thunk->pushl_eax    = 0x50;   /* pushl %eax */
744             thunk->jmp          = 0xe9;   /* jmp IC_Callback3216 */
745             thunk->callback     = (char *)IC_Callback3216 - (char *)(&thunk->callback + 1);
746             thunk->hIC16        = 0;
747         }
748     }
749     for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
750     {
751         if (thunk->pfn16 == 0)
752         {
753             thunk->pfn16 = pfn16;
754             return thunk;
755         }
756     }
757     FIXME("Out of msvideo-thunks. Bump MAX_THUNKS\n");
758     return NULL;
759 }
760
761 static struct msvideo_thunk*    MSVIDEO_HasThunk(HIC16 hic)
762 {
763     struct msvideo_thunk* thunk;
764
765     for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
766     {
767         if (thunk->hIC16 == hic) return thunk;
768     }
769     return NULL;
770 }
771
772 /***********************************************************************
773  *              ICOpenFunction                  [MSVIDEO.206]
774  */
775 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
776 {
777     HIC         hic32;
778     struct msvideo_thunk*       thunk;
779
780     EnterCriticalSection(&msvideo_cs);
781     if (!(thunk = MSVIDEO_AddThunk((DWORD)lpfnHandler)))
782     {
783         LeaveCriticalSection(&msvideo_cs);
784         return 0;
785     }
786     if ((hic32 = ICOpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)thunk)))
787         thunk->hIC16 = HIC_16(hic32);
788     else
789         thunk->pfn16 = 0;
790     LeaveCriticalSection(&msvideo_cs);
791     return HIC_16(hic32);
792 }
793
794 /***********************************************************************
795  *              ICSendMessage                   [MSVIDEO.205]
796  */
797 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2)
798 {
799     LRESULT     ret = ICERR_BADHANDLE;
800     struct msvideo_thunk* thunk;
801
802     if ((thunk = MSVIDEO_HasThunk(hic)))
803     {
804         WORD args[8];
805         DWORD result;
806
807         /* FIXME: original code was passing hdrv first and hic second */
808         /* but this doesn't match what IC_Callback3216 does */
809         args[7] = HIWORD(hic);
810         args[6] = LOWORD(hic);
811         args[5] = 0; /* the 32bit also sets it to NULL */
812         args[4] = msg;
813         args[3] = HIWORD(lParam1);
814         args[2] = LOWORD(lParam1);
815         args[1] = HIWORD(lParam2);
816         args[0] = LOWORD(lParam2);
817         WOWCallback16Ex( thunk->pfn16, WCB16_PASCAL, sizeof(args), args, &result );
818         ret = result;
819     }
820     else
821     {
822         /* map the message for a 32 bit infrastructure, and pass it along */
823         void*       data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2);
824
825         ret = ICSendMessage(HIC_32(hic), msg, lParam1, lParam2);
826         if (data16)
827             MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2);
828     }
829     return ret;
830 }
831
832 /***********************************************************************
833  *              ICClose                 [MSVIDEO.204]
834  */
835 LRESULT WINAPI ICClose16(HIC16 hic)
836 {
837     BOOL ret = ICClose(HIC_32(hic));
838
839     EnterCriticalSection(&msvideo_cs);
840     if (ret)
841     {
842         struct msvideo_thunk* thunk;
843         if ((thunk = MSVIDEO_HasThunk(hic)))
844         {
845             thunk->pfn16 = 0;
846             thunk->hIC16 = 0;
847         }
848         else ret = FALSE;
849     }
850     LeaveCriticalSection(&msvideo_cs);
851     return ret;
852 }
853
854 /***********************************************************************
855  *              VideoCapDriverDescAndVer        [MSVIDEO.22]
856  */
857 DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len,
858                                         LPSTR buf2, WORD buf2len)
859 {
860     static const char version_info_spec[] = "\\StringFileInfo\\040904E4\\FileDescription";
861     DWORD       verhandle;
862     DWORD       infosize;
863     UINT        subblocklen;
864     char        *s, buf[2048], fn[260];
865     LPBYTE      infobuf;
866     LPVOID      subblock;
867     DWORD       i, cnt = 0, lRet;
868     DWORD       bufLen, fnLen;
869     FILETIME    lastWrite;
870     HKEY        hKey;
871     BOOL        found = FALSE;
872
873     TRACE("(%d,%p,%d,%p,%d)\n", nr, buf1, buf1len, buf2, buf2len);
874     lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey);
875     if (lRet == ERROR_SUCCESS)
876     {
877         RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
878         for (i = 0; i < cnt; i++)
879         {
880             bufLen = sizeof(buf) / sizeof(buf[0]);
881             lRet = RegEnumKeyExA(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite);
882             if (lRet != ERROR_SUCCESS) continue;
883             if (strncasecmp(buf, "vid", 3)) continue;
884             if (nr--) continue;
885             fnLen = sizeof(fn);
886             lRet = RegQueryValueExA(hKey, buf, 0, 0, (LPBYTE)fn, &fnLen);
887             if (lRet == ERROR_SUCCESS) found = TRUE;
888             break;
889         }
890         RegCloseKey( hKey );
891     }
892
893     /* search system.ini if not found in the registry */
894     if (!found && GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini"))
895     {
896         for (s = buf; *s; s += strlen(s) + 1)
897         {
898             if (strncasecmp(s, "vid", 3)) continue;
899             if (nr--) continue;
900             if (GetPrivateProfileStringA("drivers32", s, NULL, fn, sizeof(fn), "system.ini"))
901                 found = TRUE;
902             break;
903         }
904     }
905
906     if (!found)
907     {
908         TRACE("No more VID* entries found nr=%d\n", nr);
909         return 20;
910     }
911     infosize = GetFileVersionInfoSizeA(fn, &verhandle);
912     if (!infosize)
913     {
914         TRACE("%s has no fileversioninfo.\n", fn);
915         return 18;
916     }
917     infobuf = HeapAlloc(GetProcessHeap(), 0, infosize);
918     if (GetFileVersionInfoA(fn, verhandle, infosize, infobuf))
919     {
920         /* Yes, two space behind : */
921         /* FIXME: test for buflen */
922         snprintf(buf2, buf2len, "Version:  %d.%d.%d.%d\n",
923                 ((WORD*)infobuf)[0x0f],
924                 ((WORD*)infobuf)[0x0e],
925                 ((WORD*)infobuf)[0x11],
926                 ((WORD*)infobuf)[0x10]
927             );
928         TRACE("version of %s is %s\n", fn, buf2);
929     }
930     else
931     {
932         TRACE("GetFileVersionInfoA failed for %s.\n", fn);
933         lstrcpynA(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/
934     }
935     /* FIXME: language problem? */
936     if (VerQueryValueA( infobuf,
937                         version_info_spec,
938                         &subblock,
939                         &subblocklen
940             ))
941     {
942         UINT copylen = min(subblocklen,buf1len-1);
943         memcpy(buf1, subblock, copylen);
944         buf1[copylen] = '\0';
945         TRACE("VQA returned %s\n", (LPCSTR)subblock);
946     }
947     else
948     {
949         TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
950         lstrcpynA(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/
951     }
952     HeapFree(GetProcessHeap(), 0, infobuf);
953     return 0;
954 }
955
956 /**************************************************************************
957  *                      DllEntryPoint (MSVIDEO.3)
958  *
959  * MSVIDEO DLL entry point
960  *
961  */
962 BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
963                           WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
964 {
965     switch (fdwReason)
966     {
967     case DLL_PROCESS_ATTACH:
968         break;
969     case DLL_PROCESS_DETACH:
970         break;
971     case DLL_THREAD_ATTACH:
972     case DLL_THREAD_DETACH:
973         break;
974     }
975     return TRUE;
976 }
977
978 /***********************************************************************
979  *                      MCIWndCreate(MSVIDEO.250)
980  */
981 HWND16 CDECL MCIWndCreate16(HWND16 hwnd, HINSTANCE16 hinst16,
982                               DWORD style, LPSTR file)
983 {
984     return HWND_16(MCIWndCreateA(HWND_32(hwnd), 0, style, file));
985 }