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