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