Fixed position of tmp.f assigned like in dlls/d3d8/shader.c.
[wine/wine64.git] / dlls / msvideo / msvideo_main.c
blob35eac439b55cb57cdcc8edfc463657cd933e4443
1 /*
2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
4 * Copyright 2003 Michael Günnewig
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * FIXME: This all assumes 32 bit codecs
21 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
22 * There is the ICOpenFunction16 to worry about still, though.
24 * TODO
25 * - no thread safety
28 #include <stdio.h>
29 #include <string.h>
31 #include "msvideo_private.h"
32 #include "winnls.h"
33 #include "wingdi.h"
34 #include "winuser.h"
36 #include "windowsx.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
42 static inline const char *wine_dbgstr_fcc( DWORD fcc )
44 return wine_dbg_sprintf("%c%c%c%c",
45 LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)),
46 LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc)));
49 LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM) = NULL;
51 static WINE_HIC* MSVIDEO_FirstHic /* = NULL */;
53 typedef struct _reg_driver reg_driver;
54 struct _reg_driver
56 DWORD fccType;
57 DWORD fccHandler;
58 DRIVERPROC proc;
59 LPWSTR name;
60 reg_driver* next;
63 static reg_driver* reg_driver_list = NULL;
65 HMODULE MSVFW32_hModule;
67 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
69 TRACE("%p,%lx,%p\n", hinst, reason, reserved);
71 switch(reason)
73 case DLL_PROCESS_ATTACH:
74 DisableThreadLibraryCalls(hinst);
75 MSVFW32_hModule = (HMODULE)hinst;
76 break;
78 return TRUE;
81 static int compare_fourcc(DWORD fcc1, DWORD fcc2)
83 char fcc_str1[5];
84 char fcc_str2[5];
85 fcc_str1[0] = LOBYTE(LOWORD(fcc1));
86 fcc_str1[1] = HIBYTE(LOWORD(fcc1));
87 fcc_str1[2] = LOBYTE(HIWORD(fcc1));
88 fcc_str1[3] = HIBYTE(HIWORD(fcc1));
89 fcc_str1[4] = 0;
90 fcc_str2[0] = LOBYTE(LOWORD(fcc2));
91 fcc_str2[1] = HIBYTE(LOWORD(fcc2));
92 fcc_str2[2] = LOBYTE(HIWORD(fcc2));
93 fcc_str2[3] = HIBYTE(HIWORD(fcc2));
94 fcc_str2[4] = 0;
96 return strcasecmp(fcc_str1,fcc_str2);
99 /******************************************************************
100 * MSVIDEO_GetHicPtr
104 WINE_HIC* MSVIDEO_GetHicPtr(HIC hic)
106 WINE_HIC* whic;
108 for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next);
109 return whic;
112 /***********************************************************************
113 * VideoForWindowsVersion [MSVFW32.2]
114 * VideoForWindowsVersion [MSVIDEO.2]
115 * Returns the version in major.minor form.
116 * In Windows95 this returns 0x040003b6 (4.950)
118 DWORD WINAPI VideoForWindowsVersion(void)
120 return 0x040003B6; /* 4.950 */
123 /* system.ini: [drivers] */
125 /***********************************************************************
126 * ICInfo [MSVFW32.@]
127 * Get information about an installable compressor. Return TRUE if there
128 * is one.
130 BOOL VFWAPI ICInfo(
131 DWORD fccType, /* [in] type of compressor ('vidc') */
132 DWORD fccHandler, /* [in] real fcc for handler or <n>th compressor */
133 ICINFO *lpicinfo) /* [out] information about compressor */
135 char buf[2000];
137 TRACE("(%s,%s/%08lx,%p)\n",
138 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo);
140 if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini"))
142 char fccTypeStr[4];
143 char fccHandlerStr[4];
144 char* s;
146 fccTypeStr[0] = LOBYTE(LOWORD(fccType));
147 fccTypeStr[1] = HIBYTE(LOWORD(fccType));
148 fccTypeStr[2] = LOBYTE(HIWORD(fccType));
149 fccTypeStr[3] = HIBYTE(HIWORD(fccType));
151 fccHandlerStr[0] = LOBYTE(LOWORD(fccHandler));
152 fccHandlerStr[1] = HIBYTE(LOWORD(fccHandler));
153 fccHandlerStr[2] = LOBYTE(HIWORD(fccHandler));
154 fccHandlerStr[3] = HIBYTE(HIWORD(fccHandler));
156 for (s = buf; *s; s += strlen(s) + 1)
158 if (!strncasecmp(fccTypeStr, s, 4) && s[4] == '.' && s[9] == '=' &&
159 (!fccHandler-- || !strncasecmp(fccHandlerStr, s + 5, 4)))
161 /* exact match of fccHandler or nth driver found ?? */
162 lpicinfo->fccType = fccType;
163 lpicinfo->fccHandler = mmioStringToFOURCCA(s + 5, 0);
164 lpicinfo->dwFlags = 0;
165 lpicinfo->dwVersion = 0;
166 lpicinfo->dwVersionICM = 0x104;
167 lpicinfo->szName[0] = 0;
168 lpicinfo->szDescription[0] = 0;
169 MultiByteToWideChar(CP_ACP, 0, s + 10, -1,
170 lpicinfo->szDriver,
171 sizeof(lpicinfo->szDriver)/sizeof(WCHAR));
172 return TRUE;
176 return FALSE;
179 static DWORD IC_HandleRef = 1;
181 /***********************************************************************
182 * ICInstall [MSVFW32.@]
184 BOOL VFWAPI ICInstall(DWORD fccType, DWORD fccHandler, LPARAM lParam, LPSTR szDesc, UINT wFlags)
186 reg_driver* driver;
187 unsigned len;
189 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), (void*)lParam, szDesc, wFlags);
191 /* Check if a driver is already registered */
192 for (driver = reg_driver_list; driver; driver = driver->next)
194 if (!compare_fourcc(fccType, driver->fccType) &&
195 !compare_fourcc(fccHandler, driver->fccHandler))
196 break;
198 if (driver) return FALSE;
200 /* Register the driver */
201 driver = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(reg_driver));
202 if (!driver) goto oom;
203 driver->fccType = fccType;
204 driver->fccHandler = fccHandler;
206 switch(wFlags)
208 case ICINSTALL_FUNCTION:
209 driver->proc = (DRIVERPROC)lParam;
210 driver->name = NULL;
211 break;
212 case ICINSTALL_DRIVER:
213 driver->proc = NULL;
214 len = MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, NULL, 0);
215 driver->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
216 if (!driver->name) goto oom;
217 MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, driver->name, len);
218 break;
219 default:
220 ERR("Invalid flags!\n");
221 HeapFree(GetProcessHeap(), 0, driver);
222 return FALSE;
225 /* Insert our driver in the list*/
226 driver->next = reg_driver_list;
227 reg_driver_list = driver;
229 return TRUE;
230 oom:
231 if (driver) HeapFree(GetProcessHeap(), 0, driver);
232 return FALSE;
235 /***********************************************************************
236 * ICRemove [MSVFW32.@]
238 BOOL VFWAPI ICRemove(DWORD fccType, DWORD fccHandler, UINT wFlags)
240 reg_driver** pdriver;
242 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wFlags);
244 /* Check if a driver is already registered */
245 for (pdriver = &reg_driver_list; *pdriver; pdriver = &(*pdriver)->next)
247 if (!compare_fourcc(fccType, (*pdriver)->fccType) &&
248 !compare_fourcc(fccHandler, (*pdriver)->fccHandler))
249 break;
251 if (!*pdriver)
252 return FALSE;
254 /* Remove the driver from the list */
255 *pdriver = (*pdriver)->next;
256 if ((*pdriver)->name)
257 HeapFree(GetProcessHeap(), 0, (*pdriver)->name);
258 HeapFree(GetProcessHeap(), 0, *pdriver);
260 return TRUE;
264 /***********************************************************************
265 * ICOpen [MSVFW32.@]
266 * Opens an installable compressor. Return special handle.
268 HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
270 WCHAR codecname[10];
271 ICOPEN icopen;
272 HDRVR hdrv;
273 WINE_HIC* whic;
274 BOOL bIs16;
275 static const WCHAR drv32W[] = {'d','r','i','v','e','r','s','3','2','\0'};
276 reg_driver* driver;
278 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode);
280 /* Check if there is a registered driver that matches */
281 driver = reg_driver_list;
282 while(driver)
283 if (!compare_fourcc(fccType, driver->fccType) &&
284 !compare_fourcc(fccHandler, driver->fccHandler))
285 break;
286 else
287 driver = driver->next;
289 if (driver && driver->proc)
290 /* The driver has been registered at runtime with its driverproc */
291 return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)driver->proc, (DWORD)NULL);
293 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
294 * same layout as ICOPEN
296 icopen.dwSize = sizeof(ICOPEN);
297 icopen.fccType = fccType;
298 icopen.fccHandler = fccHandler;
299 icopen.dwVersion = 0x00001000; /* FIXME */
300 icopen.dwFlags = wMode;
301 icopen.dwError = 0;
302 icopen.pV1Reserved = NULL;
303 icopen.pV2Reserved = NULL;
304 icopen.dnDevNode = 0; /* FIXME */
306 if (!driver) {
307 /* The driver is registered in the registry */
308 codecname[0] = LOBYTE(LOWORD(fccType));
309 codecname[1] = HIBYTE(LOWORD(fccType));
310 codecname[2] = LOBYTE(HIWORD(fccType));
311 codecname[3] = HIBYTE(HIWORD(fccType));
312 codecname[4] = '.';
313 codecname[5] = LOBYTE(LOWORD(fccHandler));
314 codecname[6] = HIBYTE(LOWORD(fccHandler));
315 codecname[7] = LOBYTE(HIWORD(fccHandler));
316 codecname[8] = HIBYTE(HIWORD(fccHandler));
317 codecname[9] = '\0';
319 hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen);
320 if (!hdrv)
322 if (fccType == streamtypeVIDEO)
324 codecname[0] = 'v';
325 codecname[1] = 'i';
326 codecname[2] = 'd';
327 codecname[3] = 'c';
329 fccType = ICTYPE_VIDEO;
330 hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen);
332 if (!hdrv)
333 return 0;
335 } else {
336 /* The driver has been registered at runtime with its name */
337 hdrv = OpenDriver(driver->name, NULL, (LPARAM)&icopen);
338 if (!hdrv)
339 return 0;
341 bIs16 = GetDriverFlags(hdrv) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */
343 if (bIs16 && !pFnCallTo16)
345 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
346 return 0;
348 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
349 if (!whic)
351 CloseDriver(hdrv, 0, 0);
352 return FALSE;
354 whic->hdrv = hdrv;
355 /* FIXME: is the signature the real one ? */
356 whic->driverproc = bIs16 ? (DRIVERPROC)pFnCallTo16 : NULL;
357 whic->driverproc16 = 0;
358 whic->type = fccType;
359 whic->handler = fccHandler;
360 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
361 whic->hic = HIC_32(IC_HandleRef++);
362 whic->next = MSVIDEO_FirstHic;
363 MSVIDEO_FirstHic = whic;
365 TRACE("=> %p\n", whic->hic);
366 return whic->hic;
369 /***********************************************************************
370 * MSVIDEO_OpenFunction
372 HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode,
373 DRIVERPROC lpfnHandler, DWORD lpfnHandler16)
375 ICOPEN icopen;
376 WINE_HIC* whic;
378 TRACE("(%s,%s,%d,%p,%08lx)\n",
379 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler, lpfnHandler16);
381 icopen.dwSize = sizeof(ICOPEN);
382 icopen.fccType = fccType;
383 icopen.fccHandler = fccHandler;
384 icopen.dwVersion = 0x00001000; /* FIXME */
385 icopen.dwFlags = wMode;
386 icopen.dwError = 0;
387 icopen.pV1Reserved = NULL;
388 icopen.pV2Reserved = NULL;
389 icopen.dnDevNode = 0; /* FIXME */
391 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
392 if (!whic) return 0;
394 whic->driverproc = lpfnHandler;
395 whic->driverproc16 = lpfnHandler16;
396 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
397 whic->hic = HIC_32(IC_HandleRef++);
398 whic->next = MSVIDEO_FirstHic;
399 MSVIDEO_FirstHic = whic;
401 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
402 /* What if the function is used more than once? */
404 if (MSVIDEO_SendMessage(whic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS)
406 WARN("DRV_LOAD failed for hic %p\n", whic->hic);
407 MSVIDEO_FirstHic = whic->next;
408 HeapFree(GetProcessHeap(), 0, whic);
409 return 0;
411 /* return value is not checked */
412 MSVIDEO_SendMessage(whic, DRV_ENABLE, 0L, 0L);
414 whic->driverId = (DWORD)MSVIDEO_SendMessage(whic, DRV_OPEN, 0, (DWORD)&icopen);
415 /* FIXME: What should we put here? */
416 whic->hdrv = (HDRVR)0;
418 if (whic->driverId == 0)
420 WARN("DRV_OPEN failed for hic %p\n", whic->hic);
421 MSVIDEO_FirstHic = whic->next;
422 HeapFree(GetProcessHeap(), 0, whic);
423 return 0;
426 TRACE("=> %p\n", whic->hic);
427 return whic->hic;
430 /***********************************************************************
431 * ICOpenFunction [MSVFW32.@]
433 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler)
435 return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)lpfnHandler, 0);
438 /***********************************************************************
439 * ICGetInfo [MSVFW32.@]
441 LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb)
443 LRESULT ret;
444 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
446 TRACE("(%p,%p,%ld)\n", hic, picinfo, cb);
448 whic = MSVIDEO_GetHicPtr(hic);
449 if (!whic) return ICERR_BADHANDLE;
450 if (!picinfo) return MMSYSERR_INVALPARAM;
452 /* (WS) The field szDriver should be initialized because the driver
453 * is not obliged and often will not do it. Some applications, like
454 * VirtualDub, rely on this field and will occasionally crash if it
455 * goes unitialized.
457 if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0';
459 ret = ICSendMessage(hic, ICM_GETINFO, (DWORD)picinfo, cb);
461 /* (WS) When szDriver was not supplied by the driver itself, apparently
462 * Windows will set its value equal to the driver file name. This can
463 * be obtained from the registry as we do here.
465 if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0)
467 ICINFO ii;
469 memset(&ii, 0, sizeof(ii));
470 ii.dwSize = sizeof(ii);
471 ICInfo(picinfo->fccType, picinfo->fccHandler, &ii);
472 lstrcpyW(picinfo->szDriver, ii.szDriver);
475 TRACE(" -> 0x%08lx\n", ret);
476 return ret;
479 /***********************************************************************
480 * ICLocate [MSVFW32.@]
482 HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
483 LPBITMAPINFOHEADER lpbiOut, WORD wMode)
485 HIC hic;
486 DWORD querymsg;
487 LPSTR pszBuffer;
489 TRACE("(%s,%s,%p,%p,0x%04x)\n",
490 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
492 switch (wMode)
494 case ICMODE_FASTCOMPRESS:
495 case ICMODE_COMPRESS:
496 querymsg = ICM_COMPRESS_QUERY;
497 break;
498 case ICMODE_FASTDECOMPRESS:
499 case ICMODE_DECOMPRESS:
500 querymsg = ICM_DECOMPRESS_QUERY;
501 break;
502 case ICMODE_DRAW:
503 querymsg = ICM_DRAW_QUERY;
504 break;
505 default:
506 WARN("Unknown mode (%d)\n", wMode);
507 return 0;
510 /* Easy case: handler/type match, we just fire a query and return */
511 hic = ICOpen(fccType, fccHandler, wMode);
512 if (hic)
514 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
516 TRACE("=> %p\n", hic);
517 return hic;
519 ICClose(hic);
522 /* Now try each driver in turn. 32 bit codecs only. */
523 /* FIXME: Move this to an init routine? */
525 pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 1024);
526 if (GetPrivateProfileSectionA("drivers32", pszBuffer, 1024, "system.ini"))
528 char* s = pszBuffer;
529 char fcc[4];
531 while (*s)
533 fcc[0] = LOBYTE(LOWORD(fccType));
534 fcc[1] = HIBYTE(LOWORD(fccType));
535 fcc[2] = LOBYTE(HIWORD(fccType));
536 fcc[3] = HIBYTE(HIWORD(fccType));
537 if (!strncasecmp(fcc, s, 4) && s[4] == '.' && s[9] == '=')
539 char *s2 = s;
540 while (*s2 != '\0' && *s2 != '.') s2++;
541 if (*s2++)
543 hic = ICOpen(fccType, mmioStringToFOURCCA(s2, 0), wMode);
544 if (hic)
546 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
548 HeapFree(GetProcessHeap(), 0, pszBuffer);
549 TRACE("=> %p\n", hic);
550 return hic;
552 ICClose(hic);
556 s += strlen(s) + 1;
559 HeapFree(GetProcessHeap(), 0, pszBuffer);
561 if (fccType == streamtypeVIDEO)
562 return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode);
564 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
565 wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
566 return 0;
569 /***********************************************************************
570 * ICGetDisplayFormat [MSVFW32.@]
572 HIC VFWAPI ICGetDisplayFormat(
573 HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
574 INT depth,INT dx,INT dy)
576 HIC tmphic = hic;
578 TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);
580 if (!tmphic) {
581 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
582 if (!tmphic)
583 return tmphic;
585 if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
586 dy = dx = 0; /* no resize needed */
588 /* Can we decompress it ? */
589 if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
590 goto errout; /* no, sorry */
592 ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
594 if (lpbiOut->biCompression != 0) {
595 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
596 lpbiOut->biCompression);
598 if (lpbiOut->biSize < sizeof(*lpbiOut)) {
599 FIXME("Ooch, size of output BIH is too small (%ld)\n",
600 lpbiOut->biSize);
601 lpbiOut->biSize = sizeof(*lpbiOut);
603 if (!depth) {
604 HDC hdc;
606 hdc = GetDC(0);
607 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
608 ReleaseDC(0,hdc);
609 if (depth==15) depth = 16;
610 if (depth<8) depth = 8;
612 if (lpbiIn->biBitCount == 8)
613 depth = 8;
615 TRACE("=> %p\n", tmphic);
616 return tmphic;
617 errout:
618 if (hic!=tmphic)
619 ICClose(tmphic);
621 TRACE("=> 0\n");
622 return 0;
625 /***********************************************************************
626 * ICCompress [MSVFW32.@]
628 DWORD VFWAPIV
629 ICCompress(
630 HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
631 LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
632 LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
633 LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
635 ICCOMPRESS iccmp;
637 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
639 iccmp.dwFlags = dwFlags;
641 iccmp.lpbiOutput = lpbiOutput;
642 iccmp.lpOutput = lpData;
643 iccmp.lpbiInput = lpbiInput;
644 iccmp.lpInput = lpBits;
646 iccmp.lpckid = lpckid;
647 iccmp.lpdwFlags = lpdwFlags;
648 iccmp.lFrameNum = lFrameNum;
649 iccmp.dwFrameSize = dwFrameSize;
650 iccmp.dwQuality = dwQuality;
651 iccmp.lpbiPrev = lpbiPrev;
652 iccmp.lpPrev = lpPrev;
653 return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp));
656 /***********************************************************************
657 * ICDecompress [MSVFW32.@]
659 DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
660 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
662 ICDECOMPRESS icd;
663 DWORD ret;
665 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
667 TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]);
669 icd.dwFlags = dwFlags;
670 icd.lpbiInput = lpbiFormat;
671 icd.lpInput = lpData;
673 icd.lpbiOutput = lpbi;
674 icd.lpOutput = lpBits;
675 icd.ckid = 0;
676 ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
678 TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]);
680 TRACE("-> %ld\n",ret);
682 return ret;
686 /***********************************************************************
687 * ICCompressorChoose [MSVFW32.@]
689 BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn,
690 LPVOID lpData, PCOMPVARS pc, LPSTR lpszTitle)
692 FIXME("(%p,0x%X,%p,%p,%p,%s),stub!\n",hwnd,uiFlags,pvIn,lpData,pc,lpszTitle);
694 if (pc == NULL || pc->cbSize != sizeof(COMPVARS))
695 return FALSE;
697 if ((pc->dwFlags & ICMF_COMPVARS_VALID) == 0) {
698 pc->dwFlags = 0;
699 pc->fccType = pc->fccHandler = 0;
700 pc->hic = NULL;
701 pc->lpbiOut = NULL;
702 pc->lpBitsOut = pc->lpBitsPrev = pc->lpState = NULL;
703 pc->lQ = ICQUALITY_DEFAULT;
704 pc->lKey = -1;
705 pc->lDataRate = 300; /* kB */
706 pc->lpState = NULL;
707 pc->cbState = 0;
709 if (pc->fccType == 0)
710 pc->fccType = ICTYPE_VIDEO;
712 /* FIXME */
714 return FALSE;
718 /***********************************************************************
719 * ICCompressorFree [MSVFW32.@]
721 void VFWAPI ICCompressorFree(PCOMPVARS pc)
723 TRACE("(%p)\n",pc);
725 if (pc != NULL && pc->cbSize == sizeof(COMPVARS)) {
726 if (pc->hic != NULL) {
727 ICClose(pc->hic);
728 pc->hic = NULL;
730 if (pc->lpbiOut != NULL) {
731 GlobalFreePtr(pc->lpbiOut);
732 pc->lpbiOut = NULL;
734 if (pc->lpBitsOut != NULL) {
735 GlobalFreePtr(pc->lpBitsOut);
736 pc->lpBitsOut = NULL;
738 if (pc->lpBitsPrev != NULL) {
739 GlobalFreePtr(pc->lpBitsPrev);
740 pc->lpBitsPrev = NULL;
742 if (pc->lpState != NULL) {
743 GlobalFreePtr(pc->lpBitsPrev);
744 pc->lpState = NULL;
746 pc->dwFlags = 0;
751 /******************************************************************
752 * MSVIDEO_SendMessage
756 LRESULT MSVIDEO_SendMessage(WINE_HIC* whic, UINT msg, DWORD lParam1, DWORD lParam2)
758 LRESULT ret;
760 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
762 switch (msg) {
763 /* DRV_* */
764 XX(DRV_LOAD);
765 XX(DRV_ENABLE);
766 XX(DRV_OPEN);
767 XX(DRV_CLOSE);
768 XX(DRV_DISABLE);
769 XX(DRV_FREE);
770 /* ICM_RESERVED+X */
771 XX(ICM_ABOUT);
772 XX(ICM_CONFIGURE);
773 XX(ICM_GET);
774 XX(ICM_GETINFO);
775 XX(ICM_GETDEFAULTQUALITY);
776 XX(ICM_GETQUALITY);
777 XX(ICM_GETSTATE);
778 XX(ICM_SETQUALITY);
779 XX(ICM_SET);
780 XX(ICM_SETSTATE);
781 /* ICM_USER+X */
782 XX(ICM_COMPRESS_FRAMES_INFO);
783 XX(ICM_COMPRESS_GET_FORMAT);
784 XX(ICM_COMPRESS_GET_SIZE);
785 XX(ICM_COMPRESS_QUERY);
786 XX(ICM_COMPRESS_BEGIN);
787 XX(ICM_COMPRESS);
788 XX(ICM_COMPRESS_END);
789 XX(ICM_DECOMPRESS_GET_FORMAT);
790 XX(ICM_DECOMPRESS_QUERY);
791 XX(ICM_DECOMPRESS_BEGIN);
792 XX(ICM_DECOMPRESS);
793 XX(ICM_DECOMPRESS_END);
794 XX(ICM_DECOMPRESS_SET_PALETTE);
795 XX(ICM_DECOMPRESS_GET_PALETTE);
796 XX(ICM_DRAW_QUERY);
797 XX(ICM_DRAW_BEGIN);
798 XX(ICM_DRAW_GET_PALETTE);
799 XX(ICM_DRAW_START);
800 XX(ICM_DRAW_STOP);
801 XX(ICM_DRAW_END);
802 XX(ICM_DRAW_GETTIME);
803 XX(ICM_DRAW);
804 XX(ICM_DRAW_WINDOW);
805 XX(ICM_DRAW_SETTIME);
806 XX(ICM_DRAW_REALIZE);
807 XX(ICM_DRAW_FLUSH);
808 XX(ICM_DRAW_RENDERBUFFER);
809 XX(ICM_DRAW_START_PLAY);
810 XX(ICM_DRAW_STOP_PLAY);
811 XX(ICM_DRAW_SUGGESTFORMAT);
812 XX(ICM_DRAW_CHANGEPALETTE);
813 XX(ICM_GETBUFFERSWANTED);
814 XX(ICM_GETDEFAULTKEYFRAMERATE);
815 XX(ICM_DECOMPRESSEX_BEGIN);
816 XX(ICM_DECOMPRESSEX_QUERY);
817 XX(ICM_DECOMPRESSEX);
818 XX(ICM_DECOMPRESSEX_END);
819 XX(ICM_SET_STATUS_PROC);
820 default:
821 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic,(DWORD)msg,lParam1,lParam2);
824 #undef XX
826 if (whic->driverproc) {
827 /* dwDriverId parameter is the value returned by the DRV_OPEN */
828 ret = whic->driverproc(whic->driverId, whic->hdrv, msg, lParam1, lParam2);
829 } else {
830 ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
833 TRACE(" -> 0x%08lx\n", ret);
834 return ret;
837 /***********************************************************************
838 * ICSendMessage [MSVFW32.@]
840 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2)
842 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
844 if (!whic) return ICERR_BADHANDLE;
845 return MSVIDEO_SendMessage(whic, msg, lParam1, lParam2);
848 /***********************************************************************
849 * ICDrawBegin [MSVFW32.@]
851 DWORD VFWAPIV ICDrawBegin(
852 HIC hic, /* [in] */
853 DWORD dwFlags, /* [in] flags */
854 HPALETTE hpal, /* [in] palette to draw with */
855 HWND hwnd, /* [in] window to draw to */
856 HDC hdc, /* [in] HDC to draw to */
857 INT xDst, /* [in] destination rectangle */
858 INT yDst, /* [in] */
859 INT dxDst, /* [in] */
860 INT dyDst, /* [in] */
861 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */
862 INT xSrc, /* [in] source rectangle */
863 INT ySrc, /* [in] */
864 INT dxSrc, /* [in] */
865 INT dySrc, /* [in] */
866 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
867 DWORD dwScale) /* [in] */
870 ICDRAWBEGIN icdb;
872 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
873 hic, dwFlags, hpal, hwnd, hdc, xDst, yDst, dxDst, dyDst,
874 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
876 icdb.dwFlags = dwFlags;
877 icdb.hpal = hpal;
878 icdb.hwnd = hwnd;
879 icdb.hdc = hdc;
880 icdb.xDst = xDst;
881 icdb.yDst = yDst;
882 icdb.dxDst = dxDst;
883 icdb.dyDst = dyDst;
884 icdb.lpbi = lpbi;
885 icdb.xSrc = xSrc;
886 icdb.ySrc = ySrc;
887 icdb.dxSrc = dxSrc;
888 icdb.dySrc = dySrc;
889 icdb.dwRate = dwRate;
890 icdb.dwScale = dwScale;
891 return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
894 /***********************************************************************
895 * ICDraw [MSVFW32.@]
897 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
898 ICDRAW icd;
900 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime);
902 icd.dwFlags = dwFlags;
903 icd.lpFormat = lpFormat;
904 icd.lpData = lpData;
905 icd.cbData = cbData;
906 icd.lTime = lTime;
908 return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
911 /***********************************************************************
912 * ICClose [MSVFW32.@]
914 LRESULT WINAPI ICClose(HIC hic)
916 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
917 WINE_HIC** p;
919 TRACE("(%p)\n",hic);
921 if (!whic) return ICERR_BADHANDLE;
923 if (whic->driverproc)
925 MSVIDEO_SendMessage(whic, DRV_CLOSE, 0, 0);
926 MSVIDEO_SendMessage(whic, DRV_DISABLE, 0, 0);
927 MSVIDEO_SendMessage(whic, DRV_FREE, 0, 0);
929 else
931 CloseDriver(whic->hdrv, 0, 0);
934 /* remove whic from list */
935 for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next))
937 if ((*p) == whic)
939 *p = whic->next;
940 break;
944 HeapFree(GetProcessHeap(), 0, whic);
945 return 0;
950 /***********************************************************************
951 * ICImageCompress [MSVFW32.@]
953 HANDLE VFWAPI ICImageCompress(
954 HIC hic, UINT uiFlags,
955 LPBITMAPINFO lpbiIn, LPVOID lpBits,
956 LPBITMAPINFO lpbiOut, LONG lQuality,
957 LONG* plSize)
959 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
960 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
962 return NULL;
965 /***********************************************************************
966 * ICImageDecompress [MSVFW32.@]
969 HANDLE VFWAPI ICImageDecompress(
970 HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
971 LPVOID lpBits, LPBITMAPINFO lpbiOut)
973 HGLOBAL hMem = NULL;
974 BYTE* pMem = NULL;
975 BOOL bReleaseIC = FALSE;
976 BYTE* pHdr = NULL;
977 LONG cbHdr = 0;
978 BOOL bSucceeded = FALSE;
979 BOOL bInDecompress = FALSE;
980 DWORD biSizeImage;
982 TRACE("(%p,%08x,%p,%p,%p)\n",
983 hic, uiFlags, lpbiIn, lpBits, lpbiOut);
985 if ( hic == NULL )
987 hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
988 if ( hic == NULL )
990 WARN("no handler\n" );
991 goto err;
993 bReleaseIC = TRUE;
995 if ( uiFlags != 0 )
997 FIXME( "unknown flag %08x\n", uiFlags );
998 goto err;
1000 if ( lpbiIn == NULL || lpBits == NULL )
1002 WARN("invalid argument\n");
1003 goto err;
1006 if ( lpbiOut != NULL )
1008 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
1009 goto err;
1010 cbHdr = sizeof(BITMAPINFOHEADER);
1011 if ( lpbiOut->bmiHeader.biCompression == 3 )
1012 cbHdr += sizeof(DWORD)*3;
1013 else
1014 if ( lpbiOut->bmiHeader.biBitCount <= 8 )
1016 if ( lpbiOut->bmiHeader.biClrUsed == 0 )
1017 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
1018 else
1019 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
1022 else
1024 TRACE( "get format\n" );
1026 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
1027 if ( cbHdr < sizeof(BITMAPINFOHEADER) )
1028 goto err;
1029 pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256);
1030 if ( pHdr == NULL )
1031 goto err;
1032 ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 );
1033 if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK )
1034 goto err;
1035 lpbiOut = (BITMAPINFO*)pHdr;
1036 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1037 ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
1038 lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
1040 if ( lpbiIn->bmiHeader.biClrUsed == 0 )
1041 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
1042 else
1043 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
1045 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
1046 lpbiOut->bmiHeader.biClrUsed == 0 )
1047 lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
1049 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1050 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
1053 biSizeImage = lpbiOut->bmiHeader.biSizeImage;
1054 if ( biSizeImage == 0 )
1055 biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight);
1057 TRACE( "call ICDecompressBegin\n" );
1059 if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
1060 goto err;
1061 bInDecompress = TRUE;
1063 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage );
1065 hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
1066 if ( hMem == NULL )
1068 WARN( "out of memory\n" );
1069 goto err;
1071 pMem = (BYTE*)GlobalLock( hMem );
1072 if ( pMem == NULL )
1073 goto err;
1074 memcpy( pMem, lpbiOut, cbHdr );
1076 TRACE( "call ICDecompress\n" );
1077 if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
1078 goto err;
1080 bSucceeded = TRUE;
1081 err:
1082 if ( bInDecompress )
1083 ICDecompressEnd( hic );
1084 if ( bReleaseIC )
1085 ICClose(hic);
1086 if ( pHdr != NULL )
1087 HeapFree(GetProcessHeap(),0,pHdr);
1088 if ( pMem != NULL )
1089 GlobalUnlock( hMem );
1090 if ( !bSucceeded && hMem != NULL )
1092 GlobalFree(hMem); hMem = NULL;
1095 return (HANDLE)hMem;
1098 static BOOL GetFileNamePreview(LPVOID lpofn,BOOL bSave,BOOL bUnicode)
1100 CHAR szFunctionName[20];
1101 BOOL (*fnGetFileName)(LPVOID);
1102 HMODULE hComdlg32;
1103 BOOL ret;
1105 FIXME("(%p,%d,%d), semi-stub!\n",lpofn,bSave,bUnicode);
1107 lstrcpyA(szFunctionName, (bSave ? "GetSaveFileName" : "GetOpenFileName"));
1108 lstrcatA(szFunctionName, (bUnicode ? "W" : "A"));
1110 hComdlg32 = LoadLibraryA("COMDLG32.DLL");
1111 if (hComdlg32 == NULL)
1112 return FALSE;
1114 fnGetFileName = (LPVOID)GetProcAddress(hComdlg32, szFunctionName);
1115 if (fnGetFileName == NULL)
1116 return FALSE;
1118 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1119 ret = fnGetFileName(lpofn);
1121 FreeLibrary(hComdlg32);
1122 return ret;
1125 /***********************************************************************
1126 * GetOpenFileNamePreviewA [MSVFW32.@]
1128 BOOL WINAPI GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn)
1130 FIXME("(%p), semi-stub!\n", lpofn);
1132 return GetFileNamePreview(lpofn, FALSE, FALSE);
1135 /***********************************************************************
1136 * GetOpenFileNamePreviewW [MSVFW32.@]
1138 BOOL WINAPI GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn)
1140 FIXME("(%p), semi-stub!\n", lpofn);
1142 return GetFileNamePreview(lpofn, FALSE, TRUE);
1145 /***********************************************************************
1146 * GetSaveFileNamePreviewA [MSVFW32.@]
1148 BOOL WINAPI GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn)
1150 FIXME("(%p), semi-stub!\n", lpofn);
1152 return GetFileNamePreview(lpofn, TRUE, FALSE);
1155 /***********************************************************************
1156 * GetSaveFileNamePreviewW [MSVFW32.@]
1158 BOOL WINAPI GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn)
1160 FIXME("(%p), semi-stub!\n", lpofn);
1162 return GetFileNamePreview(lpofn, TRUE, TRUE);