Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2500 lines
74 KiB

  1. /*
  2. * This code contains thunk enabling. If we fail to open on the 16 bit side,
  3. * we will try and open a 32 bit codec. (The reason for not trying the 32
  4. * bit codec first is an attempt to keep most things on the 16 bit side.
  5. * The performance under NT appears reasonable, and for frame specific
  6. * operations it reduces the number of 16/32 transitions.
  7. */
  8. #include <windows.h>
  9. #include <windowsx.h>
  10. #include <mmsystem.h>
  11. #include <win32.h>
  12. #ifdef WIN32
  13. #include <mmddk.h> // needed for definition of DRIVERS_SECTION
  14. #endif
  15. //
  16. // define these before compman.h, so our functions get declared right.
  17. //
  18. #ifndef WIN32
  19. #define VFWAPI FAR PASCAL _loadds
  20. #define VFWAPIV FAR CDECL _loadds
  21. #endif
  22. #include "compman.h"
  23. #include "icm.rc"
  24. #ifdef WIN32
  25. #include <wchar.h>
  26. #endif
  27. #ifndef NOTHUNKS
  28. #include "thunks.h" // Building
  29. #endif //NOTHUNKS
  30. #ifndef streamtypeVIDEO
  31. #define streamtypeVIDEO mmioFOURCC('v', 'i', 'd', 's')
  32. #endif
  33. #define ICTYPE_VCAP mmioFOURCC('v', 'c', 'a', 'p')
  34. #define ICTYPE_ACM mmioFOURCC('a', 'u', 'd', 'c')
  35. #define SMAG mmioFOURCC('S', 'm', 'a', 'g')
  36. #define GONE mmioFOURCC('G', 'o', 'n', 'e')
  37. #define IC_INI TEXT("Installable Compressors")
  38. static TCHAR szIniSect[] = IC_INI;
  39. static TCHAR szDrivers[] = DRIVERS_SECTION;
  40. static TCHAR szSystemIni[] = TEXT("SYSTEM.INI");
  41. static TCHAR szNull[] = TEXT("");
  42. static TCHAR sz44s[] = TEXT("%4.4hs");
  43. static TCHAR szICKey[] = TEXT("%4.4hs.%4.4hs");
  44. static TCHAR szMSVideo[] = TEXT("MSVideo");
  45. static TCHAR szMSACM[] = TEXT("MSACM");
  46. static TCHAR szVIDC[] = TEXT("VIDC");
  47. static SZCODEA szDriverProc[] = "DriverProc";
  48. #ifdef DEBUG
  49. #define DPF( x ) dprintfc x
  50. #define DEBUG_RETAIL
  51. #else
  52. #define DPF(x)
  53. #endif
  54. #ifdef DEBUG_RETAIL
  55. static void CDECL dprintfc(LPSTR, ...);
  56. #define RPF( x ) dprintfc x
  57. #define ROUT(sz) {static SZCODE ach[] = sz; dprintfc(ach); }
  58. void ICDebugMessage(HIC hic, UINT msg, DWORD dw1, DWORD dw2);
  59. LRESULT ICDebugReturn(LRESULT err);
  60. #define DebugErr(sz) {static SZCODE ach[] = "COMPMAN: "sz; DebugOutput(DBF_ERROR | DBF_MMSYSTEM, ach); }
  61. #else
  62. #define RPF(x)
  63. #define ROUT(sz)
  64. #define ICDebugMessage(hic, msg, dw1, dw2)
  65. #define ICDebugReturn(err) err
  66. #define DebugErr(sz)
  67. #endif
  68. #ifdef DEBUG_RETAIL
  69. #else
  70. #define DebugErr(flags)
  71. #endif
  72. #ifndef WF_WINNT
  73. #define WF_WINNT 0x4000
  74. #endif
  75. #ifdef WIN32
  76. #define IsWow() FALSE
  77. #else
  78. #define IsWow() ((BOOL) (GetWinFlags() & WF_WINNT))
  79. #define GetDriverModuleHandle(h) (IsWow() ? h : GetDriverModuleHandle(h))
  80. #endif
  81. __inline void ictokey(DWORD fccType, DWORD fcc, LPSTR sz)
  82. {
  83. int i = wsprintf(sz, szICKey, (LPSTR)&(fccType),(LPSTR)&(fcc));
  84. while (i>0 && sz[i-1] == ' ')
  85. sz[--i] = 0;
  86. }
  87. #define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
  88. #define DIBWIDTHBYTES(bi) (int)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
  89. static void ICDump(void);
  90. //
  91. // the following array is used for 'installed' converters
  92. //
  93. // converters are either driver handles or indexes into this array
  94. //
  95. // 'function' converters are installed into this array, 'driver' converters
  96. // are installed in SYSTEM.INI
  97. //
  98. #define MAX_CONVERTERS 75 // maximum installed converters.
  99. typedef struct {
  100. DWORD dwSmag; // 'Smag'
  101. HTASK hTask; // owner task.
  102. DWORD fccType; // converter type ie 'vidc'
  103. DWORD fccHandler; // converter id ie 'rle '
  104. HDRVR hDriver; // handle of driver
  105. DWORD dwDriver; // driver id for functions
  106. DRIVERPROC DriverProc; // function to call
  107. #ifndef NOTHUNKS
  108. DWORD h32; // 32-bit driver handle
  109. #endif //!NOTHUNKS
  110. } IC, *PIC;
  111. IC aicConverters[MAX_CONVERTERS];
  112. /*****************************************************************************
  113. ****************************************************************************/
  114. LRESULT CALLBACK DriverProcNull(DWORD dwDriverID, HANDLE hDriver, UINT wMessage,DWORD dwParam1, DWORD dwParam2)
  115. {
  116. DPF(("codec called after it has been removed with ICRemove\r\n"));
  117. return ICERR_UNSUPPORTED;
  118. }
  119. /*****************************************************************************
  120. ****************************************************************************/
  121. static HDRVR LoadDriver(LPSTR szDriver, DRIVERPROC FAR *lpDriverProc);
  122. static void FreeDriver(HDRVR hDriver);
  123. /*****************************************************************************
  124. driver cache - to make enuming/loading faster we keep the last N
  125. module's open for a while.
  126. ****************************************************************************/
  127. #define N_MODULES 10 //!!!????
  128. HMODULE ahModule[N_MODULES];
  129. int iModule = 0;
  130. static void CacheModule(HMODULE hModule)
  131. {
  132. TCHAR ach[128];
  133. //
  134. // what if this module is in the list currently?
  135. //
  136. #if 0
  137. // we dont do this so unused compressors will fall off the end....
  138. int i;
  139. for (i=0; i<N_MODULES; i++)
  140. {
  141. if (ahModule[i] && ahModule[i] == hModule)
  142. return;
  143. }
  144. #endif
  145. //
  146. // add this module to the cache
  147. //
  148. #ifndef WIN32 // On NT GetModuleUsage always returns 1. So... we cache
  149. if (hModule)
  150. {
  151. extern HMODULE ghInst; // in MSVIDEO/init.c
  152. int iUsage;
  153. GetModuleFileName(hModule, ach, sizeof(ach));
  154. DPF(("Loading module: %s\r\n", (LPSTR)ach));
  155. iUsage = GetModuleUsage(ghInst);
  156. LoadLibrary(ach);
  157. //
  158. // dont cache modules that link to MSVIDEO
  159. // we should realy do a toolhelp thing!
  160. // or force apps to call VFWInit and VFWExit()
  161. //
  162. if (iUsage != GetModuleUsage(ghInst))
  163. {
  164. DPF(("Not caching this module because it links to MSVIDEO\r\n"));
  165. FreeLibrary(hModule);
  166. return;
  167. }
  168. }
  169. #endif
  170. //
  171. // free module in our slot.
  172. //
  173. if (ahModule[iModule] != NULL)
  174. {
  175. #ifdef DEBUG
  176. GetModuleFileName(ahModule[iModule], ach, sizeof(ach));
  177. DPF(("Freeing module: %s\r\n", (LPSTR)ach));
  178. #endif
  179. FreeLibrary(ahModule[iModule]);
  180. }
  181. ahModule[iModule] = hModule;
  182. iModule++;
  183. if (iModule >= N_MODULES)
  184. iModule = 0;
  185. }
  186. /*****************************************************************************
  187. ****************************************************************************/
  188. /*****************************************************************************
  189. * FixFOURCC - clean up a FOURCC
  190. ****************************************************************************/
  191. static DWORD Fix4CC(DWORD fcc)
  192. {
  193. int i;
  194. if (fcc > 256)
  195. {
  196. AnsiLowerBuff((LPSTR)&fcc, sizeof(fcc));
  197. for (i=0; i<4; i++)
  198. {
  199. if (((LPSTR)&fcc)[i] == 0)
  200. for (; i<4; i++)
  201. ((LPSTR)&fcc)[i] = ' ';
  202. }
  203. }
  204. return fcc;
  205. }
  206. /*****************************************************************************
  207. * @doc INTERNAL IC
  208. *
  209. * @api PIC | FindConverter |
  210. * search the converter list for a un-opened converter
  211. *
  212. ****************************************************************************/
  213. static PIC FindConverter(DWORD fccType, DWORD fccHandler)
  214. {
  215. int i;
  216. PIC pic;
  217. for (i=0; i<MAX_CONVERTERS; i++)
  218. {
  219. pic = &aicConverters[i];
  220. if (pic->fccType == fccType &&
  221. pic->fccHandler == fccHandler &&
  222. pic->dwDriver == 0L)
  223. {
  224. if (pic->DriverProc != NULL && IsBadCodePtr((FARPROC)pic->DriverProc))
  225. {
  226. pic->DriverProc = NULL;
  227. ICClose((HIC)pic);
  228. DPF(("NO driver for fccType=%4.4s, Handler=%4.4s\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  229. return NULL;
  230. }
  231. DPF(("Possible driver for fccType=%4.4s, Handler=%4.4s\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  232. return pic;
  233. }
  234. }
  235. return NULL;
  236. }
  237. #ifdef WIN32
  238. /*
  239. * we need to hold a critical section around the ICOpen code to protect
  240. * multi-thread simultaneous opens. This critsec is initialized by
  241. * IC_Load (called from video\init.c at dll attach time) and is deleted
  242. * by IC_Unload (called from video\init.c at dll detach time).
  243. */
  244. CRITICAL_SECTION ICOpenCritSec;
  245. void
  246. IC_Load(void)
  247. {
  248. InitializeCriticalSection(&ICOpenCritSec);
  249. }
  250. void
  251. IC_Unload(void)
  252. {
  253. DeleteCriticalSection(&ICOpenCritSec);
  254. }
  255. #define ICEnterCrit(p) (EnterCriticalSection(p))
  256. #define ICLeaveCrit(p) (LeaveCriticalSection(p))
  257. #else
  258. // non-win32 code has no critsecs
  259. #define ICEnterCrit(p)
  260. #define ICLeaveCrit(p)
  261. #endif
  262. /*****************************************************************************
  263. ****************************************************************************/
  264. __inline BOOL ICValid(HIC hic)
  265. {
  266. PIC pic = (PIC)hic;
  267. if (pic < &aicConverters[0] ||
  268. pic >= &aicConverters[MAX_CONVERTERS] ||
  269. pic->dwSmag != SMAG)
  270. {
  271. DebugErr("Invalid HIC\r\n");
  272. return FALSE;
  273. }
  274. return TRUE;
  275. }
  276. /*****************************************************************************
  277. ****************************************************************************/
  278. #define V_HIC(hic) \
  279. if (!ICValid(hic)) \
  280. return ICERR_BADHANDLE;
  281. /*****************************************************************************
  282. * @doc INTERNAL IC
  283. *
  284. * @api BOOL | ICCleanup | This function is called when a task exits or
  285. * MSVIDEO.DLL is being unloaded.
  286. *
  287. * @parm HTASK | hTask | the task being terminated, NULL if DLL being unloaded
  288. *
  289. * @rdesc Returns nothing
  290. *
  291. * @comm currently MSVIDEO only calles this function from it's WEP()
  292. *
  293. ****************************************************************************/
  294. void FAR PASCAL ICCleanup(HTASK hTask)
  295. {
  296. int i;
  297. PIC pic;
  298. //
  299. // free all HICs
  300. //
  301. for (i=0; i < MAX_CONVERTERS; i++)
  302. {
  303. pic = &aicConverters[i];
  304. if (pic->dwDriver != 0L && (pic->hTask == hTask || hTask == NULL))
  305. {
  306. ROUT("Decompressor left open, closing\r\n");
  307. ICClose((HIC)pic);
  308. }
  309. }
  310. //
  311. // free the module cache.
  312. //
  313. for (i=0; i<N_MODULES; i++)
  314. CacheModule(NULL);
  315. }
  316. /*****************************************************************************
  317. * @doc EXTERNAL IC ICAPPS
  318. *
  319. * @api BOOL | ICInstall | This function installs a new compressor
  320. * or decompressor.
  321. *
  322. * @parm DWORD | fccType | Specifies a four-character code indicating the
  323. * type of data used by the compressor or decompressor. Use 'vidc'
  324. * for a video compressor or decompressor.
  325. *
  326. * @parm DWORD | fccHandler | Specifies a four-character code identifying
  327. * a specific compressor or decompressor.
  328. *
  329. * @parm LPARAM | lParam | Specifies a pointer to a zero-terminated
  330. * string containing the name of the compressor or decompressor,
  331. * or it specifies a far pointer to a function used for compression
  332. * or decompression. The contents of this parameter are defined
  333. * by the flags set for <p wFlags>.
  334. *
  335. * @parm LPSTR | szDesc | Specifies a pointer to a zero-terminated string
  336. * describing the installed compressor. Not use.
  337. *
  338. * @parm UINT | wFlags | Specifies flags defining the contents of <p lParam>.
  339. * The following flags are defined:
  340. *
  341. * @flag ICINSTALL_DRIVER | Indicates <p lParam> is a pointer to a zero-terminated
  342. * string containing the name of the compressor to install.
  343. *
  344. * @flag ICINSTALL_FUNCTION | Indicates <p lParam> is a far pointer to
  345. * a compressor function. This function should
  346. * be structured like the <f DriverProc> entry
  347. * point function used by compressors.
  348. *
  349. * @rdesc Returns TRUE if successful.
  350. *
  351. * @comm Applications must still open the installed compressor or
  352. * decompressor before it can use the compressor or decompressor.
  353. *
  354. * Usually, compressors and decompressors are installed by the user
  355. * with the Drivers option of the Control Panel.
  356. *
  357. * If your application installs a function as a compressor or
  358. * decompressor, it should remove the compressor or decompressor
  359. * with <f ICRemove> before it terminates. This prevents other
  360. * applications from trying to access the function when it is not
  361. * available.
  362. *
  363. *
  364. * @xref <f ICRemove>
  365. ****************************************************************************/
  366. BOOL VFWAPI ICInstall(DWORD fccType, DWORD fccHandler, LPARAM lParam, LPSTR szDesc, UINT wFlags)
  367. {
  368. TCHAR achKey[20];
  369. TCHAR buf[128];
  370. PIC pic;
  371. ICEnterCrit(&ICOpenCritSec);
  372. fccType = Fix4CC(fccType);
  373. fccHandler = Fix4CC(fccHandler);
  374. DPF(("ICInstall, fccType=%4.4s, Handler=%4.4s, >>%s<<\n", (LPSTR)&fccType, (LPSTR)&fccHandler, szDesc));
  375. if ((pic = FindConverter(fccType, fccHandler)) == NULL)
  376. pic = FindConverter(0L, 0L);
  377. if (wFlags & ICINSTALL_DRIVER)
  378. {
  379. //
  380. // dwConverter is the file name of a driver to install.
  381. //
  382. ictokey(fccType, fccHandler, achKey);
  383. #ifdef WIN32
  384. if (szDesc)
  385. wsprintf(buf, TEXT("%hs %hs"), (LPSTR) lParam, szDesc);
  386. else
  387. wsprintf(buf, TEXT("%hs"), (LPSTR) lParam);
  388. #else
  389. lstrcpy(buf, (LPSTR)lParam);
  390. if (szDesc)
  391. {
  392. lstrcat(buf, TEXT(" "));
  393. lstrcat(buf, szDesc);
  394. }
  395. #endif
  396. ICLeaveCrit(&ICOpenCritSec);
  397. if (WritePrivateProfileString(szDrivers,achKey,buf,szSystemIni))
  398. {
  399. WritePrivateProfileString(szIniSect,achKey,NULL,szSystemIni);
  400. return TRUE;
  401. }
  402. else
  403. {
  404. return(FALSE);
  405. }
  406. }
  407. else if (wFlags & ICINSTALL_FUNCTION)
  408. {
  409. if (pic == NULL)
  410. {
  411. ICLeaveCrit(&ICOpenCritSec);
  412. return FALSE;
  413. }
  414. pic->dwSmag = SMAG;
  415. pic->fccType = fccType;
  416. pic->fccHandler = fccHandler;
  417. pic->dwDriver = 0L;
  418. pic->hDriver = NULL;
  419. pic->DriverProc = (DRIVERPROC)lParam;
  420. ICLeaveCrit(&ICOpenCritSec);
  421. return TRUE;
  422. }
  423. #if 0
  424. else if (wFlags & ICINSTALL_HDRV)
  425. {
  426. if (pic == NULL)
  427. {
  428. ICLeaveCrit(&ICOpenCritSec);
  429. return FALSE;
  430. }
  431. pic->fccType = fccType;
  432. pic->fccHandler = fccHandler;
  433. pic->hDriver = (HDRVR)lParam;
  434. pic->dwDriver = 0L;
  435. pic->DrvProc = NULL;
  436. ICLeaveCrit(&ICOpenCritSec);
  437. return TRUE;
  438. }
  439. #endif
  440. ICLeaveCrit(&ICOpenCritSec);
  441. return FALSE;
  442. }
  443. /*****************************************************************************
  444. * @doc EXTERNAL IC ICAPPS
  445. *
  446. * @api BOOL | ICRemove | This function removes an installed compressor.
  447. *
  448. * @parm DWORD | fccType | Specifies a four-character code indicating the
  449. * type of data used by the compressor. Use 'vidc' for video compressors.
  450. *
  451. * @parm DWORD | fccHandler | Specifies a four-character code identifying
  452. * a specific compressor.
  453. *
  454. * @parm UINT | wFlags | Not used.
  455. *
  456. * @rdesc Returns TRUE if successful.
  457. *
  458. * @xref <f ICInstall>
  459. ****************************************************************************/
  460. BOOL VFWAPI ICRemove(DWORD fccType, DWORD fccHandler, UINT wFlags)
  461. {
  462. TCHAR achKey[20];
  463. PIC pic;
  464. ICEnterCrit(&ICOpenCritSec);
  465. fccType = Fix4CC(fccType);
  466. fccHandler = Fix4CC(fccHandler);
  467. DPF(("ICRemove, fccType=%4.4s, Handler=%4.4s\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  468. if (pic = FindConverter(fccType, fccHandler))
  469. {
  470. int i;
  471. //
  472. // we should realy keep usage counts!!!
  473. //
  474. for (i=0; i<MAX_CONVERTERS; i++)
  475. {
  476. if (pic->DriverProc == aicConverters[i].DriverProc)
  477. {
  478. DPF(("ACK! Handler is in use\r\n"));
  479. pic->DriverProc = DriverProcNull;
  480. }
  481. }
  482. ICClose((HIC)pic);
  483. }
  484. else
  485. {
  486. ictokey(fccType, fccHandler, achKey);
  487. WritePrivateProfileString(szIniSect,achKey,NULL,szSystemIni);
  488. WritePrivateProfileString(szDrivers,achKey,NULL,szSystemIni);
  489. }
  490. ICLeaveCrit(&ICOpenCritSec);
  491. return TRUE;
  492. }
  493. /*****************************************************************************
  494. * @doc EXTERNAL IC ICAPPS
  495. *
  496. * @api BOOL | ICInfo | This function returns information about
  497. * specific installed compressors, or it enumerates
  498. * the compressors installed.
  499. *
  500. * @parm DWORD | fccType | Specifies a four-character code indicating
  501. * the type of compressor. To match all compressor types specify zero.
  502. *
  503. * @parm DWORD | fccHandler | Specifies a four-character code identifying
  504. * a specific compressor, or a number between 0 and the number
  505. * of installed compressors of the type specified by <t fccType>.
  506. *
  507. * @parm ICINFO FAR * | lpicinfo | Specifies a far pointer to a
  508. * <t ICINFO> structure used to return
  509. * information about the compressor.
  510. *
  511. * @comm This function does not return full informaiton about
  512. * a compressor or decompressor. Use <f ICGetInfo> for full
  513. * information.
  514. *
  515. * @rdesc Returns TRUE if successful.
  516. ****************************************************************************/
  517. #ifndef NOTHUNKS
  518. BOOL VFWAPI ICInfoInternal(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicinfo);
  519. // If we are compiling the thunks, then the ICINFO entry point calls
  520. // the 32 bit thunk, or calls the real ICInfo code (as ICInfoInternal).
  521. // We deliberately give precedence to 32 bit compressors, although this
  522. // ordering can be trivially changed.
  523. // ??: Should we allow an INI setting to change the order?
  524. BOOL VFWAPI ICInfo(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicinfo)
  525. {
  526. BOOL fResult;
  527. fResult = (ICInfo32(fccType, fccHandler, lpicinfo));
  528. DPF(("ICInfo32 returned %ls\r\n", (fResult ? (LPSTR)"TRUE" : (LPSTR)"FALSE")));
  529. if (fResult) return fResult;
  530. // If we are enumerating the drivers, then we want to adjust the 16
  531. // bit index by the count of 32 bit drivers. The thunk will have
  532. // passed back the number of 32 bit drivers installed in [Drivers32]
  533. // in ICINFO.fccHandler.
  534. if ((fccType==0) || (fccHandler < 256)) {
  535. DPF(("Enumerating... no 32 bit match, Count is %ld, max count is %ld\n", fccType, lpicinfo->fccHandler));
  536. if (fccHandler >= lpicinfo->fccHandler)
  537. fccHandler -= lpicinfo->fccHandler;
  538. else
  539. ; // This should be an assertion. This leg is invalid.
  540. }
  541. //
  542. // See if there is a 16-bit compressor we can use
  543. // Because we always try 32 bit compressors first, if the user is
  544. // enumerating the list of compressors we need to subtract the count
  545. // of 32 bit compressors.
  546. //
  547. DPF(("ICInfo, fccType=%4.4hs, Handler=%4.4hs\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  548. return (ICInfoInternal(fccType, fccHandler, lpicinfo));
  549. }
  550. // Now map all ICInfo calls to ICInfoInternal
  551. #define ICInfo ICInfoInternal
  552. #endif //NOTHUNKS
  553. BOOL VFWAPI ICInfo(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicinfo)
  554. {
  555. char buf[128];
  556. static LPTSTR pszBuf = NULL;
  557. TCHAR achKey[20];
  558. #ifdef WIN32
  559. TCHAR achTypeCopy[5];
  560. char newHandler[5];
  561. char newType[5];
  562. #endif
  563. int i;
  564. int iComp;
  565. PIC pic;
  566. DPF(("ICInfoInternal(16), fccType=%4.4hs, Handler=%4.4hs\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  567. if (lpicinfo == NULL)
  568. return FALSE;
  569. // THIS IS NOT REDUNDANT. what if fccType == 0
  570. if (fccType > 0 && fccType < 256) {
  571. DPF(("fcctype invalid\r\n"));
  572. return FALSE;
  573. }
  574. fccType = Fix4CC(fccType);
  575. fccHandler = Fix4CC(fccHandler);
  576. if (fccType != 0 && fccHandler > 256)
  577. {
  578. //
  579. // the user has given us a specific fccType and fccHandler
  580. // get the info and return.
  581. //
  582. if (pic = FindConverter(fccType, fccHandler))
  583. {
  584. ICGetInfo((HIC)pic, lpicinfo, sizeof(ICINFO));
  585. return TRUE;
  586. }
  587. else
  588. {
  589. lpicinfo->dwSize = sizeof(ICINFO);
  590. lpicinfo->fccType = fccType;
  591. lpicinfo->fccHandler = fccHandler;
  592. lpicinfo->dwFlags = 0;
  593. lpicinfo->dwVersionICM = ICVERSION;
  594. lpicinfo->dwVersion = 0;
  595. lpicinfo->szDriver[0] = 0;
  596. lpicinfo->szDescription[0] = 0;
  597. lpicinfo->szName[0] = 0;
  598. ictokey(fccType, fccHandler, achKey);
  599. if (!GetPrivateProfileString(szDrivers,achKey,szNull,buf,sizeof(buf)/sizeof(TCHAR),szSystemIni) &&
  600. !GetPrivateProfileString(szIniSect,achKey,szNull,buf,sizeof(buf)/sizeof(TCHAR),szSystemIni))
  601. {
  602. DPF(("NO information in DRIVERS section\n"));
  603. return FALSE;
  604. }
  605. for (i=0; buf[i] && buf[i] != TEXT(' '); i++)
  606. lpicinfo->szDriver[i] = buf[i];
  607. lpicinfo->szDriver[i] = 0;
  608. //
  609. // the driver must be opened to get description
  610. //
  611. lpicinfo->szDescription[0] = 0;
  612. return TRUE;
  613. }
  614. }
  615. else
  616. {
  617. //
  618. // the user has given us a specific fccType and a
  619. // ordinal for fccHandler, enum the compressors, looking for
  620. // the nth compressor of 'fccType'
  621. //
  622. iComp = (int)fccHandler;
  623. //
  624. // walk the installed converters.
  625. //
  626. for (i=0; i < MAX_CONVERTERS; i++)
  627. {
  628. pic = &aicConverters[i];
  629. if (pic->fccType != 0 &&
  630. (fccType == 0 || pic->fccType == fccType) &&
  631. pic->dwDriver == 0L && iComp-- == 0)
  632. {
  633. return ICInfo(pic->fccType, pic->fccHandler, lpicinfo);
  634. }
  635. }
  636. //
  637. // read all the keys. from [Drivers] and [Installable Compressors]
  638. //
  639. if (pszBuf == NULL) {
  640. UINT cbBuffer = 128 * sizeof(TCHAR);
  641. UINT cchBuffer;
  642. for (;;)
  643. {
  644. pszBuf = GlobalAllocPtr(GMEM_SHARE | GHND, cbBuffer);
  645. if (!pszBuf) {
  646. DPF(("Out of memory for SYSTEM.INI keys\r\n"));
  647. return FALSE;
  648. }
  649. cchBuffer = (UINT)GetPrivateProfileString(szDrivers,
  650. NULL,
  651. szNull,
  652. pszBuf,
  653. cbBuffer / sizeof(TCHAR),
  654. szSystemIni);
  655. if (cchBuffer < ((cbBuffer / sizeof(TCHAR)) - 5)) {
  656. cchBuffer += (UINT)GetPrivateProfileString(szIniSect,
  657. NULL,
  658. szNull,
  659. pszBuf + cchBuffer,
  660. (cbBuffer / sizeof(TCHAR)) - cchBuffer,
  661. szSystemIni);
  662. if (cchBuffer < ((cbBuffer / sizeof(TCHAR)) - 5))
  663. break;
  664. }
  665. GlobalFreePtr(pszBuf);
  666. pszBuf = NULL;
  667. //
  668. // if cannot fit drivers section in 32k, then something is horked
  669. // with the section... so let's bail.
  670. //
  671. if (cbBuffer >= 0x8000) {
  672. DPF(("SYSTEM.INI keys won't fit in 32K????\r\n"));
  673. return FALSE;
  674. }
  675. cbBuffer *= 2;
  676. DPF(("Increasing size of SYSTEM.INI buffer to %d\r\n", cbBuffer));
  677. }
  678. }
  679. #ifdef WIN32
  680. /* make a widechar copy of the Ansi fccType so we can compare it with
  681. * the wide copy returned from GetPrivateProfileString()
  682. */
  683. MultiByteToWideChar(CP_ACP, 0, (LPSTR) &fccType, sizeof(fccType),
  684. achTypeCopy, sizeof(achTypeCopy)/sizeof(TCHAR) );
  685. #endif
  686. for (i=0; pszBuf[i] != 0; i += lstrlen(&pszBuf[i]) + 1)
  687. {
  688. if (pszBuf[i+4]!=TEXT('.'))
  689. continue;
  690. #ifdef WIN32
  691. CharLower(&pszBuf[i]);
  692. if ((fccType == 0 ||
  693. (wcsncmp(achTypeCopy, &pszBuf[i], sizeof(fccType)) == 0)) &&
  694. iComp-- == 0)
  695. {
  696. WideCharToMultiByte(CP_ACP, 0, &pszBuf[i], sizeof(fccType),
  697. newType, sizeof(newType),NULL, NULL);
  698. WideCharToMultiByte(CP_ACP, 0, &pszBuf[i+5], sizeof(fccType),
  699. newHandler, sizeof(newHandler),NULL, NULL);
  700. return ICInfo(*(LPDWORD)&newType[0],*(LPDWORD)&newHandler[0], lpicinfo);
  701. }
  702. #else
  703. AnsiLower(&pszBuf[i]);
  704. if ((fccType == 0 || fccType == *(LPDWORD)&pszBuf[i]) && iComp-- == 0)
  705. {
  706. return ICInfo(*(LPDWORD)&pszBuf[i],*(LPDWORD)&pszBuf[i+5], lpicinfo);
  707. }
  708. #endif
  709. }
  710. //
  711. // now walk the msvideo drivers. these are listed in system.ini
  712. // like so:
  713. //
  714. // [Drivers]
  715. // MSVideo = driver
  716. // MSVideo1 = driver
  717. // MSVideoN =
  718. //
  719. if (fccType == 0 || fccType == ICTYPE_VCAP)
  720. {
  721. lstrcpy(achKey, szMSVideo);
  722. if (iComp > 0)
  723. wsprintf(achKey+lstrlen(achKey), (LPVOID)"%d", iComp);
  724. if (!GetPrivateProfileString(szDrivers,achKey,szNull,buf,sizeof(buf)/sizeof(TCHAR),szSystemIni))
  725. return FALSE;
  726. lpicinfo->dwSize = sizeof(ICINFO);
  727. lpicinfo->fccType = ICTYPE_VCAP;
  728. lpicinfo->fccHandler = iComp;
  729. lpicinfo->dwFlags = 0;
  730. lpicinfo->dwVersionICM = ICVERSION; //??? right for video?
  731. lpicinfo->dwVersion = 0;
  732. lpicinfo->szDriver[0] = 0;
  733. lpicinfo->szDescription[0] = 0;
  734. lpicinfo->szName[0] = 0;
  735. for (i=0; buf[i] && buf[i] != TEXT(' '); i++)
  736. lpicinfo->szDriver[i] = buf[i];
  737. lpicinfo->szDriver[i] = 0;
  738. return TRUE;
  739. }
  740. return FALSE;
  741. }
  742. }
  743. #undef ICInfo
  744. ////////////////////////////////////////////////////////////////////////////
  745. ////////////////////////////////////////////////////////////////////////////
  746. /*****************************************************************************
  747. * @doc EXTERNAL IC ICAPPS
  748. *
  749. * @api LRESULT | ICGetInfo | This function obtains information about
  750. * a compressor.
  751. *
  752. * @parm HIC | hic | Specifies a handle to a compressor.
  753. *
  754. * @parm ICINFO FAR * | lpicinfo | Specifies a far pointer to <t ICINFO> structure
  755. * used to return information about the compressor.
  756. *
  757. * @parm DWORD | cb | Specifies the size, in bytes, of the structure pointed to
  758. * by <p lpicinfo>.
  759. *
  760. * @rdesc Return the number of bytes copied into the data structure,
  761. * or zero if an error occurs.
  762. *
  763. * @comm Use <f ICInfo> for full information about a compressor.
  764. *
  765. ****************************************************************************/
  766. LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO FAR *picinfo, DWORD cb)
  767. {
  768. PIC pic = (PIC)hic;
  769. DWORD dw;
  770. V_HIC(hic);
  771. picinfo->dwSize = sizeof(ICINFO);
  772. picinfo->fccType = 0;
  773. picinfo->fccHandler = 0;
  774. picinfo->dwFlags = 0;
  775. picinfo->dwVersionICM = ICVERSION;
  776. picinfo->dwVersion = 0;
  777. picinfo->szDriver[0] = 0;
  778. picinfo->szDescription[0] = 0;
  779. picinfo->szName[0] = 0;
  780. #ifndef NOTHUNKS
  781. if (!Is32bitHandle(hic))
  782. #endif //!NOTHUNKS
  783. if (pic->hDriver)
  784. {
  785. GetModuleFileName(GetDriverModuleHandle(pic->hDriver),
  786. picinfo->szDriver, sizeof(picinfo->szDriver));
  787. }
  788. dw = ICSendMessage((HIC)pic, ICM_GETINFO, (DWORD)picinfo, cb);
  789. return dw;
  790. }
  791. /*****************************************************************************
  792. * @doc EXTERNAL IC ICAPPS
  793. *
  794. * @api LRESULT | ICSendMessage | This function sends a
  795. * message to a compressor.
  796. *
  797. * @parm HIC | hic | Specifies the handle of the
  798. * compressor to receive the message.
  799. *
  800. * @parm UINT | wMsg | Specifies the message to send.
  801. *
  802. * @parm DWORD | dw1 | Specifies additional message-specific information.
  803. *
  804. * @parm DWORD | dw2 | Specifies additional message-specific information.
  805. *
  806. * @rdesc Returns a message-specific result.
  807. ****************************************************************************/
  808. LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD dw1, DWORD dw2)
  809. {
  810. PIC pic = (PIC)hic;
  811. LRESULT l;
  812. #ifndef NOTHUNKS
  813. //
  814. // If it's a 32-bit handle then send it to the 32-bit code
  815. // We need to take some extra care with ICM_DRAW_SUGGESTFORMAT
  816. // which can include a HIC in the ICDRAWSUGGEST structure.
  817. //
  818. #define ICD(dw1) ((ICDRAWSUGGEST FAR *)(dw1))
  819. if (pic->h32) {
  820. ICDebugMessage(hic, msg, dw1, dw2);
  821. if ((msg == ICM_DRAW_SUGGESTFORMAT)
  822. && (((ICDRAWSUGGEST FAR *)dw1)->hicDecompressor))
  823. {
  824. // We are in the problem area.
  825. // IF the hicDecompressor field is NULL, pass as is.
  826. // IF it identifies a 32 bit decompressor, translate the handle
  827. // OTHERWISE... what? We have a 32 bit compressor, that is
  828. // being told it can use a 16 bit decompressor!!
  829. if ( ((PIC) (((ICDRAWSUGGEST FAR *)dw1)->hicDecompressor))->h32)
  830. {
  831. ICD(dw1)->hicDecompressor
  832. = (HIC)((PIC)(ICD(dw1)->hicDecompressor))->h32;
  833. } else
  834. {
  835. ICD(dw1)->hicDecompressor = NULL; // Sigh...
  836. }
  837. }
  838. l = ICSendMessage32(pic->h32, msg, dw1, dw2);
  839. return ICDebugReturn(l);
  840. }
  841. #endif //!NOTHUNKS
  842. V_HIC(hic);
  843. ICDebugMessage(hic, msg, dw1, dw2);
  844. l = pic->DriverProc(pic->dwDriver, (HDRVR)1, msg, dw1, dw2);
  845. #if 1 //!!! is this realy needed! !!!yes I think it is
  846. //
  847. // special case some messages and give default values.
  848. //
  849. if (l == ICERR_UNSUPPORTED)
  850. {
  851. switch (msg)
  852. {
  853. case ICM_GETDEFAULTQUALITY:
  854. *((LPDWORD)dw1) = ICQUALITY_HIGH;
  855. l = ICERR_OK;
  856. break;
  857. case ICM_GETDEFAULTKEYFRAMERATE:
  858. *((LPDWORD)dw1) = 15;
  859. l = ICERR_OK;
  860. break;
  861. }
  862. }
  863. #endif
  864. return ICDebugReturn(l);
  865. }
  866. /*****************************************************************************
  867. * @doc EXTERNAL IC ICAPPS
  868. *
  869. * @api LRESULT | ICMessage | This function sends a
  870. * message and a variable number of arguments to a compressor.
  871. * If a macro is defined for the message you want to send,
  872. * use the macro rather than this function.
  873. *
  874. * @parm HIC | hic | Specifies the handle of the
  875. * compressor to receive the message.
  876. *
  877. * @parm UINT | msg | Specifies the message to send.
  878. *
  879. * @parm UINT | cb | Specifies the size, in bytes, of the
  880. * optional parameters. (This is usually the size of the data
  881. * structure used to store the parameters.)
  882. *
  883. * @parm . | . . | Represents the variable number of arguments used
  884. * for the optional parameters.
  885. *
  886. * @rdesc Returns a message-specific result.
  887. ****************************************************************************/
  888. LRESULT VFWAPIV ICMessage(HIC hic, UINT msg, UINT cb, ...)
  889. {
  890. // NOTE no LOADDS!
  891. #ifndef WIN32
  892. return ICSendMessage(hic, msg, (DWORD)(LPVOID)(&cb+1), cb);
  893. #else
  894. va_list va;
  895. va_start(va, cb);
  896. va_end(va);
  897. return ICSendMessage(hic, msg, (DWORD)(LPVOID)va, cb);
  898. #endif
  899. }
  900. /*****************************************************************************
  901. * @doc EXTERNAL IC ICAPPS
  902. *
  903. * @api HIC | ICOpen | This function opens a compressor or decompressor.
  904. *
  905. * @parm DWORD | fccType | Specifies the type of compressor
  906. * the caller is trying to open. For video, this is ICTYPE_VIDEO.
  907. *
  908. * @parm DWORD | fccHandler | Specifies a single preferred handler of the
  909. * given type that should be tried first. Typically, this comes
  910. * from the stream header in an AVI file.
  911. *
  912. * @parm UINT | wMode | Specifies a flag to defining the use of
  913. * the compressor or decompressor.
  914. * This parameter can contain one of the following values:
  915. *
  916. * @flag ICMODE_COMPRESS | Advises a compressor it is opened for compression.
  917. *
  918. * @flag ICMODE_FASTCOMPRESS | Advise a compressor it is open
  919. * for fast (real-time) compression.
  920. *
  921. * @flag ICMODE_DECOMPRESS | Advises a decompressor it is opened for decompression.
  922. *
  923. * @flag ICMODE_FASTDECOMPRESS | Advises a decompressor it is opened
  924. * for fast (real-time) decompression.
  925. *
  926. * @flag ICMODE_DRAW | Advises a decompressor it is opened
  927. * to decompress an image and draw it directly to hardware.
  928. *
  929. * @flag ICMODE_QUERY | Advise a compressor or decompressor it is opened
  930. * to obtain information.
  931. *
  932. * @rdesc Returns a handle to a compressor or decompressor
  933. * if successful, otherwise it returns zero.
  934. ****************************************************************************/
  935. INLINE PIC NEAR PASCAL ICOpenInternal(PIC pic, DWORD fccType, DWORD fccHandler,
  936. ICINFO FAR * picinfo, ICOPEN FAR * picopen, UINT wMode)
  937. {
  938. PIC picT;
  939. if (picinfo->szDriver[0])
  940. {
  941. #ifdef DEBUG
  942. DWORD time = timeGetTime();
  943. char ach[80];
  944. #endif
  945. pic->hDriver = LoadDriver(picinfo->szDriver, &pic->DriverProc);
  946. #ifdef DEBUG
  947. time = timeGetTime() - time;
  948. wsprintfA(ach, "COMPMAN: LoadDriver(%ls) (%ldms)\r\n", (LPSTR)picinfo->szDriver, time);
  949. OutputDebugStringA(ach);
  950. #endif
  951. if (pic->hDriver == NULL)
  952. {
  953. pic->dwSmag = 0;
  954. return NULL;
  955. }
  956. //
  957. // now try to open the driver as a codec.
  958. //
  959. pic->dwDriver = ICSendMessage((HIC)pic, DRV_OPEN, 0, (DWORD)(LPVOID)picopen);
  960. //
  961. // we want to be able to install 1.0 draw handlers in SYSTEM.INI as:
  962. //
  963. // VIDS.SMAG = SMAG.DRV
  964. //
  965. // but old driver's may not open iff fccType == 'vids' only if
  966. // fccType == 'vidc'
  967. //
  968. // they also may not like ICMODE_DRAW
  969. //
  970. if (pic->dwDriver == 0 &&
  971. picopen->dwError != 0 &&
  972. fccType == streamtypeVIDEO)
  973. {
  974. if (wMode == ICMODE_DRAW)
  975. picopen->dwFlags = ICMODE_DECOMPRESS;
  976. picopen->fccType = ICTYPE_VIDEO;
  977. pic->dwDriver = ICSendMessage((HIC)pic, DRV_OPEN, 0, (DWORD)(LPVOID)picopen);
  978. }
  979. if (pic->dwDriver == 0)
  980. {
  981. ICClose((HIC)pic);
  982. return NULL;
  983. }
  984. // open'ed ok mark these
  985. pic->fccType = fccType;
  986. pic->fccHandler = fccHandler;
  987. }
  988. else if (picT = FindConverter(fccType, fccHandler))
  989. {
  990. DWORD dw;
  991. picT->dwSmag = SMAG;
  992. dw = ICSendMessage((HIC)picT, DRV_OPEN, 0, (DWORD)(LPVOID)picopen);
  993. if (dw == 0)
  994. {
  995. pic->dwSmag = 0;
  996. return NULL;
  997. }
  998. *pic = *picT;
  999. pic->dwDriver = dw;
  1000. }
  1001. return pic;
  1002. }
  1003. /* Helper functions for compression library */
  1004. HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
  1005. {
  1006. ICOPEN icopen;
  1007. ICINFO icinfo;
  1008. PIC pic;
  1009. HIC hic = NULL; // Initialise
  1010. ICEnterCrit(&ICOpenCritSec);
  1011. AnsiLowerBuff((LPSTR) &fccType, sizeof(DWORD));
  1012. AnsiLowerBuff((LPSTR) &fccHandler, sizeof(DWORD));
  1013. icopen.dwSize = sizeof(ICOPEN);
  1014. icopen.fccType = fccType;
  1015. icopen.fccHandler = fccHandler;
  1016. icopen.dwFlags = wMode;
  1017. icopen.dwError = 0;
  1018. DPF(("\nICOpen('%4.4s','%4.4s)'\r\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  1019. if (!ICInfo(fccType, fccHandler, &icinfo))
  1020. {
  1021. RPF(("Unable to locate Compression module '%4.4s' '%4.4s'\r\n", (LPSTR)&fccType, (LPSTR)&fccHandler));
  1022. ICLeaveCrit(&ICOpenCritSec);
  1023. return NULL;
  1024. }
  1025. pic = FindConverter(0L, 0L);
  1026. if (pic == NULL)
  1027. {
  1028. ICLeaveCrit(&ICOpenCritSec);
  1029. return NULL;
  1030. }
  1031. #ifndef NOTHUNKS
  1032. // Try and open on the 32 bit side first.
  1033. // This block and the one below can be interchanged to alter the order
  1034. // in which we try and open the compressor.
  1035. if (hic == NULL)
  1036. {
  1037. pic->dwSmag = SMAG;
  1038. pic->hTask = (HTASK)GetCurrentTask();
  1039. pic->h32 = ICOpen32(fccType, fccHandler, wMode);
  1040. if (pic->h32 != 0) {
  1041. pic->fccType = fccType;
  1042. pic->fccHandler = fccHandler;
  1043. pic->dwDriver = (DWORD) -1;
  1044. pic->DriverProc = NULL;
  1045. hic = (HIC)pic;
  1046. }
  1047. }
  1048. #endif //NOTHUNKS
  1049. // Open on the 32 bit side first, then try and open 16 bit...
  1050. if (hic == NULL) {
  1051. pic->dwSmag = SMAG;
  1052. pic->hTask = (HTASK)GetCurrentTask();
  1053. hic = (HIC)ICOpenInternal(pic, fccType, fccHandler, &icinfo, &icopen, wMode);
  1054. }
  1055. ICLeaveCrit(&ICOpenCritSec);
  1056. return(hic);
  1057. }
  1058. /*****************************************************************************
  1059. * @doc EXTERNAL IC ICAPPS
  1060. *
  1061. * @api HIC | ICOpenFunction | This function opens
  1062. * a compressor or decompressor defined as a function.
  1063. *
  1064. * @parm DWORD | fccType | Specifies the type of compressor
  1065. * the caller is trying to open. For video, this is ICTYPE_VIDEO.
  1066. *
  1067. * @parm DWORD | fccHandler | Specifies a single preferred handler of the
  1068. * given type that should be tried first. Typically, this comes
  1069. * from the stream header in an AVI file.
  1070. *
  1071. * @parm UINT | wMode | Specifies a flag to defining the use of
  1072. * the compressor or decompressor.
  1073. * This parameter can contain one of the following values:
  1074. *
  1075. * @flag ICMODE_COMPRESS | Advises a compressor it is opened for compression.
  1076. *
  1077. * @flag ICMODE_FASTCOMPRESS | Advise a compressor it is open
  1078. * for fast (real-time) compression.
  1079. *
  1080. * @flag ICMODE_DECOMPRESS | Advises a decompressor it is opened for decompression.
  1081. *
  1082. * @flag ICMODE_FASTDECOMPRESS | Advises a decompressor it is opened
  1083. * for fast (real-time) decompression.
  1084. *
  1085. * @flag ICMODE_DRAW | Advises a decompressor it is opened
  1086. * to decompress an image and draw it directly to hardware.
  1087. *
  1088. * @flag ICMODE_QUERY | Advise a compressor or decompressor it is opened
  1089. * to obtain information.
  1090. *
  1091. * @parm FARPROC | lpfnHandler | Specifies a pointer to the function
  1092. * used as the compressor or decompressor.
  1093. *
  1094. * @rdesc Returns a handle to a compressor or decompressor
  1095. * if successful, otherwise it returns zero.
  1096. ****************************************************************************/
  1097. HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler)
  1098. {
  1099. ICOPEN icopen;
  1100. PIC pic;
  1101. DWORD dw;
  1102. if (IsBadCodePtr(lpfnHandler))
  1103. return NULL;
  1104. #ifndef NOTHUNKS
  1105. // lpfnHandler points to 16 bit code that will be used as a compressor.
  1106. // We do not want this to go over to the 32 bit side.
  1107. #endif
  1108. AnsiLowerBuff((LPSTR) &fccType, sizeof(DWORD));
  1109. AnsiLowerBuff((LPSTR) &fccHandler, sizeof(DWORD));
  1110. icopen.dwSize = sizeof(ICOPEN);
  1111. icopen.fccType = fccType;
  1112. icopen.fccHandler = fccHandler;
  1113. icopen.dwFlags = wMode;
  1114. pic = FindConverter(0L, 0L);
  1115. if (pic == NULL)
  1116. return NULL;
  1117. pic->dwSmag = SMAG;
  1118. pic->fccType = fccType;
  1119. pic->fccHandler = fccHandler;
  1120. pic->dwDriver = 0L;
  1121. pic->hDriver = NULL;
  1122. pic->DriverProc = (DRIVERPROC)lpfnHandler;
  1123. dw = ICSendMessage((HIC)pic, DRV_OPEN, 0, (DWORD)(LPVOID)&icopen);
  1124. if (dw == 0)
  1125. {
  1126. ICClose((HIC) pic);
  1127. return NULL;
  1128. }
  1129. pic->dwDriver = dw;
  1130. return (HIC)pic;
  1131. }
  1132. ////////////////////////////////////////////////////////////////////////////
  1133. ////////////////////////////////////////////////////////////////////////////
  1134. /*****************************************************************************
  1135. * @doc EXTERNAL IC ICAPPS
  1136. *
  1137. * @api LRESULT | ICClose | This function closes a compressor or decompressor.
  1138. *
  1139. * @parm HIC | hic | Specifies a handle to a compressor or decompressor.
  1140. *
  1141. * @rdesc Returns ICERR_OK if successful, otherwise it returns an error number.
  1142. *
  1143. ****************************************************************************/
  1144. LRESULT VFWAPI ICClose(HIC hic)
  1145. {
  1146. PIC pic = (PIC)hic;
  1147. V_HIC(hic);
  1148. #ifndef NOTHUNKS
  1149. if (pic->h32 != 0) {
  1150. LRESULT lres = ICClose32(pic->h32);
  1151. pic->dwSmag = GONE;
  1152. pic->fccType = 0L;
  1153. pic->fccHandler = 0L;
  1154. pic->dwDriver = 0;
  1155. pic->hDriver = NULL;
  1156. pic->DriverProc = NULL;
  1157. pic->h32 = 0; // Next user of this slot does not want h32 set
  1158. return(lres);
  1159. }
  1160. #endif //!NOTHUNKS
  1161. #ifdef DEBUG
  1162. {
  1163. char ach[80];
  1164. if (pic->hDriver)
  1165. GetModuleFileName(GetDriverModuleHandle (pic->hDriver), ach, sizeof(ach));
  1166. else
  1167. ach[0] = 0;
  1168. DPF(("ICClose(%04X) %4.4s.%4.4s %s\r\n", hic, (LPSTR)&pic->fccType, (LPSTR)&pic->fccHandler, (LPSTR)ach));
  1169. }
  1170. #endif
  1171. #ifdef DEBUG
  1172. ICDump();
  1173. #endif
  1174. ICEnterCrit(&ICOpenCritSec);
  1175. if (pic->dwDriver)
  1176. {
  1177. if (pic->DriverProc)
  1178. ICSendMessage((HIC)pic, DRV_CLOSE, 0, 0);
  1179. }
  1180. if (pic->hDriver)
  1181. FreeDriver(pic->hDriver);
  1182. pic->dwSmag = 0L;
  1183. pic->fccType = 0L;
  1184. pic->fccHandler = 0L;
  1185. pic->dwDriver = 0;
  1186. pic->hDriver = NULL;
  1187. pic->DriverProc = NULL;
  1188. ICLeaveCrit(&ICOpenCritSec);
  1189. return ICERR_OK;
  1190. }
  1191. ////////////////////////////////////////////////////////////////////////////
  1192. ////////////////////////////////////////////////////////////////////////////
  1193. /****************************************************************
  1194. * @doc EXTERNAL IC ICAPPS
  1195. *
  1196. * @api DWORD | ICCompress | This function compresses a single video
  1197. * image.
  1198. *
  1199. * @parm HIC | hic | Specifies the handle of the compressor to
  1200. * use.
  1201. *
  1202. * @parm DWORD | dwFlags | Specifies applicable flags for the compression.
  1203. * The following flag is defined:
  1204. *
  1205. * @flag ICCOMPRESS_KEYFRAME | Indicates that the compressor
  1206. * should make this frame a key frame.
  1207. *
  1208. * @parm LPBITMAPINFOHEADER | lpbiOutput | Specifies a far pointer
  1209. * to a <t BITMAPINFO> structure holding the output format.
  1210. *
  1211. * @parm LPVOID | lpData | Specifies a far pointer to output data buffer.
  1212. *
  1213. * @parm LPBITMAPINFOHEADER | lpbiInput | Specifies a far pointer
  1214. * to a <t BITMAPINFO> structure containing the input format.
  1215. *
  1216. * @parm LPVOID | lpBits | Specifies a far pointer to the input data buffer.
  1217. *
  1218. * @parm LPDWORD | lpckid | Not used.
  1219. *
  1220. * @parm LPDWORD | lpdwFlags | Specifies a far pointer to a <t DWORD>
  1221. * holding the return flags used in the AVI index. The following
  1222. * flag is defined:
  1223. *
  1224. * @flag AVIIF_KEYFRAME | Indicates this frame should be used as a key-frame.
  1225. *
  1226. * @parm LONG | lFrameNum | Specifies the frame number.
  1227. *
  1228. * @parm DWORD | dwFrameSize | Specifies the requested frame size in bytes.
  1229. * If set to zero, the compressor chooses the frame size.
  1230. *
  1231. * @parm DWORD | dwQuality | Specifies the requested quality value for the frame.
  1232. *
  1233. * @parm LPBITMAPINFOHEADER | lpbiPrev | Specifies a far pointer to
  1234. * a <t BITMAPINFO> structure holding the previous frame's format.
  1235. * This parameter is not used for fast temporal compression.
  1236. *
  1237. * @parm LPVOID | lpPrev | Specifies a far pointer to the
  1238. * previous frame's data buffer. This parameter is not used for fast
  1239. * temporal compression.
  1240. *
  1241. * @comm The <p lpData> buffer should be large enough to hold a compressed
  1242. * frame. You can obtain the size of this buffer by calling
  1243. * <f ICCompressGetSize>.
  1244. *
  1245. * Set the <p dwFrameSize> parameter to a requested frame
  1246. * size only if the compressor returns the VIDCF_CRUNCH flag in
  1247. * response to <f ICGetInfo>. If this flag is not set, or if a data
  1248. * rate is not specified, set this parameter to zero.
  1249. *
  1250. * Set the <p dwQuality> parameter to a quality value only
  1251. * if the compressor returns the VIDCF_QUALITY flag in response
  1252. * to <f ICGetInfo>. Without this flag, set this parameter to zero.
  1253. *
  1254. * @rdesc This function returns ICERR_OK if successful. Otherwise,
  1255. * it returns an error code.
  1256. *
  1257. * @xref <f ICCompressBegin> <f ICCompressEnd> <f ICCompressGetSize> <f ICGetInfo>
  1258. *
  1259. **********************************************************************/
  1260. DWORD VFWAPIV ICCompress(
  1261. HIC hic,
  1262. DWORD dwFlags, // flags
  1263. LPBITMAPINFOHEADER lpbiOutput, // output format
  1264. LPVOID lpData, // output data
  1265. LPBITMAPINFOHEADER lpbiInput, // format of frame to compress
  1266. LPVOID lpBits, // frame data to compress
  1267. LPDWORD lpckid, // ckid for data in AVI file
  1268. LPDWORD lpdwFlags, // flags in the AVI index.
  1269. LONG lFrameNum, // frame number of seq.
  1270. DWORD dwFrameSize, // reqested size in bytes. (if non zero)
  1271. DWORD dwQuality, // quality
  1272. LPBITMAPINFOHEADER lpbiPrev, // format of previous frame
  1273. LPVOID lpPrev) // previous frame
  1274. {
  1275. #ifdef WIN32
  1276. // We cannot rely on the stack alignment giving us the right layout
  1277. ICCOMPRESS icc;
  1278. icc.dwFlags = dwFlags;
  1279. icc.lpbiOutput = lpbiOutput;
  1280. icc.lpOutput = lpData;
  1281. icc.lpbiInput = lpbiInput;
  1282. icc.lpInput = lpBits;
  1283. icc.lpckid = lpckid;
  1284. icc.lpdwFlags = lpdwFlags;
  1285. icc.lFrameNum = lFrameNum;
  1286. icc.dwFrameSize = dwFrameSize;
  1287. icc.dwQuality = dwQuality;
  1288. icc.lpbiPrev = lpbiPrev;
  1289. icc.lpPrev = lpPrev;
  1290. return ICSendMessage(hic, ICM_COMPRESS, (DWORD)(LPVOID)&icc, sizeof(ICCOMPRESS));
  1291. // NOTE: We do NOT copy any results from this temporary structure back
  1292. // to the input variables.
  1293. #else
  1294. return ICSendMessage(hic, ICM_COMPRESS, (DWORD)(LPVOID)&dwFlags, sizeof(ICCOMPRESS));
  1295. #endif
  1296. }
  1297. /************************************************************************
  1298. decompression functions
  1299. ************************************************************************/
  1300. /*******************************************************************
  1301. * @doc EXTERNAL IC ICAPPS
  1302. *
  1303. * @api DWORD | ICDecompress | The function decompresses a single video frame.
  1304. *
  1305. * @parm HIC | hic | Specifies a handle to the decompressor to use.
  1306. *
  1307. * @parm DWORD | dwFlags | Specifies applicable flags for decompression.
  1308. * The following flags are defined:
  1309. *
  1310. * @flag ICDECOMPRESS_HURRYUP | Indicates the decompressor should try to
  1311. * decompress at a faster rate. When an application uses this flag,
  1312. * it should not draw the decompressed data.
  1313. *
  1314. * @flag ICDECOMPRESS_UPDATE | Indicates that the screen is being updated.
  1315. *
  1316. * @flag ICDECOMPRESS_PREROLL | Indicates that this frame will not actually
  1317. * be drawn, because it is before the point in the movie where play
  1318. * will start.
  1319. *
  1320. * @flag ICDECOMPRESS_NULLFRAME | Indicates that this frame does not actually
  1321. * have any data, and the decompressed image should be left the same.
  1322. *
  1323. * @flag ICDECOMPRESS_NOTKEYFRAME | Indicates that this frame is not a
  1324. * key frame.
  1325. *
  1326. * @parm LPBITMAPINFOHEADER | lpbiFormat | Specifies a far pointer
  1327. * to a <t BITMAPINFO> structure containing the format of
  1328. * the compressed data.
  1329. *
  1330. * @parm LPVOID | lpData | Specifies a far pointer to the input data.
  1331. *
  1332. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a far pointer to a
  1333. * <t BITMAPINFO> structure containing the output format.
  1334. *
  1335. * @parm LPVOID | lpBits | Specifies a far pointer to a data buffer for the
  1336. * decompressed data.
  1337. *
  1338. * @comm The <p lpBits> parameter should point to a buffer large
  1339. * enough to hold the decompressed data. Applications can obtain
  1340. * the size of this buffer with <f ICDecompressGetSize>.
  1341. *
  1342. * @rdesc Returns ICERR_OK on success, otherwise it returns an error code.
  1343. *
  1344. * @xref <f ICDecompressBegin< <f ICDecompressEnd> <f ICDecompressGetSize>
  1345. *
  1346. ********************************************************************/
  1347. DWORD VFWAPIV ICDecompress(
  1348. HIC hic,
  1349. DWORD dwFlags, // flags (from AVI index...)
  1350. LPBITMAPINFOHEADER lpbiFormat, // BITMAPINFO of compressed data
  1351. // biSizeImage has the chunk size
  1352. // biCompression has the ckid (AVI only)
  1353. LPVOID lpData, // data
  1354. LPBITMAPINFOHEADER lpbi, // DIB to decompress to
  1355. LPVOID lpBits)
  1356. {
  1357. #if 1
  1358. ICDECOMPRESS icd;
  1359. // We cannot rely on the stack alignment giving us the right layout
  1360. icd.dwFlags = dwFlags;
  1361. icd.lpbiInput = lpbiFormat;
  1362. icd.lpInput = lpData;
  1363. icd.lpbiOutput = lpbi;
  1364. icd.lpOutput = lpBits;
  1365. icd.ckid = 0;
  1366. return ICSendMessage(hic, ICM_DECOMPRESS, (DWORD)(LPVOID)&icd, sizeof(ICDECOMPRESS));
  1367. #else
  1368. return ICSendMessage(hic, ICM_DECOMPRESS, (DWORD)(LPVOID)&dwFlags, sizeof(ICDECOMPRESS));
  1369. #endif
  1370. }
  1371. /************************************************************************
  1372. drawing functions
  1373. ************************************************************************/
  1374. /**********************************************************************
  1375. * @doc EXTERNAL IC ICAPPS
  1376. *
  1377. * @api DWORD | ICDrawBegin | This function starts decompressing
  1378. * data directly to the screen.
  1379. *
  1380. * @parm HIC | hic | Specifies a handle to the decompressor to use.
  1381. *
  1382. * @parm DWORD | dwFlags | Specifies flags for the decompression. The
  1383. * following flags are defined:
  1384. *
  1385. * @flag ICDRAW_QUERY | Determines if the decompressor can handle
  1386. * the decompression. The driver does not actually decompress the data.
  1387. *
  1388. * @flag ICDRAW_FULLSCREEN | Tells the decompressor to draw
  1389. * the decompressed data on the full screen.
  1390. *
  1391. * @flag ICDRAW_HDC | Indicates the decompressor should use the window
  1392. * handle specified by <p hwnd> and the display context
  1393. * handle specified by <p hdc> for drawing the decompressed data.
  1394. *
  1395. * @flag ICDRAW_ANIMATE | Indicates the palette might be animated.
  1396. *
  1397. * @flag ICDRAW_CONTINUE | Indicates drawing is a
  1398. * continuation of the previous frame.
  1399. *
  1400. * @flag ICDRAW_MEMORYDC | Indicates the display context is offscreen.
  1401. *
  1402. * @flag ICDRAW_UPDATING | Indicates the frame is being
  1403. * updated rather than played.
  1404. *
  1405. * @parm HPALETTE | hpal | Specifies a handle to the palette used for drawing.
  1406. *
  1407. * @parm HWND | hwnd | Specifies a handle for the window used for drawing.
  1408. *
  1409. * @parm HDC | hdc | Specifies the display context used for drawing.
  1410. *
  1411. * @parm int | xDst | Specifies the x-position of the upper-right
  1412. * corner of the destination rectangle.
  1413. *
  1414. * @parm int | yDst | Specifies the y-position of the upper-right
  1415. * corner of the destination rectangle.
  1416. *
  1417. * @parm int | dxDst | Specifies the width of the destination rectangle.
  1418. *
  1419. * @parm int | dyDst | Specifies the height of the destination rectangle.
  1420. *
  1421. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a far pointer to
  1422. * a <t BITMAPINFO> structure containing the format of
  1423. * the input data to be decompressed.
  1424. *
  1425. * @parm int | xSrc | Specifies the x-position of the upper-right corner
  1426. * of the source rectangle.
  1427. *
  1428. * @parm int | ySrc | Specifies the y-position of the upper-right corner
  1429. * of the source rectangle.
  1430. *
  1431. * @parm int | dxSrc | Specifies the width of the source rectangle.
  1432. *
  1433. * @parm int | dySrc | Specifies the height of the source rectangle.
  1434. *
  1435. * @parm DWORD | dwRate | Specifies the data rate. The
  1436. * data rate in frames per second equals <p dwRate> divided
  1437. * by <p dwScale>.
  1438. *
  1439. * @parm DWORD | dwScale | Specifies the data rate.
  1440. *
  1441. * @comm Decompressors use the <p hwnd> and <p hdc> parameters
  1442. * only if an application sets ICDRAW_HDC flag in <p dwFlags>.
  1443. * It will ignore these parameters if an application sets
  1444. * the ICDRAW_FULLSCREEN flag. When an application uses the
  1445. * ICDRAW_FULLSCREEN flag, it should set <p hwnd> and <p hdc>
  1446. * to NULL.
  1447. *
  1448. * The destination rectangle is specified only if ICDRAW_HDC is used.
  1449. * If an application sets the ICDRAW_FULLSCREEN flag, the destination
  1450. * rectangle is ignored and its parameters can be set to zero.
  1451. *
  1452. * The source rectangle is relative to the full video frame.
  1453. * The portion of the video frame specified by the source
  1454. * rectangle will be stretched to fit in the destination rectangle.
  1455. *
  1456. * @rdesc Returns ICERR_OK if it can handle the decompression, otherwise
  1457. * it returns ICERR_UNSUPPORTED.
  1458. *
  1459. * @xref <f ICDraw> <f ICDrawEnd>
  1460. *
  1461. *********************************************************************/
  1462. DWORD VFWAPIV ICDrawBegin(
  1463. HIC hic,
  1464. DWORD dwFlags, // flags
  1465. HPALETTE hpal, // palette to draw with
  1466. HWND hwnd, // window to draw to
  1467. HDC hdc, // HDC to draw to
  1468. int xDst, // destination rectangle
  1469. int yDst,
  1470. int dxDst,
  1471. int dyDst,
  1472. LPBITMAPINFOHEADER lpbi, // format of frame to draw
  1473. int xSrc, // source rectangle
  1474. int ySrc,
  1475. int dxSrc,
  1476. int dySrc,
  1477. DWORD dwRate, // frames/second = (dwRate/dwScale)
  1478. DWORD dwScale)
  1479. {
  1480. #ifdef WIN32
  1481. ICDRAWBEGIN icdraw;
  1482. icdraw.dwFlags = dwFlags;
  1483. icdraw.hpal = hpal;
  1484. icdraw.hwnd = hwnd;
  1485. icdraw.hdc = hdc;
  1486. icdraw.xDst = xDst;
  1487. icdraw.yDst = yDst;
  1488. icdraw.dxDst = dxDst;
  1489. icdraw.dyDst = dyDst;
  1490. icdraw.lpbi = lpbi;
  1491. icdraw.xSrc = xSrc;
  1492. icdraw.ySrc = ySrc;
  1493. icdraw.dxSrc = dxSrc;
  1494. icdraw.dySrc = dySrc;
  1495. icdraw.dwRate = dwRate;
  1496. icdraw.dwScale = dwScale;
  1497. return ICSendMessage(hic, ICM_DRAW_BEGIN, (DWORD)(LPVOID)&icdraw, sizeof(ICDRAWBEGIN));
  1498. #else
  1499. return ICSendMessage(hic, ICM_DRAW_BEGIN, (DWORD)(LPVOID)&dwFlags, sizeof(ICDRAWBEGIN));
  1500. #endif
  1501. }
  1502. /**********************************************************************
  1503. * @doc EXTERNAL IC ICAPPS
  1504. *
  1505. * @api DWORD | ICDraw | This function decompress an image for drawing.
  1506. *
  1507. * @parm HIC | hic | Specifies a handle to an decompressor.
  1508. *
  1509. * @parm DWORD | dwFlags | Specifies any flags for the decompression.
  1510. * The following flags are defined:
  1511. *
  1512. * @flag ICDRAW_HURRYUP | Indicates the decompressor should
  1513. * just buffer the data if it needs it for decompression
  1514. * and not draw it to the screen.
  1515. *
  1516. * @flag ICDRAW_UPDATE | Tells the decompressor to update the screen based
  1517. * on data previously received. Set <p lpData> to NULL when
  1518. * this flag is used.
  1519. *
  1520. * @flag ICDRAW_PREROLL | Indicates that this frame of video occurs before
  1521. * actual playback should start. For example, if playback is to
  1522. * begin on frame 10, and frame 0 is the nearest previous keyframe,
  1523. * frames 0 through 9 are sent to the driver with the ICDRAW_PREROLL
  1524. * flag set. The driver needs this data so it can displya frmae 10
  1525. * properly, but frames 0 through 9 need not be individually displayed.
  1526. *
  1527. * @flag ICDRAW_NULLFRAME | Indicates that this frame does not actually
  1528. * have any data, and the previous frame should be redrawn.
  1529. *
  1530. * @flag ICDRAW_NOTKEYFRAME | Indicates that this frame is not a
  1531. * key frame.
  1532. *
  1533. * @parm LPVOID | lpFormat | Specifies a far pointer to a
  1534. * <t BITMAPINFOHEADER> structure containing the input
  1535. * format of the data.
  1536. *
  1537. * @parm LPVOID | lpData | Specifies a far pointer to the actual input data.
  1538. *
  1539. * @parm DWORD | cbData | Specifies the size of the input data (in bytes).
  1540. *
  1541. * @parm LONG | lTime | Specifies the time to draw this frame based on the
  1542. * time scale sent with <f ICDrawBegin>.
  1543. *
  1544. * @comm This function is used to decompress the image data for drawing
  1545. * by the decompressor. Actual drawing of frames does not occur
  1546. * until <f ICDrawStart> is called. The application should be sure to
  1547. * pre-buffer the required number of frames before drawing is started
  1548. * (you can obtain this value with <f ICGetBuffersWanted>).
  1549. *
  1550. * @rdesc Returns ICERR_OK on success, otherwise it returns an appropriate error
  1551. * number.
  1552. *
  1553. * @xref <f ICDrawBegin> <f ICDrawEnd> <f ICDrawStart> <f ICDrawStop> <f ICGetBuffersRequired>
  1554. *
  1555. **********************************************************************/
  1556. DWORD VFWAPIV ICDraw(
  1557. HIC hic,
  1558. DWORD dwFlags, // flags
  1559. LPVOID lpFormat, // format of frame to decompress
  1560. LPVOID lpData, // frame data to decompress
  1561. DWORD cbData, // size in bytes of data
  1562. LONG lTime) // time to draw this frame (see drawbegin dwRate and dwScale)
  1563. {
  1564. #ifdef WIN32
  1565. ICDRAW icdraw;
  1566. icdraw.dwFlags = dwFlags;
  1567. icdraw.lpFormat = lpFormat;
  1568. icdraw.lpData = lpData;
  1569. icdraw.cbData = cbData;
  1570. icdraw.lTime = lTime;
  1571. return ICSendMessage(hic, ICM_DRAW, (DWORD)(LPVOID)&icdraw, sizeof(ICDRAW));
  1572. #else
  1573. return ICSendMessage(hic, ICM_DRAW, (DWORD)(LPVOID)&dwFlags, sizeof(ICDRAW));
  1574. #endif
  1575. }
  1576. /*****************************************************************************
  1577. * @doc EXTERNAL IC ICAPPS
  1578. *
  1579. * @api HIC | ICGetDisplayFormat | This function returns the "best"
  1580. * format available for display a compressed image. The function
  1581. * will also open a compressor if a handle to an open compressor
  1582. * is not specified.
  1583. *
  1584. * @parm HIC | hic | Specifies the decompressor that should be used. If
  1585. * this is NULL, an appropriate compressor will be opened and returned.
  1586. *
  1587. * @parm LPBITMAPINFOHEADER | lpbiIn | Specifies a pointer to
  1588. * <t BITMAPINFOHEADER> structure containing the compressed format.
  1589. *
  1590. * @parm LPBITMAPINFOHEADER | lpbiOut | Specifies a pointer
  1591. * to a buffer used to return the decompressed format.
  1592. * The buffer should be large enough for a <t BITMAPINFOHEADER>
  1593. * structure and 256 color entries.
  1594. *
  1595. * @parm int | BitDepth | If non-zero, specifies the preferred bit depth.
  1596. *
  1597. * @parm int | dx | If non-zero, specifies the width to which the image
  1598. * is to be stretched.
  1599. *
  1600. * @parm int | dy | If non-zero, specifies the height to which the image
  1601. * is to be stretched.
  1602. *
  1603. * @rdesc Returns a handle to a decompressor if successful, otherwise, it
  1604. * returns zero.
  1605. ****************************************************************************/
  1606. HIC VFWAPI ICGetDisplayFormat(HIC hic, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, int BitDepth, int dx, int dy)
  1607. {
  1608. DWORD dw;
  1609. HDC hdc;
  1610. BOOL fNukeHic = (hic == NULL);
  1611. static int ScreenBitDepth = -1;
  1612. if (hic == NULL)
  1613. hic = ICDecompressOpen(ICTYPE_VIDEO, 0L, lpbiIn, NULL);
  1614. if (hic == NULL)
  1615. return NULL;
  1616. //
  1617. // dy = 0 and dy = 0 means don't stretch.
  1618. //
  1619. if (dx == (int)lpbiIn->biWidth && dy == (int)lpbiIn->biHeight)
  1620. dx = dy = 0;
  1621. //
  1622. // ask the compressor if it likes the format.
  1623. //
  1624. dw = ICDecompressQuery(hic, lpbiIn, NULL);
  1625. if (dw != ICERR_OK)
  1626. {
  1627. DPF(("Decompressor did not recognize the input data format\r\n"));
  1628. goto error;
  1629. }
  1630. try_again:
  1631. //
  1632. // ask the compressor first. (so it can set the palette)
  1633. // this is a HACK, we will send the ICM_GET_PALETTE message later.
  1634. //
  1635. dw = ICDecompressGetFormat(hic, lpbiIn, lpbiOut);
  1636. //
  1637. // init the output format
  1638. //
  1639. *lpbiOut = *lpbiIn;
  1640. lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
  1641. lpbiOut->biCompression = BI_RGB;
  1642. //
  1643. // default to the screen depth.
  1644. //
  1645. if (BitDepth == 0)
  1646. {
  1647. if (ScreenBitDepth < 0)
  1648. {
  1649. DWORD FAR PASCAL DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi);
  1650. hdc = GetDC(NULL);
  1651. ScreenBitDepth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  1652. ReleaseDC(NULL, hdc);
  1653. if (ScreenBitDepth == 15)
  1654. ScreenBitDepth = 16;
  1655. if (ScreenBitDepth < 8)
  1656. ScreenBitDepth = 8;
  1657. //
  1658. // only try 16 bpp if the display supports drawing it.
  1659. //
  1660. if (ScreenBitDepth == 16)
  1661. {
  1662. lpbiOut->biBitCount = 16;
  1663. if (!DrawDibProfileDisplay(lpbiOut))
  1664. ScreenBitDepth = 24;
  1665. }
  1666. if (ScreenBitDepth > 24)
  1667. {
  1668. lpbiOut->biBitCount = 32;
  1669. if (!DrawDibProfileDisplay(lpbiOut))
  1670. ScreenBitDepth = 24;
  1671. }
  1672. }
  1673. #ifdef DEBUG
  1674. ScreenBitDepth = GetProfileInt(TEXT("DrawDib"),
  1675. TEXT("ScreenBitDepth"),
  1676. ScreenBitDepth);
  1677. #endif
  1678. BitDepth = ScreenBitDepth;
  1679. }
  1680. //
  1681. // always try 8bit first for '8' bit data
  1682. //
  1683. if (lpbiIn->biBitCount == 8)
  1684. BitDepth = 8;
  1685. //
  1686. // lets suggest a format to the device.
  1687. //
  1688. try_bit_depth:
  1689. lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
  1690. lpbiOut->biCompression = BI_RGB;
  1691. lpbiOut->biBitCount = BitDepth;
  1692. //
  1693. // should we suggest a stretched decompress
  1694. //
  1695. if (dx > 0 && dy > 0)
  1696. {
  1697. lpbiOut->biWidth = dx;
  1698. lpbiOut->biHeight = dy;
  1699. }
  1700. lpbiOut->biSizeImage = (DWORD)(UINT)DIBWIDTHBYTES(*lpbiOut) *
  1701. (DWORD)(UINT)lpbiOut->biHeight;
  1702. //
  1703. // ask the compressor if it likes the suggested format.
  1704. //
  1705. dw = ICDecompressQuery(hic, lpbiIn, lpbiOut);
  1706. //
  1707. // if it likes it then return success.
  1708. //
  1709. if (dw == ICERR_OK)
  1710. goto success;
  1711. // 8: 8, 16,24,32,X
  1712. // 16: 16,24,32,X
  1713. // 24: 24,32,16,X
  1714. // 32: 32,24,16,X
  1715. //
  1716. // try another bit depth in this order 8,16,24,32
  1717. //
  1718. if (BitDepth <= 8)
  1719. {
  1720. BitDepth = 16;
  1721. goto try_bit_depth;
  1722. }
  1723. if (BitDepth == 16)
  1724. {
  1725. BitDepth = 24;
  1726. goto try_bit_depth;
  1727. }
  1728. if (BitDepth == 24)
  1729. {
  1730. BitDepth = 32;
  1731. goto try_bit_depth;
  1732. }
  1733. if (BitDepth != 32)
  1734. {
  1735. BitDepth = 32;
  1736. goto try_bit_depth;
  1737. }
  1738. if (dx > 0 && dy > 0)
  1739. {
  1740. dx = 0;
  1741. dy = 0;
  1742. //
  1743. // try to find a non stretched format. but don't let the
  1744. // device dither if we are going to stretch!
  1745. //
  1746. if (lpbiIn->biBitCount > 8)
  1747. BitDepth = 16;
  1748. else
  1749. BitDepth = 0;
  1750. goto try_again;
  1751. }
  1752. else
  1753. {
  1754. //
  1755. // let the compressor suggest a format
  1756. //
  1757. dw = ICDecompressGetFormat(hic, lpbiIn, lpbiOut);
  1758. if (dw == ICERR_OK)
  1759. goto success;
  1760. }
  1761. error:
  1762. if (hic && fNukeHic)
  1763. ICClose(hic);
  1764. return NULL;
  1765. success:
  1766. if (lpbiOut->biBitCount == 8)
  1767. ICDecompressGetPalette(hic, lpbiIn, lpbiOut);
  1768. return hic;
  1769. }
  1770. /*****************************************************************************
  1771. * @doc EXTERNAL IC ICAPPS
  1772. *
  1773. * @api HIC | ICLocate | This function finds a compressor or decompressor
  1774. * that can handle images with the formats specified, or it finds a
  1775. * driver that can decompress an image with a specified
  1776. * format directly to hardware. Applications must close the
  1777. * compressor when it has finished using the compressor.
  1778. *
  1779. * @parm DWORD | fccType | Specifies the type of compressor
  1780. * the caller is trying to open. For video, this is ICTYPE_VIDEO.
  1781. *
  1782. * @parm DWORD | fccHandler | Specifies a single preferred handler of the
  1783. * given type that should be tried first. Typically, this comes
  1784. * from the stream header in an AVI file.
  1785. *
  1786. * @parm LPBITMAPINFOHEADER | lpbiIn | Specifies a pointer to
  1787. * <t BITMAPINFOHEADER> structure defining the input format.
  1788. * A compressor handle will not be returned unless it
  1789. * can handle this format.
  1790. *
  1791. * @parm LPBITMAPINFOHEADER | lpbiOut | Specifies zero or a pointer to
  1792. * <t BITMAPINFOHEADER> structure defining an optional decompressed
  1793. * format. If <p lpbiOut> is nonzero, a compressor handle will not
  1794. * be returned unless it can create this output format.
  1795. *
  1796. * @parm WORD | wFlags | Specifies a flag to defining the use of the compressor.
  1797. * This parameter must contain one of the following values:
  1798. *
  1799. * @flag ICMODE_COMPRESS | Indicates the compressor should
  1800. * be able to compress an image with a format defined by <p lpbiIn>
  1801. * to the format defined by <p lpbiOut>.
  1802. *
  1803. * @flag ICMODE_DECOMPRESS | Indicates the decompressor should
  1804. * be able to decompress an image with a format defined by <p lpbiIn>
  1805. * to the format defined by <p lpbiOut>.
  1806. *
  1807. * @flag ICMODE_FASTDECOMPRESS | Has the same definition as ICMODE_DECOMPRESS except the
  1808. * decompressor is being used for a real-time operation and should trade off speed
  1809. * for quality if possible.
  1810. *
  1811. * @flag ICMODE_FASTCOMPRESS | Has the same definition as ICMODE_COMPRESS except the
  1812. * compressor is being used for a real-time operation and should trade off speed
  1813. * for quality if possible.
  1814. *
  1815. * @flag ICMODE_DRAW | Indicates the decompressor should
  1816. * be able to decompress an image with a format defined by <p lpbiIn>
  1817. * and draw it directly to hardware.
  1818. *
  1819. * @rdesc Returns a handle to a compressor or decompressor
  1820. * if successful, otherwise it returns zero.
  1821. ****************************************************************************/
  1822. HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, WORD wFlags)
  1823. {
  1824. HIC hic=NULL;
  1825. int i;
  1826. ICINFO icinfo;
  1827. UINT msg;
  1828. if (fccType == 0)
  1829. return NULL;
  1830. switch (wFlags)
  1831. {
  1832. case ICMODE_FASTCOMPRESS:
  1833. case ICMODE_COMPRESS:
  1834. msg = ICM_COMPRESS_QUERY;
  1835. break;
  1836. case ICMODE_FASTDECOMPRESS:
  1837. case ICMODE_DECOMPRESS:
  1838. msg = ICM_DECOMPRESS_QUERY;
  1839. break;
  1840. case ICMODE_DRAW:
  1841. msg = ICM_DRAW_QUERY;
  1842. break;
  1843. default:
  1844. return NULL;
  1845. }
  1846. if (fccHandler)
  1847. {
  1848. hic = ICOpen(fccType, fccHandler, wFlags);
  1849. if (hic && ICSendMessage(hic, msg, (DWORD)lpbiIn, (DWORD)lpbiOut) == ICERR_OK)
  1850. return hic;
  1851. else if (hic)
  1852. ICClose(hic);
  1853. }
  1854. if (fccType == ICTYPE_VIDEO && lpbiIn)
  1855. {
  1856. if (lpbiIn->biCompression > 256)
  1857. {
  1858. hic = ICOpen(fccType, lpbiIn->biCompression, wFlags);
  1859. if (hic && ICSendMessage(hic, msg, (DWORD)lpbiIn, (DWORD)lpbiOut) == ICERR_OK)
  1860. return hic;
  1861. else if (hic)
  1862. ICClose(hic);
  1863. }
  1864. }
  1865. //
  1866. // Search through all of the compressors, to see if one can do what we
  1867. // want.
  1868. //
  1869. for (i=0; ICInfo(fccType, i, &icinfo); i++)
  1870. {
  1871. hic = ICOpen(fccType, icinfo.fccHandler, wFlags);
  1872. if (hic == NULL)
  1873. continue;
  1874. if (ICSendMessage(hic, msg, (DWORD)lpbiIn, (DWORD)lpbiOut) != ICERR_OK)
  1875. {
  1876. ICClose(hic);
  1877. continue;
  1878. }
  1879. return hic;
  1880. }
  1881. return NULL;
  1882. }
  1883. /*****************************************************************************
  1884. * @doc INTERNAL IC
  1885. *
  1886. * @api HDRVR | LoadDriver | load a driver
  1887. *
  1888. ****************************************************************************/
  1889. static HDRVR LoadDriver(LPSTR szDriver, DRIVERPROC FAR *lpDriverProc)
  1890. {
  1891. HMODULE hModule;
  1892. UINT u;
  1893. DRIVERPROC DriverProc;
  1894. BOOL fWow;
  1895. HDRVR hDriver;
  1896. fWow = IsWow();
  1897. if (fWow)
  1898. {
  1899. u = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  1900. hModule = LoadLibrary(szDriver);
  1901. SetErrorMode(u);
  1902. if (hModule <= HINSTANCE_ERROR)
  1903. return NULL;
  1904. hDriver = (HMODULE) hModule;
  1905. }
  1906. else
  1907. {
  1908. hDriver = OpenDriver (szDriver, NULL, NULL);
  1909. if (!hDriver)
  1910. return NULL;
  1911. hModule = GetDriverModuleHandle (hDriver);
  1912. }
  1913. DPF(("LoadDriver: %s\r\n", szDriver));
  1914. DriverProc = (DRIVERPROC)GetProcAddress(hModule, szDriverProc);
  1915. if (DriverProc == NULL)
  1916. {
  1917. if (fWow)
  1918. {
  1919. FreeLibrary(hModule);
  1920. }
  1921. else
  1922. {
  1923. CloseDriver (hDriver, 0L, 0L);
  1924. }
  1925. return NULL;
  1926. }
  1927. if (fWow && GetModuleUsage(hModule) == 1) //!!!this is not exacly like USER
  1928. {
  1929. if (!DriverProc(0, (HDRVR)1, DRV_LOAD, 0L, 0L))
  1930. {
  1931. FreeLibrary(hModule);
  1932. return NULL;
  1933. }
  1934. DriverProc(0, (HDRVR)1, DRV_ENABLE, 0L, 0L);
  1935. }
  1936. CacheModule (hModule);
  1937. *lpDriverProc = DriverProc;
  1938. return hDriver;
  1939. }
  1940. /*****************************************************************************
  1941. * @doc INTERNAL IC
  1942. *
  1943. * @api void | FreeDriver | unload a driver
  1944. *
  1945. ****************************************************************************/
  1946. static void FreeDriver(HDRVR hDriver)
  1947. {
  1948. if (!IsWow())
  1949. {
  1950. CloseDriver (hDriver, 0L, 0L);
  1951. }
  1952. else
  1953. {
  1954. if (GetModuleUsage((HMODULE) hDriver) == 1)
  1955. {
  1956. DRIVERPROC DriverProc;
  1957. DriverProc = (DRIVERPROC)GetProcAddress((HMODULE) hDriver, szDriverProc);
  1958. if (DriverProc)
  1959. {
  1960. DriverProc(0, (HDRVR)1, DRV_DISABLE, 0L, 0L);
  1961. DriverProc(0, (HDRVR)1, DRV_FREE, 0L, 0L);
  1962. }
  1963. }
  1964. FreeLibrary((HMODULE) hDriver);
  1965. }
  1966. }
  1967. #ifdef DEBUG_RETAIL
  1968. /************************************************************************
  1969. messages.
  1970. ************************************************************************/
  1971. struct {
  1972. UINT msg;
  1973. char *szMsg;
  1974. } aMsg[] = {
  1975. DRV_OPEN , "DRV_OPEN",
  1976. DRV_CLOSE , "DRV_CLOSE",
  1977. ICM_GETSTATE , "ICM_GETSTATE",
  1978. ICM_SETSTATE , "ICM_SETSTATE",
  1979. ICM_GETINFO , "ICM_GETINFO",
  1980. ICM_CONFIGURE , "ICM_CONFIGURE",
  1981. ICM_ABOUT , "ICM_ABOUT",
  1982. ICM_GETERRORTEXT , "ICM_GETERRORTEXT",
  1983. ICM_GETFORMATNAME , "ICM_GETFORMATNAME",
  1984. ICM_ENUMFORMATS , "ICM_ENUMFORMATS",
  1985. ICM_GETDEFAULTQUALITY , "ICM_GETDEFAULTQUALITY",
  1986. ICM_GETQUALITY , "ICM_GETQUALITY",
  1987. ICM_SETQUALITY , "ICM_SETQUALITY",
  1988. ICM_COMPRESS_GET_FORMAT , "ICM_COMPRESS_GET_FORMAT",
  1989. ICM_COMPRESS_GET_SIZE , "ICM_COMPRESS_GET_SIZE",
  1990. ICM_COMPRESS_QUERY , "ICM_COMPRESS_QUERY",
  1991. ICM_COMPRESS_BEGIN , "ICM_COMPRESS_BEGIN",
  1992. ICM_COMPRESS , "ICM_COMPRESS",
  1993. ICM_COMPRESS_END , "ICM_COMPRESS_END",
  1994. ICM_DECOMPRESS_GET_FORMAT , "ICM_DECOMPRESS_GET_FORMAT",
  1995. ICM_DECOMPRESS_QUERY , "ICM_DECOMPRESS_QUERY",
  1996. ICM_DECOMPRESS_BEGIN , "ICM_DECOMPRESS_BEGIN",
  1997. ICM_DECOMPRESS , "ICM_DECOMPRESS",
  1998. ICM_DECOMPRESS_END , "ICM_DECOMPRESS_END",
  1999. ICM_DECOMPRESS_SET_PALETTE , "ICM_DECOMPRESS_SET_PALETTE",
  2000. ICM_DECOMPRESS_GET_PALETTE , "ICM_DECOMPRESS_GET_PALETTE",
  2001. ICM_DECOMPRESSEX_QUERY , "ICM_DECOMPRESSEX_QUERY",
  2002. ICM_DECOMPRESSEX_BEGIN , "ICM_DECOMPRESSEX_BEGIN",
  2003. ICM_DECOMPRESSEX , "ICM_DECOMPRESSEX",
  2004. ICM_DECOMPRESSEX_END , "ICM_DECOMPRESSEX_END",
  2005. ICM_DRAW_QUERY , "ICM_DRAW_QUERY",
  2006. ICM_DRAW_BEGIN , "ICM_DRAW_BEGIN",
  2007. ICM_DRAW_GET_PALETTE , "ICM_DRAW_GET_PALETTE",
  2008. ICM_DRAW_UPDATE , "ICM_DRAW_UPDATE",
  2009. ICM_DRAW_START , "ICM_DRAW_START",
  2010. ICM_DRAW_STOP , "ICM_DRAW_STOP",
  2011. ICM_DRAW_BITS , "ICM_DRAW_BITS",
  2012. ICM_DRAW_END , "ICM_DRAW_END",
  2013. ICM_DRAW_GETTIME , "ICM_DRAW_GETTIME",
  2014. ICM_DRAW , "ICM_DRAW",
  2015. ICM_DRAW_WINDOW , "ICM_DRAW_WINDOW",
  2016. ICM_DRAW_SETTIME , "ICM_DRAW_SETTIME",
  2017. ICM_DRAW_REALIZE , "ICM_DRAW_REALIZE",
  2018. ICM_GETBUFFERSWANTED , "ICM_GETBUFFERSWANTED",
  2019. ICM_GETDEFAULTKEYFRAMERATE , "ICM_GETDEFAULTKEYFRAMERATE",
  2020. ICM_COMPRESS_FRAMES_INFO , "ICM_COMPRESS_FRAMES_INFO",
  2021. ICM_COMPRESS_FRAMES , "ICM_COMPRESS_FRAMES",
  2022. ICM_SET_STATUS_PROC , "ICM_SET_STATUS_PROC",
  2023. ICM_ENUM_FORMATS , "ICM_ENUM_FORMATS",
  2024. ICM_GET_FORMAT_NAME , "ICM_GET_FORMAT_NAME",
  2025. 0 , NULL
  2026. };
  2027. struct {
  2028. LRESULT err;
  2029. char *szErr;
  2030. } aErr[] = {
  2031. ICERR_DONTDRAW , "ICERR_DONTDRAW",
  2032. ICERR_NEWPALETTE , "ICERR_NEWPALETTE",
  2033. ICERR_UNSUPPORTED , "ICERR_UNSUPPORTED",
  2034. ICERR_BADFORMAT , "ICERR_BADFORMAT",
  2035. ICERR_MEMORY , "ICERR_MEMORY",
  2036. ICERR_INTERNAL , "ICERR_INTERNAL",
  2037. ICERR_BADFLAGS , "ICERR_BADFLAGS",
  2038. ICERR_BADPARAM , "ICERR_BADPARAM",
  2039. ICERR_BADSIZE , "ICERR_BADSIZE",
  2040. ICERR_BADHANDLE , "ICERR_BADHANDLE",
  2041. ICERR_CANTUPDATE , "ICERR_CANTUPDATE",
  2042. ICERR_ERROR , "ICERR_ERROR",
  2043. ICERR_BADBITDEPTH , "ICERR_BADBITDEPTH",
  2044. ICERR_BADIMAGESIZE , "ICERR_BADIMAGESIZE",
  2045. ICERR_OK , "ICERR_OK"
  2046. };
  2047. static BOOL fDebug = -1;
  2048. static DWORD dwTime;
  2049. void ICDebugMessage(HIC hic, UINT msg, DWORD dw1, DWORD dw2)
  2050. {
  2051. int i;
  2052. if (!fDebug)
  2053. return;
  2054. for (i=0; aMsg[i].msg && aMsg[i].msg != msg; i++)
  2055. ;
  2056. if (aMsg[i].msg == 0)
  2057. RPF(("ICM(%04X,ICM_%04X,%08lX,%08lX)", hic, msg, dw1, dw2));
  2058. else
  2059. RPF(("ICM(%04X,%s,%08lX,%08lX)", hic, (LPSTR)aMsg[i].szMsg, dw1, dw2));
  2060. dwTime = timeGetTime();
  2061. }
  2062. LRESULT ICDebugReturn(LRESULT err)
  2063. {
  2064. int i;
  2065. if (!fDebug)
  2066. return err;
  2067. dwTime = timeGetTime() - dwTime;
  2068. for (i=0; aErr[i].err && aErr[i].err != err; i++)
  2069. ;
  2070. if (aErr[i].err != err)
  2071. RPF(("! : 0x%08lX (%ldms)\r\n", err, dwTime));
  2072. else
  2073. RPF(("! : %s (%ldms)\r\n", (LPSTR)aErr[i].szErr, dwTime));
  2074. return err;
  2075. }
  2076. static void ICDump()
  2077. {
  2078. int i;
  2079. PIC pic;
  2080. char ach[80];
  2081. DPF(("ICDump ---------------------------------------\r\n"));
  2082. for (i=0; i<MAX_CONVERTERS; i++)
  2083. {
  2084. pic = &aicConverters[i];
  2085. if (pic->fccType == 0)
  2086. continue;
  2087. if (pic->dwSmag == 0)
  2088. continue;
  2089. if (pic->hDriver)
  2090. GetModuleFileName(GetDriverModuleHandle (pic->hDriver), ach, sizeof(ach));
  2091. else
  2092. ach[0] = 0;
  2093. DPF((" HIC: %04X %4.4s.%4.4s hTask=%04X Proc=%08lx %s\r\n", (HIC)pic, (LPSTR)&pic->fccType, (LPSTR)&pic->fccHandler, pic->hTask, pic->DriverProc, (LPSTR)ach));
  2094. }
  2095. DPF(("----------------------------------------------\r\n"));
  2096. }
  2097. #endif
  2098. /*****************************************************************************
  2099. *
  2100. * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  2101. *
  2102. * The messages will be send to COM1: like any debug message. To
  2103. * enable debug output, add the following to WIN.INI :
  2104. *
  2105. * [debug]
  2106. * COMPMAN=1
  2107. *
  2108. ****************************************************************************/
  2109. #ifdef DEBUG_RETAIL
  2110. #define MODNAME "COMPMAN"
  2111. static void cdecl dprintfc(LPSTR szFormat, ...)
  2112. {
  2113. char ach[128];
  2114. #ifdef WIN32
  2115. va_list va;
  2116. if (fDebug == -1)
  2117. fDebug = GetProfileIntA("Debug",MODNAME, FALSE);
  2118. if (!fDebug)
  2119. return;
  2120. va_start(va, szFormat);
  2121. if (szFormat[0] == '!')
  2122. ach[0]=0, szFormat++;
  2123. else
  2124. lstrcpyA(ach, MODNAME ": ");
  2125. wvsprintfA(ach+lstrlenA(ach),szFormat,va);
  2126. va_end(va);
  2127. // lstrcatA(ach, "\r\r\n");
  2128. #else
  2129. if (fDebug == -1) {
  2130. fDebug = GetProfileIntA("Debug",MODNAME, FALSE);
  2131. switch (fDebug) {
  2132. case -1:
  2133. OutputDebugStringA("fDebug still set at -1\n");
  2134. break;
  2135. case 0:
  2136. OutputDebugStringA("fDebug set to 0\n");
  2137. break;
  2138. case 1:
  2139. OutputDebugStringA("fDebug set to 1\n");
  2140. break;
  2141. case 2:
  2142. OutputDebugStringA("fDebug set to 2\n");
  2143. break;
  2144. default:
  2145. OutputDebugStringA("fDebug set to something else\n");
  2146. }
  2147. }
  2148. if (!fDebug)
  2149. return;
  2150. if (szFormat[0] == '!')
  2151. ach[0]=0, szFormat++;
  2152. else
  2153. lstrcpyA(ach, MODNAME ": ");
  2154. wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)(&szFormat+1));
  2155. lstrcatA(ach, "\r\r\n");
  2156. #endif
  2157. OutputDebugStringA(ach);
  2158. }
  2159. #endif