winedd: Move shader_*_add_instruction_modifiers into the shader backend.
[wine] / dlls / msvfw32 / 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 "msvideo_private.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 /***********************************************************************
42  *              DrawDibOpen             [MSVIDEO.102]
43  */
44 HDRAWDIB16 VFWAPI DrawDibOpen16(void)
45 {
46     return HDRAWDIB_16(DrawDibOpen());
47 }
48
49 /***********************************************************************
50  *              DrawDibClose            [MSVIDEO.103]
51  */
52 BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd)
53 {
54     return DrawDibClose(HDRAWDIB_32(hdd));
55 }
56
57 /************************************************************************
58  *              DrawDibBegin            [MSVIDEO.104]
59  */
60 BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd, HDC16 hdc, INT16 dxDst,
61                              INT16 dyDst, LPBITMAPINFOHEADER lpbi, INT16 dxSrc,
62                              INT16 dySrc, UINT16 wFlags)
63 {
64     return DrawDibBegin(HDRAWDIB_32(hdd), HDC_32(hdc), dxDst, dyDst, lpbi,
65                         dxSrc, dySrc, wFlags);
66 }
67
68 /***********************************************************************
69  *              DrawDibEnd              [MSVIDEO.105]
70  */
71 BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd)
72 {
73     return DrawDibEnd(HDRAWDIB_32(hdd));
74 }
75
76 /**********************************************************************
77  *              DrawDibDraw             [MSVIDEO.106]
78  */
79 BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd, HDC16 hdc, INT16 xDst, INT16 yDst,
80                             INT16 dxDst, INT16 dyDst, LPBITMAPINFOHEADER lpbi,
81                             LPVOID lpBits, INT16 xSrc, INT16 ySrc, INT16 dxSrc,
82                             INT16 dySrc, UINT16 wFlags)
83 {
84     return DrawDibDraw(HDRAWDIB_32(hdd), HDC_32(hdc), xDst, yDst, dxDst,
85                        dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
86 }
87
88 /***********************************************************************
89  *              DrawDibGetPalette       [MSVIDEO.108]
90  */
91 HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd)
92 {
93     return HPALETTE_16(DrawDibGetPalette(HDRAWDIB_32(hdd)));
94 }
95
96 /***********************************************************************
97  *              DrawDibSetPalette       [MSVIDEO.110]
98  */
99 BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal)
100 {
101     return DrawDibSetPalette(HDRAWDIB_32(hdd), HPALETTE_32(hpal));
102 }
103
104 /***********************************************************************
105  *              DrawDibRealize          [MSVIDEO.112]
106  */
107 UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc,
108                                BOOL16 fBackground)
109 {
110     return (UINT16)DrawDibRealize(HDRAWDIB_32(hdd), HDC_32(hdc), fBackground);
111 }
112
113 /*************************************************************************
114  *              DrawDibStart            [MSVIDEO.118]
115  */
116 BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate)
117 {
118     return DrawDibStart(HDRAWDIB_32(hdd), rate);
119 }
120
121 /*************************************************************************
122  *              DrawDibStop             [MSVIDEO.119]
123  */
124 BOOL16 VFWAPI DrawDibStop16(HDRAWDIB16 hdd)
125 {
126     return DrawDibStop(HDRAWDIB_32(hdd));
127 }
128
129 /***********************************************************************
130  *              ICOpen                          [MSVIDEO.203]
131  */
132 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode)
133 {
134     return HIC_16(ICOpen(fccType, fccHandler, wMode));
135 }
136
137 /***********************************************************************
138  *              ICClose                 [MSVIDEO.204]
139  */
140 LRESULT WINAPI ICClose16(HIC16 hic)
141 {
142     return ICClose(HIC_32(hic));
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(HIC hic, HDRVR hdrv, UINT msg, DWORD lp1, DWORD lp2)
674 {
675     WINE_HIC*   whic;
676     WORD args[8];
677
678     whic = MSVIDEO_GetHicPtr(hic);
679     if (whic)
680     {
681         DWORD ret = 0;
682         switch (msg)
683         {
684         case DRV_OPEN:
685             lp2 = (DWORD)MapLS((void*)lp2);
686             break;
687         }
688         args[7] = HIWORD(hic);
689         args[6] = LOWORD(hic);
690         args[5] = HDRVR_16(whic->hdrv);
691         args[4] = msg;
692         args[3] = HIWORD(lp1);
693         args[2] = LOWORD(lp1);
694         args[1] = HIWORD(lp2);
695         args[0] = LOWORD(lp2);
696         WOWCallback16Ex( whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &ret );
697
698         switch (msg)
699         {
700         case DRV_OPEN:
701             UnMapLS(lp2);
702             break;
703         }
704         return ret;
705     }
706     else return ICERR_BADHANDLE;
707 }
708
709 /***********************************************************************
710  *              ICOpenFunction                  [MSVIDEO.206]
711  */
712 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
713 {
714     HIC         hic32;
715
716     hic32 = MSVIDEO_OpenFunction(fccType, fccHandler, wMode, 
717                                  (DRIVERPROC)IC_Callback3216, (DWORD)lpfnHandler);
718     return HIC_16(hic32);
719 }
720
721 /***********************************************************************
722  *              ICSendMessage                   [MSVIDEO.205]
723  */
724 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) 
725 {
726     LRESULT     ret = ICERR_BADHANDLE;
727     WINE_HIC*   whic;
728
729     whic = MSVIDEO_GetHicPtr(HIC_32(hic));
730     if (whic)
731     {
732         /* we've got a 16 bit driver proc... call it directly */
733         if (whic->driverproc16)
734         {
735             WORD args[8];
736             DWORD result;
737
738             /* FIXME: original code was passing hdrv first and hic second */
739             /* but this doesn't match what IC_Callback3216 does */
740             args[7] = HIWORD(hic);
741             args[6] = LOWORD(hic);
742             args[5] = HDRVR_16(whic->hdrv);
743             args[4] = msg;
744             args[3] = HIWORD(lParam1);
745             args[2] = LOWORD(lParam1);
746             args[1] = HIWORD(lParam2);
747             args[0] = LOWORD(lParam2);
748             WOWCallback16Ex( whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &result );
749             ret = result;
750         }
751         else
752         {
753             /* map the message for a 32 bit infrastructure, and pass it along */
754             void*       data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2);
755     
756             ret = MSVIDEO_SendMessage(whic, msg, lParam1, lParam2);
757             if (data16)
758                 MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2);
759         }
760     }
761     return ret;
762 }
763
764 /***********************************************************************
765  *              VideoCapDriverDescAndVer        [MSVIDEO.22]
766  */
767 DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len,
768                                         LPSTR buf2, WORD buf2len)
769 {
770     static const char version_info_spec[] = "\\StringFileInfo\\040904E4\\FileDescription";
771     DWORD       verhandle;
772     DWORD       infosize;
773     UINT        subblocklen;
774     char        *s, buf[2048], fn[260];
775     LPBYTE      infobuf;
776     LPVOID      subblock;
777     DWORD       i, cnt = 0, lRet;
778     DWORD       bufLen, fnLen;
779     FILETIME    lastWrite;
780     HKEY        hKey;
781     BOOL        found = FALSE;
782
783     TRACE("(%d,%p,%d,%p,%d)\n", nr, buf1, buf1len, buf2, buf2len);
784     lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey);
785     if (lRet == ERROR_SUCCESS) 
786     {
787         RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
788         for (i = 0; i < cnt; i++) 
789         {
790             bufLen = sizeof(buf) / sizeof(buf[0]);
791             lRet = RegEnumKeyExA(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite);
792             if (lRet != ERROR_SUCCESS) continue;
793             if (strncasecmp(buf, "vid", 3)) continue;
794             if (nr--) continue;
795             fnLen = sizeof(fn);
796             lRet = RegQueryValueExA(hKey, buf, 0, 0, (LPBYTE)fn, &fnLen);
797             if (lRet == ERROR_SUCCESS) found = TRUE;
798             break;
799         }
800         RegCloseKey( hKey );
801     } 
802
803     /* search system.ini if not found in the registry */
804     if (!found && GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini"))
805     {
806         for (s = buf; *s; s += strlen(s) + 1)
807         {
808             if (strncasecmp(s, "vid", 3)) continue;
809             if (nr--) continue;
810             if (GetPrivateProfileStringA("drivers32", s, NULL, fn, sizeof(fn), "system.ini"))
811                 found = TRUE;
812             break;
813         }
814     }
815
816     if (!found)
817     {
818         TRACE("No more VID* entries found nr=%d\n", nr);
819         return 20;
820     }
821     infosize = GetFileVersionInfoSizeA(fn, &verhandle);
822     if (!infosize) 
823     {
824         TRACE("%s has no fileversioninfo.\n", fn);
825         return 18;
826     }
827     infobuf = HeapAlloc(GetProcessHeap(), 0, infosize);
828     if (GetFileVersionInfoA(fn, verhandle, infosize, infobuf)) 
829     {
830         /* Yes, two space behind : */
831         /* FIXME: test for buflen */
832         snprintf(buf2, buf2len, "Version:  %d.%d.%d.%d\n",
833                 ((WORD*)infobuf)[0x0f],
834                 ((WORD*)infobuf)[0x0e],
835                 ((WORD*)infobuf)[0x11],
836                 ((WORD*)infobuf)[0x10]
837             );
838         TRACE("version of %s is %s\n", fn, buf2);
839     }
840     else 
841     {
842         TRACE("GetFileVersionInfoA failed for %s.\n", fn);
843         lstrcpynA(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/
844     }
845     /* FIXME: language problem? */
846     if (VerQueryValueA( infobuf,
847                         version_info_spec,
848                         &subblock,
849                         &subblocklen
850             )) 
851     {
852         UINT copylen = min(subblocklen,buf1len-1);
853         memcpy(buf1, subblock, copylen);
854         buf1[copylen] = '\0';
855         TRACE("VQA returned %s\n", (LPCSTR)subblock);
856     }
857     else 
858     {
859         TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
860         lstrcpynA(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/
861     }
862     HeapFree(GetProcessHeap(), 0, infobuf);
863     return 0;
864 }
865
866 /******************************************************************
867  *              IC_CallTo16
868  *
869  *
870  */
871 static  LRESULT CALLBACK IC_CallTo16(HDRVR hdrv, HIC hic, UINT msg, LPARAM lp1, LPARAM lp2)
872 {
873 #if 0
874     WINE_HIC*   whic = IC_GetPtr(hic);
875     LRESULT     ret = 0;
876     
877     
878     if (whic->driverproc) 
879     {
880         ret = whic->driverproc(hic, whic->hdrv, msg, lParam1, lParam2);
881     }
882     else
883     {
884         ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
885     }
886 #else
887     FIXME("No 32=>16 conversion yet\n");
888 #endif
889     return 0;
890 }
891
892 /**************************************************************************
893  *                      DllEntryPoint (MSVIDEO.3)
894  *
895  * MSVIDEO DLL entry point
896  *
897  */
898 BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
899                           WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
900 {
901     switch (fdwReason) 
902     {
903     case DLL_PROCESS_ATTACH:
904         /* hook in our 16 bit management functions */
905         pFnCallTo16 = IC_CallTo16;
906         break;
907     case DLL_PROCESS_DETACH:
908         /* remove our 16 bit management functions */
909         pFnCallTo16 = NULL;
910         break;
911     case DLL_THREAD_ATTACH:
912     case DLL_THREAD_DETACH:
913         break;
914     }
915     return TRUE;
916 }