ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

msvideo_main.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1998 Marcus Meissner
00003  * Copyright 2000 Bradley Baetz
00004  * Copyright 2003 Michael Günnewig
00005  * Copyright 2005 Dmitry Timoshkov
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * FIXME: This all assumes 32 bit codecs
00022  *      Win95 appears to prefer 32 bit codecs, even from 16 bit code.
00023  *      There is the ICOpenFunction16 to worry about still, though.
00024  *      
00025  * TODO
00026  *      - no thread safety
00027  */
00028 
00029 #include <stdarg.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "winreg.h"
00036 #include "winnls.h"
00037 #include "wingdi.h"
00038 #include "winuser.h"
00039 #include "commdlg.h"
00040 #include "vfw.h"
00041 #include "msvideo_private.h"
00042 #include "wine/debug.h"
00043 
00044 /* Drivers32 settings */
00045 #define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
00046 
00047 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
00048 
00049 static inline const char *wine_dbgstr_fcc( DWORD fcc )
00050 {
00051     return wine_dbg_sprintf("%c%c%c%c", 
00052                             LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)),
00053                             LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc)));
00054 }
00055 
00056 static WINE_HIC*        MSVIDEO_FirstHic /* = NULL */;
00057 
00058 typedef struct _reg_driver reg_driver;
00059 struct _reg_driver
00060 {
00061     DWORD       fccType;
00062     DWORD       fccHandler;
00063     DRIVERPROC  proc;
00064     LPWSTR      name;
00065     reg_driver* next;
00066 };
00067 
00068 static reg_driver* reg_driver_list = NULL;
00069 
00070 /* This one is a macro such that it works for both ASCII and Unicode */
00071 #define fourcc_to_string(str, fcc) do { \
00072     (str)[0] = LOBYTE(LOWORD(fcc)); \
00073     (str)[1] = HIBYTE(LOWORD(fcc)); \
00074     (str)[2] = LOBYTE(HIWORD(fcc)); \
00075     (str)[3] = HIBYTE(HIWORD(fcc)); \
00076     } while(0)
00077 
00078 HMODULE MSVFW32_hModule;
00079 
00080 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
00081 {
00082     TRACE("%p,%x,%p\n", hinst, reason, reserved);
00083 
00084     switch(reason)
00085     {
00086         case DLL_PROCESS_ATTACH:
00087             DisableThreadLibraryCalls(hinst);
00088             MSVFW32_hModule = hinst;
00089             break;
00090     }
00091     return TRUE;
00092 }
00093 
00094 /******************************************************************
00095  *      MSVIDEO_SendMessage
00096  *
00097  *
00098  */
00099 static LRESULT MSVIDEO_SendMessage(WINE_HIC* whic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2)
00100 {
00101     LRESULT     ret;
00102 
00103 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break
00104 
00105     switch (msg) {
00106         /* DRV_* */
00107         XX(DRV_LOAD);
00108         XX(DRV_ENABLE);
00109         XX(DRV_OPEN);
00110         XX(DRV_CLOSE);
00111         XX(DRV_DISABLE);
00112         XX(DRV_FREE);
00113         /* ICM_RESERVED+X */
00114         XX(ICM_ABOUT);
00115         XX(ICM_CONFIGURE);
00116         XX(ICM_GET);
00117         XX(ICM_GETINFO);
00118         XX(ICM_GETDEFAULTQUALITY);
00119         XX(ICM_GETQUALITY);
00120         XX(ICM_GETSTATE);
00121         XX(ICM_SETQUALITY);
00122         XX(ICM_SET);
00123         XX(ICM_SETSTATE);
00124         /* ICM_USER+X */
00125         XX(ICM_COMPRESS_FRAMES_INFO);
00126         XX(ICM_COMPRESS_GET_FORMAT);
00127         XX(ICM_COMPRESS_GET_SIZE);
00128         XX(ICM_COMPRESS_QUERY);
00129         XX(ICM_COMPRESS_BEGIN);
00130         XX(ICM_COMPRESS);
00131         XX(ICM_COMPRESS_END);
00132         XX(ICM_DECOMPRESS_GET_FORMAT);
00133         XX(ICM_DECOMPRESS_QUERY);
00134         XX(ICM_DECOMPRESS_BEGIN);
00135         XX(ICM_DECOMPRESS);
00136         XX(ICM_DECOMPRESS_END);
00137         XX(ICM_DECOMPRESS_SET_PALETTE);
00138         XX(ICM_DECOMPRESS_GET_PALETTE);
00139         XX(ICM_DRAW_QUERY);
00140         XX(ICM_DRAW_BEGIN);
00141         XX(ICM_DRAW_GET_PALETTE);
00142         XX(ICM_DRAW_START);
00143         XX(ICM_DRAW_STOP);
00144         XX(ICM_DRAW_END);
00145         XX(ICM_DRAW_GETTIME);
00146         XX(ICM_DRAW);
00147         XX(ICM_DRAW_WINDOW);
00148         XX(ICM_DRAW_SETTIME);
00149         XX(ICM_DRAW_REALIZE);
00150         XX(ICM_DRAW_FLUSH);
00151         XX(ICM_DRAW_RENDERBUFFER);
00152         XX(ICM_DRAW_START_PLAY);
00153         XX(ICM_DRAW_STOP_PLAY);
00154         XX(ICM_DRAW_SUGGESTFORMAT);
00155         XX(ICM_DRAW_CHANGEPALETTE);
00156         XX(ICM_GETBUFFERSWANTED);
00157         XX(ICM_GETDEFAULTKEYFRAMERATE);
00158         XX(ICM_DECOMPRESSEX_BEGIN);
00159         XX(ICM_DECOMPRESSEX_QUERY);
00160         XX(ICM_DECOMPRESSEX);
00161         XX(ICM_DECOMPRESSEX_END);
00162         XX(ICM_SET_STATUS_PROC);
00163     default:
00164         FIXME("(%p,0x%08x,0x%08lx,0x%08lx) unknown message\n",whic,msg,lParam1,lParam2);
00165     }
00166 
00167 #undef XX
00168 
00169     if (whic->driverproc) {
00170     /* dwDriverId parameter is the value returned by the DRV_OPEN */
00171         ret = whic->driverproc(whic->driverId, whic->hdrv, msg, lParam1, lParam2);
00172     } else {
00173         ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
00174     }
00175 
00176     TRACE(" -> 0x%08lx\n", ret);
00177     return ret;
00178 }
00179 
00180 static int compare_fourcc(DWORD fcc1, DWORD fcc2)
00181 {
00182   char fcc_str1[4];
00183   char fcc_str2[4];
00184   fourcc_to_string(fcc_str1, fcc1);
00185   fourcc_to_string(fcc_str2, fcc2);
00186   return strncasecmp(fcc_str1, fcc_str2, 4);
00187 }
00188 
00189 typedef BOOL (*enum_handler_t)(const char*, unsigned int, void*);
00190 
00191 static BOOL enum_drivers(DWORD fccType, enum_handler_t handler, void* param)
00192 {
00193     CHAR buf[2048], fccTypeStr[5], *s;
00194     DWORD i, cnt = 0, lRet;
00195     BOOL result = FALSE;
00196     HKEY hKey;
00197 
00198     fourcc_to_string(fccTypeStr, fccType);
00199     fccTypeStr[4] = '.';
00200 
00201     /* first, go through the registry entries */
00202     lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey);
00203     if (lRet == ERROR_SUCCESS) 
00204     {
00205         DWORD name, data, type;
00206         i = 0;
00207         for (;;)
00208     {
00209         name = 10;
00210         data = sizeof buf - name;
00211         lRet = RegEnumValueA(hKey, i++, buf, &name, 0, &type, (LPBYTE)(buf+name), &data);
00212         if (lRet == ERROR_NO_MORE_ITEMS) break;
00213         if (lRet != ERROR_SUCCESS) continue;
00214         if (name != 9 || strncasecmp(buf, fccTypeStr, 5)) continue;
00215         buf[name] = '=';
00216         if ((result = handler(buf, cnt++, param))) break;
00217     }
00218         RegCloseKey( hKey );
00219     }
00220     if (result) return result;
00221 
00222     /* if that didn't work, go through the values in system.ini */
00223     if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini")) 
00224     {
00225     for (s = buf; *s; s += strlen(s) + 1)
00226     {
00227             TRACE("got %s\n", s);
00228         if (strncasecmp(s, fccTypeStr, 5) || s[9] != '=') continue;
00229         if ((result = handler(s, cnt++, param))) break;
00230     }
00231     }
00232 
00233     return result;
00234 }
00235 
00236 /******************************************************************
00237  *      MSVIDEO_GetHicPtr
00238  *
00239  *
00240  */
00241 static WINE_HIC*   MSVIDEO_GetHicPtr(HIC hic)
00242 {
00243     WINE_HIC*   whic;
00244 
00245     for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next);
00246     return whic;
00247 }
00248 
00249 /***********************************************************************
00250  *      VideoForWindowsVersion      [MSVFW32.2]
00251  *      VideoForWindowsVersion      [MSVIDEO.2]
00252  * Returns the version in major.minor form.
00253  * In Windows95 this returns 0x040003b6 (4.950)
00254  */
00255 DWORD WINAPI VideoForWindowsVersion(void) 
00256 {
00257     return 0x040003B6; /* 4.950 */
00258 }
00259 
00260 static BOOL ICInfo_enum_handler(const char *drv, unsigned int nr, void *param)
00261 {
00262     ICINFO *lpicinfo = param;
00263     DWORD fccHandler = mmioStringToFOURCCA(drv + 5, 0);
00264 
00265     /* exact match of fccHandler or nth driver found */
00266     if ((lpicinfo->fccHandler != nr) && (lpicinfo->fccHandler != fccHandler))
00267     return FALSE;
00268 
00269     lpicinfo->fccHandler = fccHandler;
00270     lpicinfo->dwFlags = 0;
00271     lpicinfo->dwVersion = 0;
00272     lpicinfo->dwVersionICM = ICVERSION;
00273     lpicinfo->szName[0] = 0;
00274     lpicinfo->szDescription[0] = 0;
00275     MultiByteToWideChar(CP_ACP, 0, drv + 10, -1, lpicinfo->szDriver, 
00276             sizeof(lpicinfo->szDriver)/sizeof(WCHAR));
00277 
00278     return TRUE;
00279 }
00280 
00281 /***********************************************************************
00282  *      ICInfo              [MSVFW32.@]
00283  * Get information about an installable compressor. Return TRUE if there
00284  * is one.
00285  *
00286  * PARAMS
00287  *   fccType     [I] type of compressor (e.g. 'vidc')
00288  *   fccHandler  [I] real fcc for handler or <n>th compressor
00289  *   lpicinfo    [O] information about compressor
00290  */
00291 BOOL VFWAPI ICInfo( DWORD fccType, DWORD fccHandler, ICINFO *lpicinfo)
00292 {
00293     TRACE("(%s,%s/%08x,%p)\n",
00294           wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo);
00295 
00296     lpicinfo->fccType = fccType;
00297     lpicinfo->fccHandler = fccHandler;
00298     return enum_drivers(fccType, ICInfo_enum_handler, lpicinfo);
00299 }
00300 
00301 static DWORD IC_HandleRef = 1;
00302 
00303 /***********************************************************************
00304  *      ICInstall           [MSVFW32.@]
00305  */
00306 BOOL VFWAPI ICInstall(DWORD fccType, DWORD fccHandler, LPARAM lParam, LPSTR szDesc, UINT wFlags) 
00307 {
00308     reg_driver* driver;
00309     unsigned len;
00310 
00311     TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), (void*)lParam, szDesc, wFlags);
00312 
00313     /* Check if a driver is already registered */
00314     for (driver = reg_driver_list; driver; driver = driver->next)
00315     {
00316         if (!compare_fourcc(fccType, driver->fccType) &&
00317             !compare_fourcc(fccHandler, driver->fccHandler))
00318             break;
00319     }
00320     if (driver) return FALSE;
00321 
00322     /* Register the driver */
00323     driver = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(reg_driver));
00324     if (!driver) goto oom;
00325     driver->fccType = fccType;
00326     driver->fccHandler = fccHandler;
00327 
00328     switch(wFlags)
00329     {
00330     case ICINSTALL_FUNCTION:
00331         driver->proc = (DRIVERPROC)lParam;
00332     driver->name = NULL;
00333         break;
00334     case ICINSTALL_DRIVER:
00335     driver->proc = NULL;
00336         len = MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, NULL, 0);
00337         driver->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00338         if (!driver->name) goto oom;
00339         MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, driver->name, len);
00340     break;
00341     default:
00342     ERR("Invalid flags!\n");
00343     HeapFree(GetProcessHeap(), 0, driver);
00344     return FALSE;
00345    }
00346 
00347    /* Insert our driver in the list*/
00348    driver->next = reg_driver_list;
00349    reg_driver_list = driver;
00350     
00351    return TRUE;
00352 oom:
00353    HeapFree(GetProcessHeap(), 0, driver);
00354    return FALSE;
00355 }
00356 
00357 /***********************************************************************
00358  *      ICRemove            [MSVFW32.@]
00359  */
00360 BOOL VFWAPI ICRemove(DWORD fccType, DWORD fccHandler, UINT wFlags) 
00361 {
00362     reg_driver** pdriver;
00363     reg_driver*  drv;
00364 
00365     TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wFlags);
00366 
00367     /* Check if a driver is already registered */
00368     for (pdriver = &reg_driver_list; *pdriver; pdriver = &(*pdriver)->next)
00369     {
00370         if (!compare_fourcc(fccType, (*pdriver)->fccType) &&
00371             !compare_fourcc(fccHandler, (*pdriver)->fccHandler))
00372             break;
00373     }
00374     if (!*pdriver)
00375         return FALSE;
00376 
00377     /* Remove the driver from the list */
00378     drv = *pdriver;
00379     *pdriver = (*pdriver)->next;
00380     HeapFree(GetProcessHeap(), 0, drv->name);
00381     HeapFree(GetProcessHeap(), 0, drv);
00382     
00383     return TRUE;  
00384 }
00385 
00386 
00387 /***********************************************************************
00388  *      ICOpen              [MSVFW32.@]
00389  * Opens an installable compressor. Return special handle.
00390  */
00391 HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) 
00392 {
00393     WCHAR       codecname[10];
00394     ICOPEN      icopen;
00395     HDRVR       hdrv;
00396     WINE_HIC*           whic;
00397     static const WCHAR  drv32W[] = {'d','r','i','v','e','r','s','3','2','\0'};
00398     reg_driver*         driver;
00399 
00400     TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode);
00401 
00402     /* Check if there is a registered driver that matches */
00403     driver = reg_driver_list;
00404     while(driver)
00405         if (!compare_fourcc(fccType, driver->fccType) &&
00406             !compare_fourcc(fccHandler, driver->fccHandler))
00407         break;
00408         else
00409             driver = driver->next;
00410 
00411     if (driver && driver->proc)
00412     /* The driver has been registered at runtime with its driverproc */
00413         return ICOpenFunction(fccType, fccHandler, wMode, driver->proc);
00414   
00415     /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
00416      * same layout as ICOPEN
00417      */
00418     icopen.dwSize       = sizeof(ICOPEN);
00419     icopen.fccType      = fccType;
00420     icopen.fccHandler           = fccHandler;
00421     icopen.dwVersion            = 0x00001000; /* FIXME */
00422     icopen.dwFlags      = wMode;
00423     icopen.dwError              = 0;
00424     icopen.pV1Reserved          = NULL;
00425     icopen.pV2Reserved          = NULL;
00426     icopen.dnDevNode            = 0; /* FIXME */
00427     
00428     if (!driver) {
00429         /* The driver is registered in the registry */
00430     fourcc_to_string(codecname, fccType);
00431         codecname[4] = '.';
00432     fourcc_to_string(codecname + 5, fccHandler);
00433         codecname[9] = '\0';
00434 
00435         hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen);
00436         if (!hdrv) 
00437             return 0;
00438     } else {
00439         /* The driver has been registered at runtime with its name */
00440         hdrv = OpenDriver(driver->name, NULL, (LPARAM)&icopen);
00441         if (!hdrv) 
00442             return 0; 
00443     }
00444 
00445     whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
00446     if (!whic)
00447     {
00448         CloseDriver(hdrv, 0, 0);
00449         return FALSE;
00450     }
00451     whic->hdrv          = hdrv;
00452     whic->driverproc    = NULL;
00453     whic->type          = fccType;
00454     whic->handler       = fccHandler;
00455     while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++;
00456     whic->hic           = (HIC)(ULONG_PTR)IC_HandleRef++;
00457     whic->next          = MSVIDEO_FirstHic;
00458     MSVIDEO_FirstHic = whic;
00459 
00460     TRACE("=> %p\n", whic->hic);
00461     return whic->hic;
00462 }
00463 
00464 /***********************************************************************
00465  *      ICOpenFunction          [MSVFW32.@]
00466  */
00467 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, DRIVERPROC lpfnHandler)
00468 {
00469     ICOPEN      icopen;
00470     WINE_HIC*   whic;
00471 
00472     TRACE("(%s,%s,%d,%p)\n",
00473           wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler);
00474 
00475     icopen.dwSize       = sizeof(ICOPEN);
00476     icopen.fccType      = fccType;
00477     icopen.fccHandler           = fccHandler;
00478     icopen.dwVersion            = ICVERSION;
00479     icopen.dwFlags      = wMode;
00480     icopen.dwError              = 0;
00481     icopen.pV1Reserved          = NULL;
00482     icopen.pV2Reserved          = NULL;
00483     icopen.dnDevNode            = 0; /* FIXME */
00484 
00485     whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
00486     if (!whic) return 0;
00487 
00488     whic->driverproc   = lpfnHandler;
00489     while (MSVIDEO_GetHicPtr((HIC)(ULONG_PTR)IC_HandleRef) != NULL) IC_HandleRef++;
00490     whic->hic          = (HIC)(ULONG_PTR)IC_HandleRef++;
00491     whic->next         = MSVIDEO_FirstHic;
00492     MSVIDEO_FirstHic = whic;
00493 
00494     /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
00495     /* What if the function is used more than once? */
00496 
00497     if (MSVIDEO_SendMessage(whic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) 
00498     {
00499         WARN("DRV_LOAD failed for hic %p\n", whic->hic);
00500         MSVIDEO_FirstHic = whic->next;
00501         HeapFree(GetProcessHeap(), 0, whic);
00502         return 0;
00503     }
00504     /* return value is not checked */
00505     MSVIDEO_SendMessage(whic, DRV_ENABLE, 0L, 0L);
00506 
00507     whic->driverId = (DWORD)MSVIDEO_SendMessage(whic, DRV_OPEN, 0, (DWORD_PTR)&icopen);
00508     /* FIXME: What should we put here? */
00509     whic->hdrv = NULL;
00510     
00511     if (whic->driverId == 0) 
00512     {
00513         WARN("DRV_OPEN failed for hic %p\n", whic->hic);
00514         MSVIDEO_FirstHic = whic->next;
00515         HeapFree(GetProcessHeap(), 0, whic);
00516         return 0;
00517     }
00518 
00519     TRACE("=> %p\n", whic->hic);
00520     return whic->hic;
00521 }
00522 
00523 /***********************************************************************
00524  *      ICGetInfo           [MSVFW32.@]
00525  */
00526 LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb) 
00527 {
00528     LRESULT ret;
00529     WINE_HIC*   whic = MSVIDEO_GetHicPtr(hic);
00530 
00531     TRACE("(%p,%p,%d)\n", hic, picinfo, cb);
00532 
00533     whic = MSVIDEO_GetHicPtr(hic);
00534     if (!whic) return ICERR_BADHANDLE;
00535     if (!picinfo) return MMSYSERR_INVALPARAM;
00536 
00537     /* (WS) The field szDriver should be initialized because the driver 
00538      * is not obliged and often will not do it. Some applications, like
00539      * VirtualDub, rely on this field and will occasionally crash if it
00540      * goes uninitialized.
00541      */
00542     if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0';
00543 
00544     ret = ICSendMessage(hic, ICM_GETINFO, (DWORD_PTR)picinfo, cb);
00545 
00546     /* (WS) When szDriver was not supplied by the driver itself, apparently 
00547      * Windows will set its value equal to the driver file name. This can
00548      * be obtained from the registry as we do here.
00549      */
00550     if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0)
00551     {
00552         ICINFO  ii;
00553 
00554         memset(&ii, 0, sizeof(ii));
00555         ii.dwSize = sizeof(ii);
00556         ICInfo(picinfo->fccType, picinfo->fccHandler, &ii);
00557         lstrcpyW(picinfo->szDriver, ii.szDriver);
00558     }
00559 
00560     TRACE(" -> 0x%08lx\n", ret);
00561     return ret;
00562 }
00563 
00564 typedef struct {
00565     DWORD fccType;
00566     DWORD fccHandler;
00567     LPBITMAPINFOHEADER lpbiIn;
00568     LPBITMAPINFOHEADER lpbiOut;
00569     WORD wMode;
00570     DWORD querymsg;
00571     HIC hic;
00572 } driver_info_t;
00573 
00574 static HIC try_driver(driver_info_t *info)
00575 {
00576     HIC   hic;
00577 
00578     if ((hic = ICOpen(info->fccType, info->fccHandler, info->wMode))) 
00579     {
00580     if (!ICSendMessage(hic, info->querymsg, (DWORD_PTR)info->lpbiIn, (DWORD_PTR)info->lpbiOut))
00581         return hic;
00582     ICClose(hic);
00583     }
00584     return 0;
00585 }
00586 
00587 static BOOL ICLocate_enum_handler(const char *drv, unsigned int nr, void *param)
00588 {
00589     driver_info_t *info = param;
00590     info->fccHandler = mmioStringToFOURCCA(drv + 5, 0);
00591     info->hic = try_driver(info);
00592     return info->hic != 0;
00593 }
00594 
00595 /***********************************************************************
00596  *      ICLocate            [MSVFW32.@]
00597  */
00598 HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
00599                     LPBITMAPINFOHEADER lpbiOut, WORD wMode)
00600 {
00601     driver_info_t info;
00602 
00603     TRACE("(%s,%s,%p,%p,0x%04x)\n", 
00604           wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
00605 
00606     info.fccType = fccType;
00607     info.fccHandler = fccHandler;
00608     info.lpbiIn = lpbiIn;
00609     info.lpbiOut = lpbiOut;
00610     info.wMode = wMode;
00611 
00612     switch (wMode) 
00613     {
00614     case ICMODE_FASTCOMPRESS:
00615     case ICMODE_COMPRESS:
00616         info.querymsg = ICM_COMPRESS_QUERY;
00617         break;
00618     case ICMODE_FASTDECOMPRESS:
00619     case ICMODE_DECOMPRESS:
00620         info.querymsg = ICM_DECOMPRESS_QUERY;
00621         break;
00622     case ICMODE_DRAW:
00623         info.querymsg = ICM_DRAW_QUERY;
00624         break;
00625     default:
00626         WARN("Unknown mode (%d)\n", wMode);
00627         return 0;
00628     }
00629 
00630     /* Easy case: handler/type match, we just fire a query and return */
00631     info.hic = try_driver(&info);
00632     /* If it didn't work, try each driver in turn. 32 bit codecs only. */
00633     /* FIXME: Move this to an init routine? */
00634     if (!info.hic) enum_drivers(fccType, ICLocate_enum_handler, &info);
00635 
00636     if (info.hic) 
00637     {
00638         TRACE("=> %p\n", info.hic);
00639     return info.hic;
00640     }
00641 
00642     if (fccType == streamtypeVIDEO) 
00643         return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode);
00644     
00645     WARN("(%s,%s,%p,%p,0x%04x) not found!\n",
00646          wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode);
00647     return 0;
00648 }
00649 
00650 /***********************************************************************
00651  *      ICGetDisplayFormat          [MSVFW32.@]
00652  */
00653 HIC VFWAPI ICGetDisplayFormat(
00654     HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
00655     INT depth,INT dx,INT dy)
00656 {
00657     HIC tmphic = hic;
00658 
00659     TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);
00660 
00661     if (!tmphic) {
00662         tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
00663         if (!tmphic)
00664             return tmphic;
00665     }
00666     if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
00667         dy = dx = 0; /* no resize needed */
00668 
00669     /* Can we decompress it ? */
00670     if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
00671         goto errout; /* no, sorry */
00672 
00673     ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut);
00674 
00675     if (lpbiOut->biCompression != 0) {
00676            FIXME("Ooch, how come decompressor outputs compressed data (%d)??\n",
00677              lpbiOut->biCompression);
00678     }
00679     if (lpbiOut->biSize < sizeof(*lpbiOut)) {
00680            FIXME("Ooch, size of output BIH is too small (%d)\n",
00681              lpbiOut->biSize);
00682        lpbiOut->biSize = sizeof(*lpbiOut);
00683     }
00684     if (!depth) {
00685         HDC hdc;
00686 
00687         hdc = GetDC(0);
00688         depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
00689         ReleaseDC(0,hdc);
00690         if (depth==15)  depth = 16;
00691         if (depth<8)    depth =  8;
00692     }
00693     if (lpbiIn->biBitCount == 8)
00694         depth = 8;
00695 
00696     TRACE("=> %p\n", tmphic);
00697     return tmphic;
00698 errout:
00699     if (hic!=tmphic)
00700         ICClose(tmphic);
00701 
00702     TRACE("=> 0\n");
00703     return 0;
00704 }
00705 
00706 /***********************************************************************
00707  *      ICCompress          [MSVFW32.@]
00708  */
00709 DWORD VFWAPIV
00710 ICCompress(
00711     HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
00712     LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
00713     LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
00714     LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
00715 {
00716     ICCOMPRESS  iccmp;
00717 
00718     TRACE("(%p,%d,%p,%p,%p,%p,...)\n",hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
00719 
00720     iccmp.dwFlags       = dwFlags;
00721 
00722     iccmp.lpbiOutput    = lpbiOutput;
00723     iccmp.lpOutput      = lpData;
00724     iccmp.lpbiInput     = lpbiInput;
00725     iccmp.lpInput       = lpBits;
00726 
00727     iccmp.lpckid        = lpckid;
00728     iccmp.lpdwFlags     = lpdwFlags;
00729     iccmp.lFrameNum     = lFrameNum;
00730     iccmp.dwFrameSize   = dwFrameSize;
00731     iccmp.dwQuality     = dwQuality;
00732     iccmp.lpbiPrev      = lpbiPrev;
00733     iccmp.lpPrev        = lpPrev;
00734     return ICSendMessage(hic,ICM_COMPRESS,(DWORD_PTR)&iccmp,sizeof(iccmp));
00735 }
00736 
00737 /***********************************************************************
00738  *      ICDecompress            [MSVFW32.@]
00739  */
00740 DWORD VFWAPIV  ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
00741                 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
00742 {
00743     ICDECOMPRESS    icd;
00744     DWORD ret;
00745 
00746     TRACE("(%p,%d,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
00747 
00748     icd.dwFlags = dwFlags;
00749     icd.lpbiInput   = lpbiFormat;
00750     icd.lpInput = lpData;
00751 
00752     icd.lpbiOutput  = lpbi;
00753     icd.lpOutput    = lpBits;
00754     icd.ckid    = 0;
00755     ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD_PTR)&icd,sizeof(ICDECOMPRESS));
00756 
00757     TRACE("-> %d\n",ret);
00758 
00759     return ret;
00760 }
00761 
00762 
00763 struct choose_compressor
00764 {
00765     UINT flags;
00766     LPCSTR title;
00767     COMPVARS cv;
00768 };
00769 
00770 struct codec_info
00771 {
00772     HIC hic;
00773     ICINFO icinfo;
00774 };
00775 
00776 static BOOL enum_compressors(HWND list, COMPVARS *pcv, BOOL enum_all)
00777 {
00778     UINT id, total = 0;
00779     ICINFO icinfo;
00780 
00781     id = 0;
00782 
00783     while (ICInfo(pcv->fccType, id, &icinfo))
00784     {
00785         struct codec_info *ic;
00786         DWORD idx;
00787         HIC hic;
00788 
00789         id++;
00790 
00791         hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
00792 
00793         if (hic)
00794         {
00795             /* for unknown reason fccHandler reported by the driver
00796              * doesn't always work, use the one returned by ICInfo instead.
00797              */
00798             DWORD fccHandler = icinfo.fccHandler;
00799 
00800             if (!enum_all && pcv->lpbiIn)
00801             {
00802                 if (ICCompressQuery(hic, pcv->lpbiIn, NULL) != ICERR_OK)
00803                 {
00804                     TRACE("fccHandler %s doesn't support input DIB format %d\n",
00805                           wine_dbgstr_fcc(icinfo.fccHandler), pcv->lpbiIn->bmiHeader.biCompression);
00806                     ICClose(hic);
00807                     continue;
00808                 }
00809             }
00810 
00811             ICGetInfo(hic, &icinfo, sizeof(icinfo));
00812             icinfo.fccHandler = fccHandler;
00813 
00814             idx = SendMessageW(list, CB_ADDSTRING, 0, (LPARAM)icinfo.szDescription);
00815 
00816             ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info));
00817             ic->icinfo = icinfo;
00818             ic->hic = hic;
00819             SendMessageW(list, CB_SETITEMDATA, idx, (LPARAM)ic);
00820         }
00821         total++;
00822     }
00823 
00824     return total != 0;
00825 }
00826 
00827 static INT_PTR CALLBACK icm_choose_compressor_dlgproc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
00828 {
00829     switch (msg)
00830     {
00831     case WM_INITDIALOG:
00832     {
00833         struct codec_info *ic;
00834         WCHAR buf[128];
00835         struct choose_compressor *choose_comp = (struct choose_compressor *)lparam;
00836 
00837         SetWindowLongPtrW(hdlg, DWLP_USER, lparam);
00838 
00839         /* FIXME */
00840         choose_comp->flags &= ~(ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME);
00841 
00842         if (choose_comp->title)
00843             SetWindowTextA(hdlg, choose_comp->title);
00844 
00845         if (!(choose_comp->flags & ICMF_CHOOSE_DATARATE))
00846         {
00847             ShowWindow(GetDlgItem(hdlg, IDC_DATARATE_CHECKBOX), SW_HIDE);
00848             ShowWindow(GetDlgItem(hdlg, IDC_DATARATE), SW_HIDE);
00849             ShowWindow(GetDlgItem(hdlg, IDC_DATARATE_KB), SW_HIDE);
00850         }
00851 
00852         if (!(choose_comp->flags & ICMF_CHOOSE_KEYFRAME))
00853         {
00854             ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME_CHECKBOX), SW_HIDE);
00855             ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME), SW_HIDE);
00856             ShowWindow(GetDlgItem(hdlg, IDC_KEYFRAME_FRAMES), SW_HIDE);
00857         }
00858 
00859         /* FIXME */
00860         EnableWindow(GetDlgItem(hdlg, IDC_QUALITY_SCROLL), FALSE);
00861         EnableWindow(GetDlgItem(hdlg, IDC_QUALITY_TXT), FALSE);
00862 
00863         /*if (!(choose_comp->flags & ICMF_CHOOSE_PREVIEW))
00864             ShowWindow(GetDlgItem(hdlg, IDC_PREVIEW), SW_HIDE);*/
00865 
00866         LoadStringW(MSVFW32_hModule, IDS_FULLFRAMES, buf, 128);
00867         SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_ADDSTRING, 0, (LPARAM)buf);
00868 
00869         ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info));
00870         ic->icinfo.fccType = streamtypeVIDEO;
00871         ic->icinfo.fccHandler = comptypeDIB;
00872         ic->hic = 0;
00873         SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_SETITEMDATA, 0, (LPARAM)ic);
00874 
00875         enum_compressors(GetDlgItem(hdlg, IDC_COMP_LIST), &choose_comp->cv, choose_comp->flags & ICMF_CHOOSE_ALLCOMPRESSORS);
00876 
00877         SendDlgItemMessageW(hdlg, IDC_COMP_LIST, CB_SETCURSEL, 0, 0);
00878         SetFocus(GetDlgItem(hdlg, IDC_COMP_LIST));
00879 
00880         SetWindowLongPtrW(hdlg, DWLP_USER, (ULONG_PTR)choose_comp);
00881         break;
00882     }
00883 
00884     case WM_COMMAND:
00885         switch (LOWORD(wparam))
00886         {
00887         case IDC_COMP_LIST:
00888         {
00889             INT cur_sel;
00890             struct codec_info *ic;
00891             BOOL can_configure = FALSE, can_about = FALSE;
00892             struct choose_compressor *choose_comp;
00893 
00894             if (HIWORD(wparam) != CBN_SELCHANGE && HIWORD(wparam) != CBN_SETFOCUS)
00895                 break;
00896 
00897             choose_comp = (struct choose_compressor *)GetWindowLongPtrW(hdlg, DWLP_USER);
00898 
00899             cur_sel = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
00900 
00901             ic = (struct codec_info *)SendMessageW((HWND)lparam, CB_GETITEMDATA, cur_sel, 0);
00902             if (ic && ic->hic)
00903             {
00904                 if (ICQueryConfigure(ic->hic) == DRVCNF_OK)
00905                     can_configure = TRUE;
00906                 if (ICQueryAbout(ic->hic) == DRVCNF_OK)
00907                     can_about = TRUE;
00908             }
00909             EnableWindow(GetDlgItem(hdlg, IDC_CONFIGURE), can_configure);
00910             EnableWindow(GetDlgItem(hdlg, IDC_ABOUT), can_about);
00911 
00912             if (choose_comp->flags & ICMF_CHOOSE_DATARATE)
00913             {
00914                 /* FIXME */
00915             }
00916             if (choose_comp->flags & ICMF_CHOOSE_KEYFRAME)
00917             {
00918                 /* FIXME */
00919             }
00920 
00921             break;
00922         }
00923 
00924         case IDC_CONFIGURE:
00925         case IDC_ABOUT:
00926         {
00927             HWND list = GetDlgItem(hdlg, IDC_COMP_LIST);
00928             INT cur_sel;
00929             struct codec_info *ic;
00930 
00931             if (HIWORD(wparam) != BN_CLICKED)
00932                 break;
00933 
00934             cur_sel = SendMessageW(list, CB_GETCURSEL, 0, 0);
00935 
00936             ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, cur_sel, 0);
00937             if (ic && ic->hic)
00938             {
00939                 if (LOWORD(wparam) == IDC_CONFIGURE)
00940                     ICConfigure(ic->hic, hdlg);
00941                 else
00942                     ICAbout(ic->hic, hdlg);
00943             }
00944 
00945             break;
00946         }
00947 
00948         case IDOK:
00949         {
00950             HWND list = GetDlgItem(hdlg, IDC_COMP_LIST);
00951             INT cur_sel;
00952             struct codec_info *ic;
00953 
00954             if (HIWORD(wparam) != BN_CLICKED)
00955                 break;
00956 
00957             cur_sel = SendMessageW(list, CB_GETCURSEL, 0, 0);
00958             ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, cur_sel, 0);
00959             if (ic)
00960             {
00961                 struct choose_compressor *choose_comp = (struct choose_compressor *)GetWindowLongPtrW(hdlg, DWLP_USER);
00962 
00963                 choose_comp->cv.hic = ic->hic;
00964                 choose_comp->cv.fccType = ic->icinfo.fccType;
00965                 choose_comp->cv.fccHandler = ic->icinfo.fccHandler;
00966                 /* FIXME: fill everything else */
00967 
00968                 /* prevent closing the codec handle below */
00969                 ic->hic = 0;
00970             }
00971         }
00972         /* fall through */
00973         case IDCANCEL:
00974         {
00975             HWND list = GetDlgItem(hdlg, IDC_COMP_LIST);
00976             INT idx = 0;
00977 
00978             if (HIWORD(wparam) != BN_CLICKED)
00979                 break;
00980 
00981             while (1)
00982             {
00983                 struct codec_info *ic;
00984     
00985                 ic = (struct codec_info *)SendMessageW(list, CB_GETITEMDATA, idx++, 0);
00986 
00987                 if (!ic || (LONG_PTR)ic == CB_ERR) break;
00988 
00989                 if (ic->hic) ICClose(ic->hic);
00990                 HeapFree(GetProcessHeap(), 0, ic);
00991             }
00992 
00993             EndDialog(hdlg, LOWORD(wparam) == IDOK);
00994             break;
00995         }
00996 
00997         default:
00998             break;
00999         }
01000         break;
01001 
01002     default:
01003         break;
01004     }
01005 
01006     return FALSE;
01007 }
01008 
01009 /***********************************************************************
01010  *      ICCompressorChoose   [MSVFW32.@]
01011  */
01012 BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn,
01013                                LPVOID lpData, PCOMPVARS pc, LPSTR lpszTitle)
01014 {
01015     struct choose_compressor choose_comp;
01016     BOOL ret;
01017 
01018     TRACE("(%p,%08x,%p,%p,%p,%s)\n", hwnd, uiFlags, pvIn, lpData, pc, lpszTitle);
01019 
01020     if (!pc || pc->cbSize != sizeof(COMPVARS))
01021         return FALSE;
01022 
01023     if (!(pc->dwFlags & ICMF_COMPVARS_VALID))
01024     {
01025         pc->dwFlags   = 0;
01026         pc->fccType   = pc->fccHandler = 0;
01027         pc->hic       = NULL;
01028         pc->lpbiIn    = NULL;
01029         pc->lpbiOut   = NULL;
01030         pc->lpBitsOut = pc->lpBitsPrev = pc->lpState = NULL;
01031         pc->lQ        = ICQUALITY_DEFAULT;
01032         pc->lKey      = -1;
01033         pc->lDataRate = 300; /* kB */
01034         pc->lpState   = NULL;
01035         pc->cbState   = 0;
01036     }
01037     if (pc->fccType == 0)
01038         pc->fccType = ICTYPE_VIDEO;
01039 
01040     choose_comp.cv = *pc;
01041     choose_comp.flags = uiFlags;
01042     choose_comp.title = lpszTitle;
01043 
01044     ret = DialogBoxParamW(MSVFW32_hModule, MAKEINTRESOURCEW(ICM_CHOOSE_COMPRESSOR), hwnd,
01045                           icm_choose_compressor_dlgproc, (LPARAM)&choose_comp);
01046 
01047     if (ret)
01048     {
01049         *pc = choose_comp.cv;
01050         pc->dwFlags |= ICMF_COMPVARS_VALID;
01051     }
01052 
01053     return ret;
01054 }
01055 
01056 
01057 /***********************************************************************
01058  *      ICCompressorFree   [MSVFW32.@]
01059  */
01060 void VFWAPI ICCompressorFree(PCOMPVARS pc)
01061 {
01062   TRACE("(%p)\n",pc);
01063 
01064   if (pc != NULL && pc->cbSize == sizeof(COMPVARS)) {
01065     if (pc->hic != NULL) {
01066       ICClose(pc->hic);
01067       pc->hic = NULL;
01068     }
01069     HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01070     pc->lpbiIn = NULL;
01071     HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
01072     pc->lpBitsOut = NULL;
01073     HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
01074     pc->lpBitsPrev = NULL;
01075     HeapFree(GetProcessHeap(), 0, pc->lpState);
01076     pc->lpState = NULL;
01077     pc->dwFlags = 0;
01078   }
01079 }
01080 
01081 /***********************************************************************
01082  *      ICSendMessage           [MSVFW32.@]
01083  */
01084 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2) 
01085 {
01086     WINE_HIC*   whic = MSVIDEO_GetHicPtr(hic);
01087 
01088     if (!whic) return ICERR_BADHANDLE;
01089     return MSVIDEO_SendMessage(whic, msg, lParam1, lParam2);
01090 }
01091 
01092 /***********************************************************************
01093  *      ICDrawBegin     [MSVFW32.@]
01094  */
01095 DWORD VFWAPIV ICDrawBegin(
01096     HIC                hic,     /* [in] */
01097     DWORD              dwFlags, /* [in] flags */
01098     HPALETTE           hpal,    /* [in] palette to draw with */
01099     HWND               hwnd,    /* [in] window to draw to */
01100     HDC                hdc,     /* [in] HDC to draw to */
01101     INT                xDst,    /* [in] destination rectangle */
01102     INT                yDst,    /* [in] */
01103     INT                dxDst,   /* [in] */
01104     INT                dyDst,   /* [in] */
01105     LPBITMAPINFOHEADER lpbi,    /* [in] format of frame to draw */
01106     INT                xSrc,    /* [in] source rectangle */
01107     INT                ySrc,    /* [in] */
01108     INT                dxSrc,   /* [in] */
01109     INT                dySrc,   /* [in] */
01110     DWORD              dwRate,  /* [in] frames/second = (dwRate/dwScale) */
01111     DWORD              dwScale) /* [in] */
01112 {
01113 
01114     ICDRAWBEGIN icdb;
01115 
01116     TRACE("(%p,%d,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n",
01117           hic, dwFlags, hpal, hwnd, hdc, xDst, yDst, dxDst, dyDst,
01118           lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
01119 
01120     icdb.dwFlags = dwFlags;
01121     icdb.hpal = hpal;
01122     icdb.hwnd = hwnd;
01123     icdb.hdc = hdc;
01124     icdb.xDst = xDst;
01125     icdb.yDst = yDst;
01126     icdb.dxDst = dxDst;
01127     icdb.dyDst = dyDst;
01128     icdb.lpbi = lpbi;
01129     icdb.xSrc = xSrc;
01130     icdb.ySrc = ySrc;
01131     icdb.dxSrc = dxSrc;
01132     icdb.dySrc = dySrc;
01133     icdb.dwRate = dwRate;
01134     icdb.dwScale = dwScale;
01135     return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD_PTR)&icdb,sizeof(icdb));
01136 }
01137 
01138 /***********************************************************************
01139  *      ICDraw          [MSVFW32.@]
01140  */
01141 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
01142     ICDRAW  icd;
01143 
01144     TRACE("(%p,%d,%p,%p,%d,%d)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime);
01145 
01146     icd.dwFlags = dwFlags;
01147     icd.lpFormat = lpFormat;
01148     icd.lpData = lpData;
01149     icd.cbData = cbData;
01150     icd.lTime = lTime;
01151 
01152     return ICSendMessage(hic,ICM_DRAW,(DWORD_PTR)&icd,sizeof(icd));
01153 }
01154 
01155 /***********************************************************************
01156  *      ICClose         [MSVFW32.@]
01157  */
01158 LRESULT WINAPI ICClose(HIC hic)
01159 {
01160     WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
01161     WINE_HIC** p;
01162 
01163     TRACE("(%p)\n",hic);
01164 
01165     if (!whic) return ICERR_BADHANDLE;
01166 
01167     if (whic->driverproc) 
01168     {
01169         MSVIDEO_SendMessage(whic, DRV_CLOSE, 0, 0);
01170         MSVIDEO_SendMessage(whic, DRV_DISABLE, 0, 0);
01171         MSVIDEO_SendMessage(whic, DRV_FREE, 0, 0);
01172     }
01173     else
01174     {
01175         CloseDriver(whic->hdrv, 0, 0);
01176     }
01177 
01178     /* remove whic from list */
01179     for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next))
01180     {
01181         if ((*p) == whic)
01182         {
01183             *p = whic->next;
01184             break;
01185         }
01186     }
01187 
01188     HeapFree(GetProcessHeap(), 0, whic);
01189     return 0;
01190 }
01191 
01192 
01193 
01194 /***********************************************************************
01195  *      ICImageCompress [MSVFW32.@]
01196  */
01197 HANDLE VFWAPI ICImageCompress(
01198     HIC hic, UINT uiFlags,
01199     LPBITMAPINFO lpbiIn, LPVOID lpBits,
01200     LPBITMAPINFO lpbiOut, LONG lQuality,
01201     LONG* plSize)
01202 {
01203     FIXME("(%p,%08x,%p,%p,%p,%d,%p)\n",
01204         hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
01205 
01206     return NULL;
01207 }
01208 
01209 /***********************************************************************
01210  *      ICImageDecompress   [MSVFW32.@]
01211  */
01212 
01213 HANDLE VFWAPI ICImageDecompress(
01214     HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
01215     LPVOID lpBits, LPBITMAPINFO lpbiOut)
01216 {
01217     HGLOBAL hMem = NULL;
01218     BYTE*   pMem = NULL;
01219     BOOL    bReleaseIC = FALSE;
01220     BYTE*   pHdr = NULL;
01221     ULONG   cbHdr = 0;
01222     BOOL    bSucceeded = FALSE;
01223     BOOL    bInDecompress = FALSE;
01224     DWORD   biSizeImage;
01225 
01226     TRACE("(%p,%08x,%p,%p,%p)\n",
01227         hic, uiFlags, lpbiIn, lpBits, lpbiOut);
01228 
01229     if ( hic == NULL )
01230     {
01231         hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
01232         if ( hic == NULL )
01233         {
01234             WARN("no handler\n" );
01235             goto err;
01236         }
01237         bReleaseIC = TRUE;
01238     }
01239     if ( uiFlags != 0 )
01240     {
01241         FIXME( "unknown flag %08x\n", uiFlags );
01242         goto err;
01243     }
01244     if ( lpbiIn == NULL || lpBits == NULL )
01245     {
01246         WARN("invalid argument\n");
01247         goto err;
01248     }
01249 
01250     if ( lpbiOut != NULL )
01251     {
01252         if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
01253             goto err;
01254         cbHdr = sizeof(BITMAPINFOHEADER);
01255         if ( lpbiOut->bmiHeader.biCompression == 3 )
01256             cbHdr += sizeof(DWORD)*3;
01257         else
01258         if ( lpbiOut->bmiHeader.biBitCount <= 8 )
01259         {
01260             if ( lpbiOut->bmiHeader.biClrUsed == 0 )
01261                 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
01262             else
01263                 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
01264         }
01265     }
01266     else
01267     {
01268         TRACE( "get format\n" );
01269 
01270         cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
01271         if ( cbHdr < sizeof(BITMAPINFOHEADER) )
01272             goto err;
01273         pHdr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,cbHdr+sizeof(RGBQUAD)*256);
01274         if ( pHdr == NULL )
01275             goto err;
01276         if ( ICDecompressGetFormat( hic, lpbiIn, pHdr ) != ICERR_OK )
01277             goto err;
01278         lpbiOut = (BITMAPINFO*)pHdr;
01279         if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
01280              ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
01281              lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
01282         {
01283             if ( lpbiIn->bmiHeader.biClrUsed == 0 )
01284                 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
01285             else
01286                 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
01287         }
01288         if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
01289              lpbiOut->bmiHeader.biClrUsed == 0 )
01290             lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
01291 
01292         lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01293         cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
01294     }
01295 
01296     biSizeImage = lpbiOut->bmiHeader.biSizeImage;
01297     if ( biSizeImage == 0 )
01298         biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight);
01299 
01300     TRACE( "call ICDecompressBegin\n" );
01301 
01302     if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
01303         goto err;
01304     bInDecompress = TRUE;
01305 
01306     TRACE( "cbHdr %d, biSizeImage %d\n", cbHdr, biSizeImage );
01307 
01308     hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
01309     if ( hMem == NULL )
01310     {
01311         WARN( "out of memory\n" );
01312         goto err;
01313     }
01314     pMem = GlobalLock( hMem );
01315     if ( pMem == NULL )
01316         goto err;
01317     memcpy( pMem, lpbiOut, cbHdr );
01318 
01319     TRACE( "call ICDecompress\n" );
01320     if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
01321         goto err;
01322 
01323     bSucceeded = TRUE;
01324 err:
01325     if ( bInDecompress )
01326         ICDecompressEnd( hic );
01327     if ( bReleaseIC )
01328         ICClose(hic);
01329         HeapFree(GetProcessHeap(),0,pHdr);
01330     if ( pMem != NULL )
01331         GlobalUnlock( hMem );
01332     if ( !bSucceeded && hMem != NULL )
01333     {
01334         GlobalFree(hMem); hMem = NULL;
01335     }
01336 
01337     return hMem;
01338 }
01339 
01340 /***********************************************************************
01341  *      ICSeqCompressFrame   [MSVFW32.@]
01342  */
01343 LPVOID VFWAPI ICSeqCompressFrame(PCOMPVARS pc, UINT uiFlags, LPVOID lpBits, BOOL *pfKey, LONG *plSize)
01344 {
01345     ICCOMPRESS* icComp = pc->lpState;
01346     DWORD ret;
01347     TRACE("(%p, 0x%08x, %p, %p, %p)\n", pc, uiFlags, lpBits, pfKey, plSize);
01348 
01349     if (pc->cbState != sizeof(ICCOMPRESS))
01350     {
01351        ERR("Invalid cbState %i\n", pc->cbState);
01352        return NULL;
01353     }
01354 
01355     if (!pc->lKeyCount++)
01356        icComp->dwFlags = ICCOMPRESS_KEYFRAME;
01357     else
01358     {
01359         if (pc->lKey && pc->lKeyCount == (pc->lKey - 1))
01360         /* No key frames if pc->lKey == 0 */
01361            pc->lKeyCount = 0;
01362     icComp->dwFlags = 0;
01363     }
01364 
01365     icComp->lpInput = lpBits;
01366     icComp->lFrameNum = pc->lFrame++;
01367     icComp->lpOutput = pc->lpBitsOut;
01368     icComp->lpPrev = pc->lpBitsPrev;
01369     ret = ICSendMessage(pc->hic, ICM_COMPRESS, (DWORD_PTR)icComp, sizeof(icComp));
01370 
01371     if (icComp->dwFlags & AVIIF_KEYFRAME)
01372     {
01373        pc->lKeyCount = 1;
01374        *pfKey = TRUE;
01375        TRACE("Key frame\n");
01376     }
01377     else
01378        *pfKey = FALSE;
01379 
01380     *plSize = icComp->lpbiOutput->biSizeImage;
01381     TRACE(" -- 0x%08x\n", ret);
01382     if (ret == ICERR_OK)
01383     {
01384        LPVOID oldprev, oldout;
01385 /* We shift Prev and Out, so we don't have to allocate and release memory */
01386        oldprev = pc->lpBitsPrev;
01387        oldout = pc->lpBitsOut;
01388        pc->lpBitsPrev = oldout;
01389        pc->lpBitsOut = oldprev;
01390 
01391        TRACE("returning: %p\n", icComp->lpOutput);
01392        return icComp->lpOutput;
01393     }
01394     return NULL;
01395 }
01396 
01397 /***********************************************************************
01398  *      ICSeqCompressFrameEnd   [MSVFW32.@]
01399  */
01400 void VFWAPI ICSeqCompressFrameEnd(PCOMPVARS pc)
01401 {
01402     DWORD ret;
01403     TRACE("(%p)\n", pc);
01404     ret = ICSendMessage(pc->hic, ICM_COMPRESS_END, 0, 0);
01405     TRACE(" -- %x\n", ret);
01406     HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01407     HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
01408     HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
01409     HeapFree(GetProcessHeap(), 0, pc->lpState);
01410     pc->lpbiIn = pc->lpBitsPrev = pc->lpBitsOut = pc->lpState = NULL;
01411 }
01412 
01413 /***********************************************************************
01414  *      ICSeqCompressFrameStart [MSVFW32.@]
01415  */
01416 BOOL VFWAPI ICSeqCompressFrameStart(PCOMPVARS pc, LPBITMAPINFO lpbiIn)
01417 {
01418     /* I'm ignoring bmiColors as I don't know what to do with it,
01419      * it doesn't appear to be used though
01420      */
01421     DWORD ret;
01422     pc->lpbiIn = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO));
01423     if (!pc->lpbiIn)
01424         return FALSE;
01425 
01426     *pc->lpbiIn = *lpbiIn;
01427     pc->lpBitsPrev = HeapAlloc(GetProcessHeap(), 0, pc->lpbiIn->bmiHeader.biSizeImage);
01428     if (!pc->lpBitsPrev)
01429     {
01430         HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01431     return FALSE;
01432     }
01433 
01434     pc->lpState = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS));
01435     if (!pc->lpState)
01436     {
01437        HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01438        HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
01439        return FALSE;
01440     }
01441     pc->cbState = sizeof(ICCOMPRESS);
01442 
01443     pc->lpBitsOut = HeapAlloc(GetProcessHeap(), 0, pc->lpbiOut->bmiHeader.biSizeImage);
01444     if (!pc->lpBitsOut)
01445     {
01446        HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01447        HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
01448        HeapFree(GetProcessHeap(), 0, pc->lpState);
01449        return FALSE;
01450     }
01451     TRACE("Compvars:\n"
01452           "\tpc:\n"
01453           "\tsize: %i\n"
01454           "\tflags: %i\n"
01455           "\thic: %p\n"
01456           "\ttype: %x\n"
01457           "\thandler: %x\n"
01458           "\tin/out: %p/%p\n"
01459           "key/data/quality: %i/%i/%i\n",
01460          pc->cbSize, pc->dwFlags, pc->hic, pc->fccType, pc->fccHandler,
01461          pc->lpbiIn, pc->lpbiOut, pc->lKey, pc->lDataRate, pc->lQ);
01462 
01463     ret = ICSendMessage(pc->hic, ICM_COMPRESS_BEGIN, (DWORD_PTR)pc->lpbiIn, (DWORD_PTR)pc->lpbiOut);
01464     TRACE(" -- %x\n", ret);
01465     if (ret == ICERR_OK)
01466     {
01467        ICCOMPRESS* icComp = pc->lpState;
01468        /* Initialise some variables */
01469        pc->lFrame = 0; pc->lKeyCount = 0;
01470 
01471        icComp->lpbiOutput = &pc->lpbiOut->bmiHeader;
01472        icComp->lpbiInput = &pc->lpbiIn->bmiHeader;
01473        icComp->lpckid = NULL;
01474        icComp->dwFrameSize = 0;
01475        icComp->dwQuality = pc->lQ;
01476        icComp->lpbiPrev = &pc->lpbiIn->bmiHeader;
01477        return TRUE;
01478     }
01479     HeapFree(GetProcessHeap(), 0, pc->lpbiIn);
01480     HeapFree(GetProcessHeap(), 0, pc->lpBitsPrev);
01481     HeapFree(GetProcessHeap(), 0, pc->lpState);
01482     HeapFree(GetProcessHeap(), 0, pc->lpBitsOut);
01483     pc->lpBitsPrev = pc->lpbiIn = pc->lpState = pc->lpBitsOut = NULL;
01484     return FALSE;
01485 }
01486 
01487 /***********************************************************************
01488  *      GetFileNamePreview   [MSVFW32.@]
01489  */
01490 static BOOL GetFileNamePreview(LPVOID lpofn,BOOL bSave,BOOL bUnicode)
01491 {
01492   CHAR    szFunctionName[20];
01493   BOOL    (*fnGetFileName)(LPVOID);
01494   HMODULE hComdlg32;
01495   BOOL    ret;
01496 
01497   FIXME("(%p,%d,%d), semi-stub!\n",lpofn,bSave,bUnicode);
01498 
01499   lstrcpyA(szFunctionName, (bSave ? "GetSaveFileName" : "GetOpenFileName"));
01500   lstrcatA(szFunctionName, (bUnicode ? "W" : "A"));
01501 
01502   hComdlg32 = LoadLibraryA("COMDLG32.DLL");
01503   if (hComdlg32 == NULL)
01504     return FALSE;
01505 
01506   fnGetFileName = (LPVOID)GetProcAddress(hComdlg32, szFunctionName);
01507   if (fnGetFileName == NULL)
01508     return FALSE;
01509 
01510   /* FIXME: need to add OFN_ENABLEHOOK and our own handler */
01511   ret = fnGetFileName(lpofn);
01512 
01513   FreeLibrary(hComdlg32);
01514   return ret;
01515 }
01516 
01517 /***********************************************************************
01518  *      GetOpenFileNamePreviewA [MSVFW32.@]
01519  */
01520 BOOL WINAPI GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn)
01521 {
01522   FIXME("(%p), semi-stub!\n", lpofn);
01523 
01524   return GetFileNamePreview(lpofn, FALSE, FALSE);
01525 }
01526 
01527 /***********************************************************************
01528  *      GetOpenFileNamePreviewW [MSVFW32.@]
01529  */
01530 BOOL WINAPI GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn)
01531 {
01532   FIXME("(%p), semi-stub!\n", lpofn);
01533 
01534   return GetFileNamePreview(lpofn, FALSE, TRUE);
01535 }
01536 
01537 /***********************************************************************
01538  *      GetSaveFileNamePreviewA [MSVFW32.@]
01539  */
01540 BOOL WINAPI GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn)
01541 {
01542   FIXME("(%p), semi-stub!\n", lpofn);
01543 
01544   return GetFileNamePreview(lpofn, TRUE, FALSE);
01545 }
01546 
01547 /***********************************************************************
01548  *      GetSaveFileNamePreviewW [MSVFW32.@]
01549  */
01550 BOOL WINAPI GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn)
01551 {
01552   FIXME("(%p), semi-stub!\n", lpofn);
01553 
01554   return GetFileNamePreview(lpofn, TRUE, TRUE);
01555 }

Generated on Sun May 27 2012 04:25:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.