2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
4 * Copyright 2003 Michael Günnewig
5 * Copyright 2005 Dmitry Timoshkov
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * FIXME: This all assumes 32 bit codecs
22 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
23 * There is the ICOpenFunction16 to worry about still, though.
33 #define COM_NO_WINDOWS_H
42 #include "msvideo_private.h"
43 #include "wine/debug.h"
45 /* Drivers32 settings */
46 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
48 WINE_DEFAULT_DEBUG_CHANNEL(msvideo
);
50 static inline const char *wine_dbgstr_fcc( DWORD fcc
)
52 return wine_dbg_sprintf("%c%c%c%c",
53 LOBYTE(LOWORD(fcc
)), HIBYTE(LOWORD(fcc
)),
54 LOBYTE(HIWORD(fcc
)), HIBYTE(HIWORD(fcc
)));
57 LRESULT (CALLBACK
*pFnCallTo16
)(HDRVR
, HIC
, UINT
, LPARAM
, LPARAM
) = NULL
;
59 static WINE_HIC
* MSVIDEO_FirstHic
/* = NULL */;
61 typedef struct _reg_driver reg_driver
;
71 static reg_driver
* reg_driver_list
= NULL
;
73 /* This one is a macro such that it works for both ASCII and Unicode */
74 #define fourcc_to_string(str, fcc) do { \
75 (str)[0] = LOBYTE(LOWORD(fcc)); \
76 (str)[1] = HIBYTE(LOWORD(fcc)); \
77 (str)[2] = LOBYTE(HIWORD(fcc)); \
78 (str)[3] = HIBYTE(HIWORD(fcc)); \
81 HMODULE MSVFW32_hModule
;
83 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
85 TRACE("%p,%lx,%p\n", hinst
, reason
, reserved
);
89 case DLL_PROCESS_ATTACH
:
90 DisableThreadLibraryCalls(hinst
);
91 MSVFW32_hModule
= (HMODULE
)hinst
;
97 static int compare_fourcc(DWORD fcc1
, DWORD fcc2
)
101 fourcc_to_string(fcc_str1
, fcc1
);
102 fourcc_to_string(fcc_str2
, fcc2
);
103 return strncasecmp(fcc_str1
, fcc_str2
, 4);
106 typedef BOOL (*enum_handler_t
)(const char*, int, void*);
108 static BOOL
enum_drivers(DWORD fccType
, enum_handler_t handler
, void* param
)
110 CHAR buf
[2048], fccTypeStr
[5], *s
;
111 DWORD i
, cnt
= 0, bufLen
, lRet
;
116 fourcc_to_string(fccTypeStr
, fccType
);
119 /* first, go through the registry entries */
120 lRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, HKLM_DRIVERS32
, 0, KEY_QUERY_VALUE
, &hKey
);
121 if (lRet
== ERROR_SUCCESS
)
124 RegQueryInfoKeyA( hKey
, 0, 0, 0, &numkeys
, 0, 0, 0, 0, 0, 0, 0);
125 for (i
= 0; i
< numkeys
; i
++)
127 bufLen
= sizeof(buf
) / sizeof(buf
[0]);
128 lRet
= RegEnumKeyExA(hKey
, i
, buf
, &bufLen
, 0, 0, 0, &lastWrite
);
129 if (lRet
!= ERROR_SUCCESS
) continue;
130 if (strncasecmp(buf
, fccTypeStr
, 5) || buf
[9] != '=') continue;
131 if ((result
= handler(buf
, cnt
++, param
))) break;
135 if (result
) return result
;
137 /* if that didn't work, go through the values in system.ini */
138 if (GetPrivateProfileSectionA("drivers32", buf
, sizeof(buf
), "system.ini"))
140 for (s
= buf
; *s
; s
+= strlen(s
) + 1)
142 TRACE("got %s\n", s
);
143 if (strncasecmp(s
, fccTypeStr
, 5) || s
[9] != '=') continue;
144 if ((result
= handler(s
, cnt
++, param
))) break;
151 /******************************************************************
156 WINE_HIC
* MSVIDEO_GetHicPtr(HIC hic
)
160 for (whic
= MSVIDEO_FirstHic
; whic
&& whic
->hic
!= hic
; whic
= whic
->next
);
164 /***********************************************************************
165 * VideoForWindowsVersion [MSVFW32.2]
166 * VideoForWindowsVersion [MSVIDEO.2]
167 * Returns the version in major.minor form.
168 * In Windows95 this returns 0x040003b6 (4.950)
170 DWORD WINAPI
VideoForWindowsVersion(void)
172 return 0x040003B6; /* 4.950 */
175 static BOOL
ICInfo_enum_handler(const char *drv
, int nr
, void *param
)
177 ICINFO
*lpicinfo
= (ICINFO
*)param
;
178 DWORD fccHandler
= mmioStringToFOURCCA(drv
+ 5, 0);
180 /* exact match of fccHandler or nth driver found */
181 if ((lpicinfo
->fccHandler
!= nr
) && (lpicinfo
->fccHandler
!= fccHandler
))
184 lpicinfo
->fccType
= mmioStringToFOURCCA(drv
, 0);
185 lpicinfo
->fccHandler
= fccHandler
;
186 lpicinfo
->dwFlags
= 0;
187 lpicinfo
->dwVersion
= 0;
188 lpicinfo
->dwVersionICM
= 0x104;
189 lpicinfo
->szName
[0] = 0;
190 lpicinfo
->szDescription
[0] = 0;
191 MultiByteToWideChar(CP_ACP
, 0, drv
+ 10, -1, lpicinfo
->szDriver
,
192 sizeof(lpicinfo
->szDriver
)/sizeof(WCHAR
));
197 /***********************************************************************
199 * Get information about an installable compressor. Return TRUE if there
203 * fccType [I] type of compressor (e.g. 'vidc')
204 * fccHandler [I] real fcc for handler or <n>th compressor
205 * lpicinfo [O] information about compressor
207 BOOL VFWAPI
ICInfo( DWORD fccType
, DWORD fccHandler
, ICINFO
*lpicinfo
)
209 TRACE("(%s,%s/%08lx,%p)\n",
210 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), fccHandler
, lpicinfo
);
212 lpicinfo
->fccHandler
= fccHandler
;
213 return enum_drivers(fccType
, ICInfo_enum_handler
, lpicinfo
);
216 static DWORD IC_HandleRef
= 1;
218 /***********************************************************************
219 * ICInstall [MSVFW32.@]
221 BOOL VFWAPI
ICInstall(DWORD fccType
, DWORD fccHandler
, LPARAM lParam
, LPSTR szDesc
, UINT wFlags
)
226 TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), (void*)lParam
, szDesc
, wFlags
);
228 /* Check if a driver is already registered */
229 for (driver
= reg_driver_list
; driver
; driver
= driver
->next
)
231 if (!compare_fourcc(fccType
, driver
->fccType
) &&
232 !compare_fourcc(fccHandler
, driver
->fccHandler
))
235 if (driver
) return FALSE
;
237 /* Register the driver */
238 driver
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(reg_driver
));
239 if (!driver
) goto oom
;
240 driver
->fccType
= fccType
;
241 driver
->fccHandler
= fccHandler
;
245 case ICINSTALL_FUNCTION
:
246 driver
->proc
= (DRIVERPROC
)lParam
;
249 case ICINSTALL_DRIVER
:
251 len
= MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, NULL
, 0);
252 driver
->name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
253 if (!driver
->name
) goto oom
;
254 MultiByteToWideChar(CP_ACP
, 0, (char*)lParam
, -1, driver
->name
, len
);
257 ERR("Invalid flags!\n");
258 HeapFree(GetProcessHeap(), 0, driver
);
262 /* Insert our driver in the list*/
263 driver
->next
= reg_driver_list
;
264 reg_driver_list
= driver
;
268 HeapFree(GetProcessHeap(), 0, driver
);
272 /***********************************************************************
273 * ICRemove [MSVFW32.@]
275 BOOL VFWAPI
ICRemove(DWORD fccType
, DWORD fccHandler
, UINT wFlags
)
277 reg_driver
** pdriver
;
280 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wFlags
);
282 /* Check if a driver is already registered */
283 for (pdriver
= ®_driver_list
; *pdriver
; pdriver
= &(*pdriver
)->next
)
285 if (!compare_fourcc(fccType
, (*pdriver
)->fccType
) &&
286 !compare_fourcc(fccHandler
, (*pdriver
)->fccHandler
))
292 /* Remove the driver from the list */
294 *pdriver
= (*pdriver
)->next
;
295 HeapFree(GetProcessHeap(), 0, drv
->name
);
296 HeapFree(GetProcessHeap(), 0, drv
);
302 /***********************************************************************
304 * Opens an installable compressor. Return special handle.
306 HIC VFWAPI
ICOpen(DWORD fccType
, DWORD fccHandler
, UINT wMode
)
313 static const WCHAR drv32W
[] = {'d','r','i','v','e','r','s','3','2','\0'};
316 TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
);
318 /* Check if there is a registered driver that matches */
319 driver
= reg_driver_list
;
321 if (!compare_fourcc(fccType
, driver
->fccType
) &&
322 !compare_fourcc(fccHandler
, driver
->fccHandler
))
325 driver
= driver
->next
;
327 if (driver
&& driver
->proc
)
328 /* The driver has been registered at runtime with its driverproc */
329 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)driver
->proc
, (DWORD
)NULL
);
331 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
332 * same layout as ICOPEN
334 icopen
.dwSize
= sizeof(ICOPEN
);
335 icopen
.fccType
= fccType
;
336 icopen
.fccHandler
= fccHandler
;
337 icopen
.dwVersion
= 0x00001000; /* FIXME */
338 icopen
.dwFlags
= wMode
;
340 icopen
.pV1Reserved
= NULL
;
341 icopen
.pV2Reserved
= NULL
;
342 icopen
.dnDevNode
= 0; /* FIXME */
345 /* The driver is registered in the registry */
346 fourcc_to_string(codecname
, fccType
);
348 fourcc_to_string(codecname
+ 5, fccHandler
);
351 hdrv
= OpenDriver(codecname
, drv32W
, (LPARAM
)&icopen
);
355 /* The driver has been registered at runtime with its name */
356 hdrv
= OpenDriver(driver
->name
, NULL
, (LPARAM
)&icopen
);
360 bIs16
= GetDriverFlags(hdrv
) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */
362 if (bIs16
&& !pFnCallTo16
)
364 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
367 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
370 CloseDriver(hdrv
, 0, 0);
374 /* FIXME: is the signature the real one ? */
375 whic
->driverproc
= bIs16
? (DRIVERPROC
)pFnCallTo16
: NULL
;
376 whic
->driverproc16
= 0;
377 whic
->type
= fccType
;
378 whic
->handler
= fccHandler
;
379 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
380 whic
->hic
= HIC_32(IC_HandleRef
++);
381 whic
->next
= MSVIDEO_FirstHic
;
382 MSVIDEO_FirstHic
= whic
;
384 TRACE("=> %p\n", whic
->hic
);
388 /***********************************************************************
389 * MSVIDEO_OpenFunction
391 HIC
MSVIDEO_OpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
,
392 DRIVERPROC lpfnHandler
, DWORD lpfnHandler16
)
397 TRACE("(%s,%s,%d,%p,%08lx)\n",
398 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), wMode
, lpfnHandler
, lpfnHandler16
);
400 icopen
.dwSize
= sizeof(ICOPEN
);
401 icopen
.fccType
= fccType
;
402 icopen
.fccHandler
= fccHandler
;
403 icopen
.dwVersion
= 0x00001000; /* FIXME */
404 icopen
.dwFlags
= wMode
;
406 icopen
.pV1Reserved
= NULL
;
407 icopen
.pV2Reserved
= NULL
;
408 icopen
.dnDevNode
= 0; /* FIXME */
410 whic
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC
));
413 whic
->driverproc
= lpfnHandler
;
414 whic
->driverproc16
= lpfnHandler16
;
415 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef
)) != NULL
) IC_HandleRef
++;
416 whic
->hic
= HIC_32(IC_HandleRef
++);
417 whic
->next
= MSVIDEO_FirstHic
;
418 MSVIDEO_FirstHic
= whic
;
420 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
421 /* What if the function is used more than once? */
423 if (MSVIDEO_SendMessage(whic
, DRV_LOAD
, 0L, 0L) != DRV_SUCCESS
)
425 WARN("DRV_LOAD failed for hic %p\n", whic
->hic
);
426 MSVIDEO_FirstHic
= whic
->next
;
427 HeapFree(GetProcessHeap(), 0, whic
);
430 /* return value is not checked */
431 MSVIDEO_SendMessage(whic
, DRV_ENABLE
, 0L, 0L);
433 whic
->driverId
= (DWORD
)MSVIDEO_SendMessage(whic
, DRV_OPEN
, 0, (DWORD_PTR
)&icopen
);
434 /* FIXME: What should we put here? */
437 if (whic
->driverId
== 0)
439 WARN("DRV_OPEN failed for hic %p\n", whic
->hic
);
440 MSVIDEO_FirstHic
= whic
->next
;
441 HeapFree(GetProcessHeap(), 0, whic
);
445 TRACE("=> %p\n", whic
->hic
);
449 /***********************************************************************
450 * ICOpenFunction [MSVFW32.@]
452 HIC VFWAPI
ICOpenFunction(DWORD fccType
, DWORD fccHandler
, UINT wMode
, FARPROC lpfnHandler
)
454 return MSVIDEO_OpenFunction(fccType
, fccHandler
, wMode
, (DRIVERPROC
)lpfnHandler
, 0);
457 /***********************************************************************
458 * ICGetInfo [MSVFW32.@]
460 LRESULT VFWAPI
ICGetInfo(HIC hic
, ICINFO
*picinfo
, DWORD cb
)
463 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
465 TRACE("(%p,%p,%ld)\n", hic
, picinfo
, cb
);
467 whic
= MSVIDEO_GetHicPtr(hic
);
468 if (!whic
) return ICERR_BADHANDLE
;
469 if (!picinfo
) return MMSYSERR_INVALPARAM
;
471 /* (WS) The field szDriver should be initialized because the driver
472 * is not obliged and often will not do it. Some applications, like
473 * VirtualDub, rely on this field and will occasionally crash if it
476 if (cb
>= sizeof(ICINFO
)) picinfo
->szDriver
[0] = '\0';
478 ret
= ICSendMessage(hic
, ICM_GETINFO
, (DWORD_PTR
)picinfo
, cb
);
480 /* (WS) When szDriver was not supplied by the driver itself, apparently
481 * Windows will set its value equal to the driver file name. This can
482 * be obtained from the registry as we do here.
484 if (cb
>= sizeof(ICINFO
) && picinfo
->szDriver
[0] == 0)
488 memset(&ii
, 0, sizeof(ii
));
489 ii
.dwSize
= sizeof(ii
);
490 ICInfo(picinfo
->fccType
, picinfo
->fccHandler
, &ii
);
491 lstrcpyW(picinfo
->szDriver
, ii
.szDriver
);
494 TRACE(" -> 0x%08lx\n", ret
);
501 LPBITMAPINFOHEADER lpbiIn
;
502 LPBITMAPINFOHEADER lpbiOut
;
508 static HIC
try_driver(driver_info_t
*info
)
512 if ((hic
= ICOpen(info
->fccType
, info
->fccHandler
, info
->wMode
)))
514 if (!ICSendMessage(hic
, info
->querymsg
, (DWORD_PTR
)info
->lpbiIn
, (DWORD_PTR
)info
->lpbiOut
))
521 static BOOL
ICLocate_enum_handler(const char *drv
, int nr
, void *param
)
523 driver_info_t
*info
= (driver_info_t
*)param
;
524 info
->fccHandler
= mmioStringToFOURCCA(drv
+ 5, 0);
525 info
->hic
= try_driver(info
);
526 return info
->hic
!= 0;
529 /***********************************************************************
530 * ICLocate [MSVFW32.@]
532 HIC VFWAPI
ICLocate(DWORD fccType
, DWORD fccHandler
, LPBITMAPINFOHEADER lpbiIn
,
533 LPBITMAPINFOHEADER lpbiOut
, WORD wMode
)
537 TRACE("(%s,%s,%p,%p,0x%04x)\n",
538 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
540 info
.fccType
= fccType
;
541 info
.fccHandler
= fccHandler
;
542 info
.lpbiIn
= lpbiIn
;
543 info
.lpbiOut
= lpbiOut
;
548 case ICMODE_FASTCOMPRESS
:
549 case ICMODE_COMPRESS
:
550 info
.querymsg
= ICM_COMPRESS_QUERY
;
552 case ICMODE_FASTDECOMPRESS
:
553 case ICMODE_DECOMPRESS
:
554 info
.querymsg
= ICM_DECOMPRESS_QUERY
;
557 info
.querymsg
= ICM_DRAW_QUERY
;
560 WARN("Unknown mode (%d)\n", wMode
);
564 /* Easy case: handler/type match, we just fire a query and return */
565 info
.hic
= try_driver(&info
);
566 /* If it didn't work, try each driver in turn. 32 bit codecs only. */
567 /* FIXME: Move this to an init routine? */
568 if (!info
.hic
) enum_drivers(fccType
, ICLocate_enum_handler
, &info
);
572 TRACE("=> %p\n", info
.hic
);
576 if (fccType
== streamtypeVIDEO
)
577 return ICLocate(ICTYPE_VIDEO
, fccHandler
, lpbiIn
, lpbiOut
, wMode
);
579 WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
580 wine_dbgstr_fcc(fccType
), wine_dbgstr_fcc(fccHandler
), lpbiIn
, lpbiOut
, wMode
);
584 /***********************************************************************
585 * ICGetDisplayFormat [MSVFW32.@]
587 HIC VFWAPI
ICGetDisplayFormat(
588 HIC hic
,LPBITMAPINFOHEADER lpbiIn
,LPBITMAPINFOHEADER lpbiOut
,
589 INT depth
,INT dx
,INT dy
)
593 TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic
,lpbiIn
,lpbiOut
,depth
,dx
,dy
);
596 tmphic
=ICLocate(ICTYPE_VIDEO
,0,lpbiIn
,NULL
,ICMODE_DECOMPRESS
);
600 if ((dy
== lpbiIn
->biHeight
) && (dx
== lpbiIn
->biWidth
))
601 dy
= dx
= 0; /* no resize needed */
603 /* Can we decompress it ? */
604 if (ICDecompressQuery(tmphic
,lpbiIn
,NULL
) != 0)
605 goto errout
; /* no, sorry */
607 ICDecompressGetFormat(tmphic
,lpbiIn
,lpbiOut
);
609 if (lpbiOut
->biCompression
!= 0) {
610 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
611 lpbiOut
->biCompression
);
613 if (lpbiOut
->biSize
< sizeof(*lpbiOut
)) {
614 FIXME("Ooch, size of output BIH is too small (%ld)\n",
616 lpbiOut
->biSize
= sizeof(*lpbiOut
);
622 depth
= GetDeviceCaps(hdc
,BITSPIXEL
)*GetDeviceCaps(hdc
,PLANES
);
624 if (depth
==15) depth
= 16;
625 if (depth
<8) depth
= 8;
627 if (lpbiIn
->biBitCount
== 8)
630 TRACE("=> %p\n", tmphic
);
640 /***********************************************************************
641 * ICCompress [MSVFW32.@]
645 HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiOutput
,LPVOID lpData
,
646 LPBITMAPINFOHEADER lpbiInput
,LPVOID lpBits
,LPDWORD lpckid
,
647 LPDWORD lpdwFlags
,LONG lFrameNum
,DWORD dwFrameSize
,DWORD dwQuality
,
648 LPBITMAPINFOHEADER lpbiPrev
,LPVOID lpPrev
)
652 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic
,dwFlags
,lpbiOutput
,lpData
,lpbiInput
,lpBits
);
654 iccmp
.dwFlags
= dwFlags
;
656 iccmp
.lpbiOutput
= lpbiOutput
;
657 iccmp
.lpOutput
= lpData
;
658 iccmp
.lpbiInput
= lpbiInput
;
659 iccmp
.lpInput
= lpBits
;
661 iccmp
.lpckid
= lpckid
;
662 iccmp
.lpdwFlags
= lpdwFlags
;
663 iccmp
.lFrameNum
= lFrameNum
;
664 iccmp
.dwFrameSize
= dwFrameSize
;
665 iccmp
.dwQuality
= dwQuality
;
666 iccmp
.lpbiPrev
= lpbiPrev
;
667 iccmp
.lpPrev
= lpPrev
;
668 return ICSendMessage(hic
,ICM_COMPRESS
,(DWORD_PTR
)&iccmp
,sizeof(iccmp
));
671 /***********************************************************************
672 * ICDecompress [MSVFW32.@]
674 DWORD VFWAPIV
ICDecompress(HIC hic
,DWORD dwFlags
,LPBITMAPINFOHEADER lpbiFormat
,
675 LPVOID lpData
,LPBITMAPINFOHEADER lpbi
,LPVOID lpBits
)
680 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic
,dwFlags
,lpbiFormat
,lpData
,lpbi
,lpBits
);
682 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
684 icd
.dwFlags
= dwFlags
;
685 icd
.lpbiInput
= lpbiFormat
;
686 icd
.lpInput
= lpData
;
688 icd
.lpbiOutput
= lpbi
;
689 icd
.lpOutput
= lpBits
;
691 ret
= ICSendMessage(hic
,ICM_DECOMPRESS
,(DWORD_PTR
)&icd
,sizeof(ICDECOMPRESS
));
693 TRACE("lpBits[0] == %lx\n",((LPDWORD
)lpBits
)[0]);
695 TRACE("-> %ld\n",ret
);
701 struct choose_compressor
708 static BOOL
enum_compressors(HWND list
)
715 while (ICInfo(ICTYPE_VIDEO
, id
, &icinfo
))
721 hic
= ICOpen(icinfo
.fccType
, icinfo
.fccHandler
, ICMODE_COMPRESS
);
725 /* for unknown reason fccHandler reported by the driver
726 * doesn't always work, use the one returned by ICInfo instead.
728 DWORD fccHandler
= icinfo
.fccHandler
;
730 ICGetInfo(hic
, &icinfo
, sizeof(icinfo
));
731 icinfo
.fccHandler
= fccHandler
;
734 idx
= SendMessageW(list
, CB_ADDSTRING
, 0, (LPARAM
)icinfo
.szDescription
);
736 ic
= HeapAlloc(GetProcessHeap(), 0, sizeof(ICINFO
));
738 SendMessageW(list
, CB_SETITEMDATA
, idx
, (LPARAM
)ic
);
746 static INT_PTR CALLBACK
icm_choose_compressor_dlgproc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
753 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)lparam
;
755 if (choose_comp
->title
)
756 SetWindowTextA(hdlg
, choose_comp
->title
);
758 LoadStringW(MSVFW32_hModule
, IDS_FULLFRAMES
, buf
, 128);
759 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
761 enum_compressors(GetDlgItem(hdlg
, IDC_COMP_LIST
));
763 SendDlgItemMessageW(hdlg
, IDC_COMP_LIST
, CB_SETCURSEL
, 0, 0);
764 SetFocus(GetDlgItem(hdlg
, IDC_COMP_LIST
));
766 SetWindowLongPtrW(hdlg
, DWLP_USER
, (ULONG_PTR
)choose_comp
);
771 switch (LOWORD(wparam
))
775 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
779 cur_sel
= SendMessageW(list
, CB_GETCURSEL
, 0, 0);
780 ic
= (ICINFO
*)SendMessageW(list
, CB_GETITEMDATA
, cur_sel
, 0);
783 struct choose_compressor
*choose_comp
= (struct choose_compressor
*)GetWindowLongPtrW(hdlg
, DWLP_USER
);
785 choose_comp
->cv
.hic
= ICOpen(ic
->fccType
, ic
->fccHandler
, ICMODE_COMPRESS
);
786 if (choose_comp
->cv
.hic
)
788 choose_comp
->cv
.fccType
= ic
->fccType
;
789 choose_comp
->cv
.fccHandler
= ic
->fccHandler
;
790 /* FIXME: fill everything else */
797 HWND list
= GetDlgItem(hdlg
, IDC_COMP_LIST
);
802 LRESULT ret
= SendMessageW(list
, CB_GETITEMDATA
, idx
++, 0);
804 if (!ret
|| ret
== CB_ERR
) break;
806 HeapFree(GetProcessHeap(), 0, (void *)ret
);
809 EndDialog(hdlg
, LOWORD(wparam
) == IDOK
);
825 /***********************************************************************
826 * ICCompressorChoose [MSVFW32.@]
828 BOOL VFWAPI
ICCompressorChoose(HWND hwnd
, UINT uiFlags
, LPVOID pvIn
,
829 LPVOID lpData
, PCOMPVARS pc
, LPSTR lpszTitle
)
831 struct choose_compressor choose_comp
;
834 TRACE("(%p,%08x,%p,%p,%p,%s)\n", hwnd
, uiFlags
, pvIn
, lpData
, pc
, lpszTitle
);
836 if (!pc
|| pc
->cbSize
!= sizeof(COMPVARS
))
839 if (!(pc
->dwFlags
& ICMF_COMPVARS_VALID
))
842 pc
->fccType
= pc
->fccHandler
= 0;
845 pc
->lpBitsOut
= pc
->lpBitsPrev
= pc
->lpState
= NULL
;
846 pc
->lQ
= ICQUALITY_DEFAULT
;
848 pc
->lDataRate
= 300; /* kB */
852 if (pc
->fccType
== 0)
853 pc
->fccType
= ICTYPE_VIDEO
;
855 choose_comp
.flags
= uiFlags
;
856 choose_comp
.title
= lpszTitle
;
858 ret
= DialogBoxParamW(MSVFW32_hModule
, MAKEINTRESOURCEW(ICM_CHOOSE_COMPRESSOR
), hwnd
,
859 icm_choose_compressor_dlgproc
, (LPARAM
)&choose_comp
);
863 *pc
= choose_comp
.cv
;
864 pc
->dwFlags
|= ICMF_COMPVARS_VALID
;
871 /***********************************************************************
872 * ICCompressorFree [MSVFW32.@]
874 void VFWAPI
ICCompressorFree(PCOMPVARS pc
)
878 if (pc
!= NULL
&& pc
->cbSize
== sizeof(COMPVARS
)) {
879 if (pc
->hic
!= NULL
) {
883 if (pc
->lpbiIn
!= NULL
) {
884 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
887 if (pc
->lpBitsOut
!= NULL
) {
888 HeapFree(GetProcessHeap(), 0, pc
->lpBitsOut
);
889 pc
->lpBitsOut
= NULL
;
891 if (pc
->lpBitsPrev
!= NULL
) {
892 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
893 pc
->lpBitsPrev
= NULL
;
895 if (pc
->lpState
!= NULL
) {
896 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
904 /******************************************************************
905 * MSVIDEO_SendMessage
909 LRESULT
MSVIDEO_SendMessage(WINE_HIC
* whic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
913 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break;
928 XX(ICM_GETDEFAULTQUALITY
);
935 XX(ICM_COMPRESS_FRAMES_INFO
);
936 XX(ICM_COMPRESS_GET_FORMAT
);
937 XX(ICM_COMPRESS_GET_SIZE
);
938 XX(ICM_COMPRESS_QUERY
);
939 XX(ICM_COMPRESS_BEGIN
);
941 XX(ICM_COMPRESS_END
);
942 XX(ICM_DECOMPRESS_GET_FORMAT
);
943 XX(ICM_DECOMPRESS_QUERY
);
944 XX(ICM_DECOMPRESS_BEGIN
);
946 XX(ICM_DECOMPRESS_END
);
947 XX(ICM_DECOMPRESS_SET_PALETTE
);
948 XX(ICM_DECOMPRESS_GET_PALETTE
);
951 XX(ICM_DRAW_GET_PALETTE
);
955 XX(ICM_DRAW_GETTIME
);
958 XX(ICM_DRAW_SETTIME
);
959 XX(ICM_DRAW_REALIZE
);
961 XX(ICM_DRAW_RENDERBUFFER
);
962 XX(ICM_DRAW_START_PLAY
);
963 XX(ICM_DRAW_STOP_PLAY
);
964 XX(ICM_DRAW_SUGGESTFORMAT
);
965 XX(ICM_DRAW_CHANGEPALETTE
);
966 XX(ICM_GETBUFFERSWANTED
);
967 XX(ICM_GETDEFAULTKEYFRAMERATE
);
968 XX(ICM_DECOMPRESSEX_BEGIN
);
969 XX(ICM_DECOMPRESSEX_QUERY
);
970 XX(ICM_DECOMPRESSEX
);
971 XX(ICM_DECOMPRESSEX_END
);
972 XX(ICM_SET_STATUS_PROC
);
974 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic
,(DWORD
)msg
,lParam1
,lParam2
);
979 if (whic
->driverproc
) {
980 /* dwDriverId parameter is the value returned by the DRV_OPEN */
981 ret
= whic
->driverproc(whic
->driverId
, whic
->hdrv
, msg
, lParam1
, lParam2
);
983 ret
= SendDriverMessage(whic
->hdrv
, msg
, lParam1
, lParam2
);
986 TRACE(" -> 0x%08lx\n", ret
);
990 /***********************************************************************
991 * ICSendMessage [MSVFW32.@]
993 LRESULT VFWAPI
ICSendMessage(HIC hic
, UINT msg
, DWORD_PTR lParam1
, DWORD_PTR lParam2
)
995 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
997 if (!whic
) return ICERR_BADHANDLE
;
998 return MSVIDEO_SendMessage(whic
, msg
, lParam1
, lParam2
);
1001 /***********************************************************************
1002 * ICDrawBegin [MSVFW32.@]
1004 DWORD VFWAPIV
ICDrawBegin(
1006 DWORD dwFlags
, /* [in] flags */
1007 HPALETTE hpal
, /* [in] palette to draw with */
1008 HWND hwnd
, /* [in] window to draw to */
1009 HDC hdc
, /* [in] HDC to draw to */
1010 INT xDst
, /* [in] destination rectangle */
1011 INT yDst
, /* [in] */
1012 INT dxDst
, /* [in] */
1013 INT dyDst
, /* [in] */
1014 LPBITMAPINFOHEADER lpbi
, /* [in] format of frame to draw */
1015 INT xSrc
, /* [in] source rectangle */
1016 INT ySrc
, /* [in] */
1017 INT dxSrc
, /* [in] */
1018 INT dySrc
, /* [in] */
1019 DWORD dwRate
, /* [in] frames/second = (dwRate/dwScale) */
1020 DWORD dwScale
) /* [in] */
1025 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
1026 hic
, dwFlags
, hpal
, hwnd
, hdc
, xDst
, yDst
, dxDst
, dyDst
,
1027 lpbi
, xSrc
, ySrc
, dxSrc
, dySrc
, dwRate
, dwScale
);
1029 icdb
.dwFlags
= dwFlags
;
1042 icdb
.dwRate
= dwRate
;
1043 icdb
.dwScale
= dwScale
;
1044 return ICSendMessage(hic
,ICM_DRAW_BEGIN
,(DWORD_PTR
)&icdb
,sizeof(icdb
));
1047 /***********************************************************************
1048 * ICDraw [MSVFW32.@]
1050 DWORD VFWAPIV
ICDraw(HIC hic
, DWORD dwFlags
, LPVOID lpFormat
, LPVOID lpData
, DWORD cbData
, LONG lTime
) {
1053 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic
,dwFlags
,lpFormat
,lpData
,cbData
,lTime
);
1055 icd
.dwFlags
= dwFlags
;
1056 icd
.lpFormat
= lpFormat
;
1057 icd
.lpData
= lpData
;
1058 icd
.cbData
= cbData
;
1061 return ICSendMessage(hic
,ICM_DRAW
,(DWORD_PTR
)&icd
,sizeof(icd
));
1064 /***********************************************************************
1065 * ICClose [MSVFW32.@]
1067 LRESULT WINAPI
ICClose(HIC hic
)
1069 WINE_HIC
* whic
= MSVIDEO_GetHicPtr(hic
);
1072 TRACE("(%p)\n",hic
);
1074 if (!whic
) return ICERR_BADHANDLE
;
1076 if (whic
->driverproc
)
1078 MSVIDEO_SendMessage(whic
, DRV_CLOSE
, 0, 0);
1079 MSVIDEO_SendMessage(whic
, DRV_DISABLE
, 0, 0);
1080 MSVIDEO_SendMessage(whic
, DRV_FREE
, 0, 0);
1084 CloseDriver(whic
->hdrv
, 0, 0);
1087 /* remove whic from list */
1088 for (p
= &MSVIDEO_FirstHic
; *p
!= NULL
; p
= &((*p
)->next
))
1097 HeapFree(GetProcessHeap(), 0, whic
);
1103 /***********************************************************************
1104 * ICImageCompress [MSVFW32.@]
1106 HANDLE VFWAPI
ICImageCompress(
1107 HIC hic
, UINT uiFlags
,
1108 LPBITMAPINFO lpbiIn
, LPVOID lpBits
,
1109 LPBITMAPINFO lpbiOut
, LONG lQuality
,
1112 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
1113 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
, lQuality
, plSize
);
1118 /***********************************************************************
1119 * ICImageDecompress [MSVFW32.@]
1122 HANDLE VFWAPI
ICImageDecompress(
1123 HIC hic
, UINT uiFlags
, LPBITMAPINFO lpbiIn
,
1124 LPVOID lpBits
, LPBITMAPINFO lpbiOut
)
1126 HGLOBAL hMem
= NULL
;
1128 BOOL bReleaseIC
= FALSE
;
1131 BOOL bSucceeded
= FALSE
;
1132 BOOL bInDecompress
= FALSE
;
1135 TRACE("(%p,%08x,%p,%p,%p)\n",
1136 hic
, uiFlags
, lpbiIn
, lpBits
, lpbiOut
);
1140 hic
= ICDecompressOpen( ICTYPE_VIDEO
, 0, &lpbiIn
->bmiHeader
, (lpbiOut
!= NULL
) ? &lpbiOut
->bmiHeader
: NULL
);
1143 WARN("no handler\n" );
1150 FIXME( "unknown flag %08x\n", uiFlags
);
1153 if ( lpbiIn
== NULL
|| lpBits
== NULL
)
1155 WARN("invalid argument\n");
1159 if ( lpbiOut
!= NULL
)
1161 if ( lpbiOut
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) )
1163 cbHdr
= sizeof(BITMAPINFOHEADER
);
1164 if ( lpbiOut
->bmiHeader
.biCompression
== 3 )
1165 cbHdr
+= sizeof(DWORD
)*3;
1167 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 )
1169 if ( lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1170 cbHdr
+= sizeof(RGBQUAD
) * (1<<lpbiOut
->bmiHeader
.biBitCount
);
1172 cbHdr
+= sizeof(RGBQUAD
) * lpbiOut
->bmiHeader
.biClrUsed
;
1177 TRACE( "get format\n" );
1179 cbHdr
= ICDecompressGetFormatSize(hic
,lpbiIn
);
1180 if ( cbHdr
< sizeof(BITMAPINFOHEADER
) )
1182 pHdr
= HeapAlloc(GetProcessHeap(),0,cbHdr
+sizeof(RGBQUAD
)*256);
1185 ZeroMemory( pHdr
, cbHdr
+sizeof(RGBQUAD
)*256 );
1186 if ( ICDecompressGetFormat( hic
, lpbiIn
, (BITMAPINFO
*)pHdr
) != ICERR_OK
)
1188 lpbiOut
= (BITMAPINFO
*)pHdr
;
1189 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1190 ICDecompressGetPalette( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
&&
1191 lpbiIn
->bmiHeader
.biBitCount
== lpbiOut
->bmiHeader
.biBitCount
)
1193 if ( lpbiIn
->bmiHeader
.biClrUsed
== 0 )
1194 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*(1<<lpbiOut
->bmiHeader
.biBitCount
) );
1196 memcpy( lpbiOut
->bmiColors
, lpbiIn
->bmiColors
, sizeof(RGBQUAD
)*lpbiIn
->bmiHeader
.biClrUsed
);
1198 if ( lpbiOut
->bmiHeader
.biBitCount
<= 8 &&
1199 lpbiOut
->bmiHeader
.biClrUsed
== 0 )
1200 lpbiOut
->bmiHeader
.biClrUsed
= 1<<lpbiOut
->bmiHeader
.biBitCount
;
1202 lpbiOut
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1203 cbHdr
= sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
)*lpbiOut
->bmiHeader
.biClrUsed
;
1206 biSizeImage
= lpbiOut
->bmiHeader
.biSizeImage
;
1207 if ( biSizeImage
== 0 )
1208 biSizeImage
= ((((lpbiOut
->bmiHeader
.biWidth
* lpbiOut
->bmiHeader
.biBitCount
+ 7) >> 3) + 3) & (~3)) * abs(lpbiOut
->bmiHeader
.biHeight
);
1210 TRACE( "call ICDecompressBegin\n" );
1212 if ( ICDecompressBegin( hic
, lpbiIn
, lpbiOut
) != ICERR_OK
)
1214 bInDecompress
= TRUE
;
1216 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr
, biSizeImage
);
1218 hMem
= GlobalAlloc( GMEM_MOVEABLE
|GMEM_ZEROINIT
, cbHdr
+ biSizeImage
);
1221 WARN( "out of memory\n" );
1224 pMem
= (BYTE
*)GlobalLock( hMem
);
1227 memcpy( pMem
, lpbiOut
, cbHdr
);
1229 TRACE( "call ICDecompress\n" );
1230 if ( ICDecompress( hic
, 0, &lpbiIn
->bmiHeader
, lpBits
, &lpbiOut
->bmiHeader
, pMem
+cbHdr
) != ICERR_OK
)
1235 if ( bInDecompress
)
1236 ICDecompressEnd( hic
);
1239 HeapFree(GetProcessHeap(),0,pHdr
);
1241 GlobalUnlock( hMem
);
1242 if ( !bSucceeded
&& hMem
!= NULL
)
1244 GlobalFree(hMem
); hMem
= NULL
;
1247 return (HANDLE
)hMem
;
1250 /***********************************************************************
1251 * ICSeqCompressFrame [MSVFW32.@]
1253 LPVOID VFWAPI
ICSeqCompressFrame(PCOMPVARS pc
, UINT uiFlags
, LPVOID lpBits
, BOOL
*pfKey
, LONG
*plSize
)
1255 ICCOMPRESS
* icComp
= (ICCOMPRESS
*)pc
->lpState
;
1257 TRACE("(%p, 0x%08x, %p, %p, %p)\n", pc
, uiFlags
, lpBits
, pfKey
, plSize
);
1259 if (pc
->cbState
!= sizeof(ICCOMPRESS
))
1261 ERR("Invalid cbState (%li should be %i)\n", pc
->cbState
, sizeof(ICCOMPRESS
));
1265 if (!pc
->lKeyCount
++)
1266 icComp
->dwFlags
= ICCOMPRESS_KEYFRAME
;
1269 if (pc
->lKey
&& pc
->lKeyCount
== (pc
->lKey
- 1))
1270 /* No key frames if pc->lKey == 0 */
1272 icComp
->dwFlags
= 0;
1275 icComp
->lpInput
= lpBits
;
1276 icComp
->lFrameNum
= pc
->lFrame
++;
1277 icComp
->lpOutput
= pc
->lpBitsOut
;
1278 icComp
->lpPrev
= pc
->lpBitsPrev
;
1279 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS
, (DWORD_PTR
)icComp
, sizeof(icComp
));
1281 if (icComp
->dwFlags
& AVIIF_KEYFRAME
)
1285 TRACE("Key frame\n");
1290 *plSize
= icComp
->lpbiOutput
->biSizeImage
;
1291 TRACE(" -- 0x%08lx\n", ret
);
1292 if (ret
== ICERR_OK
)
1294 LPVOID oldprev
, oldout
;
1295 /* We shift Prev and Out, so we don't have to allocate and release memory */
1296 oldprev
= pc
->lpBitsPrev
;
1297 oldout
= pc
->lpBitsOut
;
1298 pc
->lpBitsPrev
= oldout
;
1299 pc
->lpBitsOut
= oldprev
;
1301 TRACE("returning: %p\n", icComp
->lpOutput
);
1302 return icComp
->lpOutput
;
1307 /***********************************************************************
1308 * ICSeqCompressFrameEnd [MSVFW32.@]
1310 void VFWAPI
ICSeqCompressFrameEnd(PCOMPVARS pc
)
1313 TRACE("(%p)\n", pc
);
1314 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_END
, 0, 0);
1315 TRACE(" -- %lx", ret
);
1317 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1319 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1321 HeapFree(GetProcessHeap(), 0, pc
->lpBitsOut
);
1323 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
1324 pc
->lpbiIn
= pc
->lpBitsPrev
= pc
->lpBitsOut
= pc
->lpState
= NULL
;
1327 /***********************************************************************
1328 * ICSeqCompressFrameStart [MSVFW32.@]
1330 BOOL VFWAPI
ICSeqCompressFrameStart(PCOMPVARS pc
, LPBITMAPINFO lpbiIn
)
1332 /* I'm ignoring bmiColors as I don't know what to do with it,
1333 * it doesn't appear to be used though
1336 pc
->lpbiIn
= HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO
));
1340 memcpy(pc
->lpbiIn
, lpbiIn
, sizeof(BITMAPINFO
));
1341 pc
->lpBitsPrev
= HeapAlloc(GetProcessHeap(), 0, pc
->lpbiIn
->bmiHeader
.biSizeImage
);
1342 if (!pc
->lpBitsPrev
)
1344 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1348 pc
->lpState
= HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS
));
1351 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1352 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1355 pc
->cbState
= sizeof(ICCOMPRESS
);
1357 pc
->lpBitsOut
= HeapAlloc(GetProcessHeap(), 0, pc
->lpbiOut
->bmiHeader
.biSizeImage
);
1360 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1361 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1362 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
1373 "key/data/quality: %li/%li/%li\n",
1374 pc
->cbSize
, pc
->dwFlags
, pc
->hic
, pc
->fccType
, pc
->fccHandler
,
1375 pc
->lpbiIn
, pc
->lpbiOut
, pc
->lKey
, pc
->lDataRate
, pc
->lQ
);
1377 ret
= ICSendMessage(pc
->hic
, ICM_COMPRESS_BEGIN
, (DWORD_PTR
)pc
->lpbiIn
, (DWORD_PTR
)pc
->lpbiOut
);
1378 TRACE(" -- %lx\n", ret
);
1379 if (ret
== ICERR_OK
)
1381 ICCOMPRESS
* icComp
= (ICCOMPRESS
*)pc
->lpState
;
1382 /* Initialise some variables */
1383 pc
->lFrame
= 0; pc
->lKeyCount
= 0;
1385 icComp
->lpbiOutput
= &pc
->lpbiOut
->bmiHeader
;
1386 icComp
->lpbiInput
= &pc
->lpbiIn
->bmiHeader
;
1387 icComp
->lpckid
= NULL
;
1388 icComp
->dwFrameSize
= 0;
1389 icComp
->dwQuality
= pc
->lQ
;
1390 icComp
->lpbiPrev
= &pc
->lpbiIn
->bmiHeader
;
1393 HeapFree(GetProcessHeap(), 0, pc
->lpbiIn
);
1394 HeapFree(GetProcessHeap(), 0, pc
->lpBitsPrev
);
1395 HeapFree(GetProcessHeap(), 0, pc
->lpState
);
1396 HeapFree(GetProcessHeap(), 0, pc
->lpBitsOut
);
1397 pc
->lpBitsPrev
= pc
->lpbiIn
= pc
->lpState
= pc
->lpBitsOut
= NULL
;
1401 /***********************************************************************
1402 * GetFileNamePreview [MSVFW32.@]
1404 static BOOL
GetFileNamePreview(LPVOID lpofn
,BOOL bSave
,BOOL bUnicode
)
1406 CHAR szFunctionName
[20];
1407 BOOL (*fnGetFileName
)(LPVOID
);
1411 FIXME("(%p,%d,%d), semi-stub!\n",lpofn
,bSave
,bUnicode
);
1413 lstrcpyA(szFunctionName
, (bSave
? "GetSaveFileName" : "GetOpenFileName"));
1414 lstrcatA(szFunctionName
, (bUnicode
? "W" : "A"));
1416 hComdlg32
= LoadLibraryA("COMDLG32.DLL");
1417 if (hComdlg32
== NULL
)
1420 fnGetFileName
= (LPVOID
)GetProcAddress(hComdlg32
, szFunctionName
);
1421 if (fnGetFileName
== NULL
)
1424 /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
1425 ret
= fnGetFileName(lpofn
);
1427 FreeLibrary(hComdlg32
);
1431 /***********************************************************************
1432 * GetOpenFileNamePreviewA [MSVFW32.@]
1434 BOOL WINAPI
GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1436 FIXME("(%p), semi-stub!\n", lpofn
);
1438 return GetFileNamePreview(lpofn
, FALSE
, FALSE
);
1441 /***********************************************************************
1442 * GetOpenFileNamePreviewW [MSVFW32.@]
1444 BOOL WINAPI
GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1446 FIXME("(%p), semi-stub!\n", lpofn
);
1448 return GetFileNamePreview(lpofn
, FALSE
, TRUE
);
1451 /***********************************************************************
1452 * GetSaveFileNamePreviewA [MSVFW32.@]
1454 BOOL WINAPI
GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn
)
1456 FIXME("(%p), semi-stub!\n", lpofn
);
1458 return GetFileNamePreview(lpofn
, TRUE
, FALSE
);
1461 /***********************************************************************
1462 * GetSaveFileNamePreviewW [MSVFW32.@]
1464 BOOL WINAPI
GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn
)
1466 FIXME("(%p), semi-stub!\n", lpofn
);
1468 return GetFileNamePreview(lpofn
, TRUE
, TRUE
);