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