winmm: dwBytesRecorded controls how much is played, not dwBufferLength.
[wine/hramrach.git] / dlls / msvideo.dll16 / msvideo16.c
blobe157808efffe5a0338eceeaf59b47374ddc051c7
1 /*
2 * msvideo 16-bit functions
4 * Copyright 1998 Marcus Meissner
5 * Copyright 2000 Bradley Baetz
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.
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.
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
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
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"
36 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
38 /* Drivers32 settings */
39 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
41 /* handle16 --> handle conversions */
42 #define HDRAWDIB_32(h16) ((HDRAWDIB)(ULONG_PTR)(h16))
43 #define HIC_32(h16) ((HIC)(ULONG_PTR)(h16))
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))
50 /***********************************************************************
51 * DrawDibOpen [MSVIDEO.102]
53 HDRAWDIB16 VFWAPI DrawDibOpen16(void)
55 return HDRAWDIB_16(DrawDibOpen());
58 /***********************************************************************
59 * DrawDibClose [MSVIDEO.103]
61 BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd)
63 return DrawDibClose(HDRAWDIB_32(hdd));
66 /************************************************************************
67 * DrawDibBegin [MSVIDEO.104]
69 BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd, HDC16 hdc, INT16 dxDst,
70 INT16 dyDst, LPBITMAPINFOHEADER lpbi, INT16 dxSrc,
71 INT16 dySrc, UINT16 wFlags)
73 return DrawDibBegin(HDRAWDIB_32(hdd), HDC_32(hdc), dxDst, dyDst, lpbi,
74 dxSrc, dySrc, wFlags);
77 /***********************************************************************
78 * DrawDibEnd [MSVIDEO.105]
80 BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd)
82 return DrawDibEnd(HDRAWDIB_32(hdd));
85 /**********************************************************************
86 * DrawDibDraw [MSVIDEO.106]
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)
93 return DrawDibDraw(HDRAWDIB_32(hdd), HDC_32(hdc), xDst, yDst, dxDst,
94 dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
97 /***********************************************************************
98 * DrawDibGetPalette [MSVIDEO.108]
100 HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd)
102 return HPALETTE_16(DrawDibGetPalette(HDRAWDIB_32(hdd)));
105 /***********************************************************************
106 * DrawDibSetPalette [MSVIDEO.110]
108 BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal)
110 return DrawDibSetPalette(HDRAWDIB_32(hdd), HPALETTE_32(hpal));
113 /***********************************************************************
114 * DrawDibRealize [MSVIDEO.112]
116 UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc,
117 BOOL16 fBackground)
119 return (UINT16)DrawDibRealize(HDRAWDIB_32(hdd), HDC_32(hdc), fBackground);
122 /*************************************************************************
123 * DrawDibStart [MSVIDEO.118]
125 BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate)
127 return DrawDibStart(HDRAWDIB_32(hdd), rate);
130 /*************************************************************************
131 * DrawDibStop [MSVIDEO.119]
133 BOOL16 VFWAPI DrawDibStop16(HDRAWDIB16 hdd)
135 return DrawDibStop(HDRAWDIB_32(hdd));
138 /***********************************************************************
139 * ICOpen [MSVIDEO.203]
141 HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode)
143 return HIC_16(ICOpen(fccType, fccHandler, wMode));
146 /***********************************************************************
147 * _ICMessage [MSVIDEO.207]
149 LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist )
151 LPWORD lpData;
152 SEGPTR segData;
153 LRESULT ret;
154 UINT16 i;
156 lpData = HeapAlloc(GetProcessHeap(), 0, cb);
158 TRACE("0x%08x, %u, %u, ...)\n", (DWORD) hic, msg, cb);
160 for (i = 0; i < cb / sizeof(WORD); i++)
162 lpData[i] = VA_ARG16(valist, WORD);
165 segData = MapLS(lpData);
166 ret = ICSendMessage16(hic, msg, segData, (DWORD) cb);
167 UnMapLS(segData);
168 HeapFree(GetProcessHeap(), 0, lpData);
169 return ret;
172 /***********************************************************************
173 * ICGetInfo [MSVIDEO.212]
175 LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 * picinfo, DWORD cb)
177 LRESULT ret;
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;
185 /***********************************************************************
186 * ICLocate [MSVIDEO.213]
188 HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler,
189 LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut,
190 WORD wFlags)
192 return HIC_16(ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags));
195 /***********************************************************************
196 * _ICCompress [MSVIDEO.224]
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)
206 DWORD ret;
207 ICCOMPRESS iccmp;
208 SEGPTR seg_iccmp;
210 TRACE("(0x%08x,%d,%p,%p,%p,%p,...)\n", (DWORD) hic, dwFlags,
211 lpbiOutput, lpData, lpbiInput, lpBits);
213 iccmp.dwFlags = dwFlags;
215 iccmp.lpbiOutput = lpbiOutput;
216 iccmp.lpOutput = lpData;
217 iccmp.lpbiInput = lpbiInput;
218 iccmp.lpInput = lpBits;
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;
233 /***********************************************************************
234 * _ICDecompress [MSVIDEO.230]
236 DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags,
237 LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData,
238 LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
240 ICDECOMPRESS icd;
241 SEGPTR segptr;
242 DWORD ret;
244 TRACE("(0x%08x,%d,%p,%p,%p,%p)\n", (DWORD) hic, dwFlags, lpbiFormat,
245 lpData, lpbi, lpBits);
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;
259 /***********************************************************************
260 * _ICDrawBegin [MSVIDEO.232]
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] */
279 DWORD ret;
280 ICDRAWBEGIN16 icdb;
281 SEGPTR seg_icdb;
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);
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;
310 /***********************************************************************
311 * _ICDraw [MSVIDEO.234]
313 DWORD VFWAPIV ICDraw16(HIC16 hic, DWORD dwFlags,
314 LPVOID lpFormat, /* [???] NOTE: SEGPTR */
315 LPVOID lpData, /* [???] NOTE: SEGPTR */
316 DWORD cbData, LONG lTime)
318 DWORD ret;
319 ICDRAW icd;
320 SEGPTR seg_icd;
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;
335 /***********************************************************************
336 * ICGetDisplayFormat [MSVIDEO.239]
338 HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn,
339 LPBITMAPINFOHEADER lpbiOut, INT16 depth,
340 INT16 dx, INT16 dy)
342 return HIC_16(ICGetDisplayFormat(HIC_32(hic), lpbiIn, lpbiOut, depth,
343 dx, dy));
346 #define COPY(x,y) (x->y = x##16->y);
347 #define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
349 /******************************************************************
350 * MSVIDEO_MapICDEX16To32
354 static LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam)
356 LPVOID ret;
358 ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESSEX));
359 ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam);
360 ret = icdx16;
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);
376 *lParam = (DWORD)(icdx);
377 return ret;
380 /******************************************************************
381 * MSVIDEO_MapMsg16To32
385 static LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2)
387 LPVOID ret = 0;
389 TRACE("Mapping %d\n", msg);
391 switch (msg)
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:
420 ICINFO *ici = HeapAlloc(GetProcessHeap(), 0, sizeof(ICINFO));
421 ICINFO16 *ici16;
423 ici16 = MapSL(*lParam1);
424 ret = ici16;
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);
438 break;
439 case ICM_COMPRESS:
441 ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS));
442 ICCOMPRESS *icc16;
444 icc16 = MapSL(*lParam1);
445 ret = icc16;
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);
460 *lParam1 = (DWORD)(icc);
461 *lParam2 = sizeof(ICCOMPRESS);
463 break;
464 case ICM_DECOMPRESS:
466 ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESS));
467 ICDECOMPRESS *icd16; /* Same structure except for the pointers */
469 icd16 = MapSL(*lParam1);
470 ret = icd16;
472 COPY(icd, dwFlags);
473 COPYPTR(icd, lpbiInput);
474 COPYPTR(icd, lpInput);
475 COPYPTR(icd, lpbiOutput);
476 COPYPTR(icd, lpOutput);
477 COPY(icd, ckid);
479 *lParam1 = (DWORD)(icd);
480 *lParam2 = sizeof(ICDECOMPRESS);
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?
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;
508 ret = addr;
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:
518 ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWBEGIN));
519 ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1);
520 ret = icdb16;
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);
538 *lParam1 = (DWORD)(icdb);
539 *lParam2 = sizeof(ICDRAWBEGIN);
541 break;
542 case ICM_DRAW_SUGGESTFORMAT:
544 ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWSUGGEST));
545 ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1);
547 ret = icds16;
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);
558 *lParam1 = (DWORD)(icds);
559 *lParam2 = sizeof(ICDRAWSUGGEST);
561 break;
562 case ICM_DRAW:
564 ICDRAW *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAW));
565 ICDRAW *icd16 = MapSL(*lParam1);
566 ret = icd16;
568 COPY(icd, dwFlags);
569 COPYPTR(icd, lpFormat);
570 COPYPTR(icd, lpData);
571 COPY(icd, cbData);
572 COPY(icd, lTime);
574 *lParam1 = (DWORD)(icd);
575 *lParam2 = sizeof(ICDRAW);
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);
584 return ret;
587 #undef COPY
588 #undef COPYPTR
590 /******************************************************************
591 * MSVIDEO_UnmapMsg16To32
595 static void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2)
597 TRACE("Unmapping %d\n", msg);
599 #define UNCOPY(x, y) (x##16->y = x->y);
601 switch (msg)
603 case ICM_GETINFO:
605 ICINFO *ici = (ICINFO*)(*lParam1);
606 ICINFO16 *ici16 = data16;
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);*/
622 HeapFree(GetProcessHeap(), 0, ici);
624 break;
625 case ICM_DECOMPRESS_QUERY:
627 LPVOID* x = data16;
628 HeapFree(GetProcessHeap(), 0, x[0]);
629 if (x[1])
630 HeapFree(GetProcessHeap(), 0, x[1]);
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);
646 #undef UNCOPY
649 /***********************************************************************
650 * ICInfo [MSVIDEO.200]
652 BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo)
654 BOOL16 ret;
655 LPVOID lpv;
656 DWORD lParam = (DWORD)lpicinfo;
657 DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;
659 /* Use the mapping functions to map the ICINFO structure */
660 lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO, &lParam, &size);
662 ret = ICInfo(fccType, fccHandler, (ICINFO*)lParam);
664 MSVIDEO_UnmapMsg16To32(ICM_GETINFO, lpv, &lParam, &size);
666 return ret;
669 /******************************************************************
670 * IC_Callback3216
674 static LRESULT CALLBACK IC_Callback3216(DWORD pfn16, HIC hic, HDRVR hdrv, UINT msg, LPARAM lp1, LPARAM lp2)
676 WORD args[8];
677 DWORD ret = 0;
679 switch (msg)
681 case DRV_OPEN:
682 lp2 = (DWORD)MapLS((void*)lp2);
683 break;
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 );
695 switch (msg)
697 case DRV_OPEN:
698 UnMapLS(lp2);
699 break;
701 return ret;
704 #define MAX_THUNKS 32
706 #include "pshpack1.h"
707 static struct msvideo_thunk
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"
719 static CRITICAL_SECTION msvideo_cs;
720 static CRITICAL_SECTION_DEBUG critsect_debug =
722 0, 0, &msvideo_cs,
723 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
724 0, 0, { (DWORD_PTR)(__FILE__ ": msvideo_cs") }
726 static CRITICAL_SECTION msvideo_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
728 static struct msvideo_thunk* MSVIDEO_AddThunk(DWORD pfn16)
730 struct msvideo_thunk* thunk;
732 if (!MSVIDEO_Thunks)
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++)
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;
748 for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
750 if (thunk->pfn16 == 0)
752 thunk->pfn16 = pfn16;
753 return thunk;
756 FIXME("Out of msvideo-thunks. Bump MAX_THUNKS\n");
757 return NULL;
760 static struct msvideo_thunk* MSVIDEO_HasThunk(HIC16 hic)
762 struct msvideo_thunk* thunk;
764 for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
766 if (thunk->hIC16 == hic) return thunk;
768 return NULL;
771 /***********************************************************************
772 * ICOpenFunction [MSVIDEO.206]
774 HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
776 HIC hic32;
777 struct msvideo_thunk* thunk;
779 EnterCriticalSection(&msvideo_cs);
780 if (!(thunk = MSVIDEO_AddThunk((DWORD)lpfnHandler)))
782 LeaveCriticalSection(&msvideo_cs);
783 return 0;
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);
793 /***********************************************************************
794 * ICSendMessage [MSVIDEO.205]
796 LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2)
798 LRESULT ret = ICERR_BADHANDLE;
799 struct msvideo_thunk* thunk;
801 if ((thunk = MSVIDEO_HasThunk(hic)))
803 WORD args[8];
804 DWORD result;
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;
819 else
821 /* map the message for a 32 bit infrastructure, and pass it along */
822 void* data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2);
824 ret = ICSendMessage(HIC_32(hic), msg, lParam1, lParam2);
825 if (data16)
826 MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2);
828 return ret;
831 /***********************************************************************
832 * ICClose [MSVIDEO.204]
834 LRESULT WINAPI ICClose16(HIC16 hic)
836 BOOL ret = ICClose(HIC_32(hic));
838 EnterCriticalSection(&msvideo_cs);
839 if (ret)
841 struct msvideo_thunk* thunk;
842 if ((thunk = MSVIDEO_HasThunk(hic)))
844 thunk->pfn16 = 0;
845 thunk->hIC16 = 0;
847 else ret = FALSE;
849 LeaveCriticalSection(&msvideo_cs);
850 return ret;
853 /***********************************************************************
854 * VideoCapDriverDescAndVer [MSVIDEO.22]
856 DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len,
857 LPSTR buf2, WORD buf2len)
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;
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)
876 RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
877 for (i = 0; i < cnt; i++)
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;
889 RegCloseKey( hKey );
892 /* search system.ini if not found in the registry */
893 if (!found && GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini"))
895 for (s = buf; *s; s += strlen(s) + 1)
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;
905 if (!found)
907 TRACE("No more VID* entries found nr=%d\n", nr);
908 return 20;
910 infosize = GetFileVersionInfoSizeA(fn, &verhandle);
911 if (!infosize)
913 TRACE("%s has no fileversioninfo.\n", fn);
914 return 18;
916 infobuf = HeapAlloc(GetProcessHeap(), 0, infosize);
917 if (GetFileVersionInfoA(fn, verhandle, infosize, infobuf))
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]
927 TRACE("version of %s is %s\n", fn, buf2);
929 else
931 TRACE("GetFileVersionInfoA failed for %s.\n", fn);
932 lstrcpynA(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/
934 /* FIXME: language problem? */
935 if (VerQueryValueA( infobuf,
936 version_info_spec,
937 &subblock,
938 &subblocklen
941 UINT copylen = min(subblocklen,buf1len-1);
942 memcpy(buf1, subblock, copylen);
943 buf1[copylen] = '\0';
944 TRACE("VQA returned %s\n", (LPCSTR)subblock);
946 else
948 TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
949 lstrcpynA(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/
951 HeapFree(GetProcessHeap(), 0, infobuf);
952 return 0;
955 /**************************************************************************
956 * DllEntryPoint (MSVIDEO.3)
958 * MSVIDEO DLL entry point
961 BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
962 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
964 switch (fdwReason)
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;
974 return TRUE;