Source code of Windows XP (NT5)
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.

1301 lines
38 KiB

  1. //==========================================================================;
  2. // COMMENTS DO NOT YET APPLY TO MSVFW32.DLL
  3. // thunk32.c
  4. //
  5. // Copyright (c) 1991-1994 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Description:
  8. // This module contains routines for thunking the
  9. // ICM APIs (messages) from 16-bit Windows to 32-bit WOW.
  10. //
  11. // History:
  12. //
  13. //==========================================================================;
  14. /*
  15. WOW Thunking design:
  16. Thunks are generated as follows :
  17. 16-bit :
  18. acmBootDrivers->acmInitThunks :
  19. Generate calls to 32-bit drivers if we're in WOW call across
  20. to KERNEL to find thunking entry points.
  21. If we're thunking 'load' all the 32-bit ACM drivers as well as
  22. the 16-bit ones.
  23. Priority is always to find a 32-bit driver first but this is
  24. done via searching for one on open.
  25. The internal flag ACM_DRIVERADDF_32BIT is specified when
  26. calling IDriverAdd and this flag is stored in the ACMDRIVERID
  27. structure.
  28. IDriverAdd->IDriverLoad->IDriverLoad32
  29. The 16-bit side calls the 32-bit side passing in the driver
  30. alias which is used to compare against the aliases on the 32
  31. bit side and the 32-bit HACMDRIVERID is passed back for the
  32. relevant driver and stored in the hdrvr field of the
  33. ACMDRIVERID structure.
  34. IDriverOpen->IDriverOpen32
  35. The parameters are passed to the 32-bit side using the hdrvr
  36. field deduced from the HACMDRIVERID as the 32-bit HACMDRIVERID.
  37. IDriverMessageId->IDriverMessageId32 :
  38. If the driver is 32-bit (as identified in the ACMDRIVERID
  39. structure) then call IDriverMessageId32. The hadid for
  40. the 32-bit driver is stored in the hdrvr field of ACMDRIVERID
  41. on the 16-bit side.
  42. IDriverMessage->IDriverMessage32
  43. If the driver is 32-bit (as identified in the ACMDRIVERID
  44. structure pointed to by the ACMDRIVER structure) then call
  45. IDriverMessage32. The had for the 32-bit driver is stored
  46. in the hdrvr field of ACMDRIVER on the 16-bit side.
  47. Stream headers
  48. These must be persistent on the 32-bit side too and kept
  49. in synch.
  50. They are allocated on the 32-bit side for ACMDM_STREAM_PREPARE
  51. and freed on ACMDM_STREAM_UNPREPARE. While in existence
  52. the 32-bit stream header is stored in the dwDriver field in
  53. */
  54. #include <windows.h>
  55. #include <windowsx.h>
  56. #include <mmsystem.h>
  57. #include <mmddk.h>
  58. #include <mmreg.h>
  59. #include <memory.h>
  60. #include <win32.h>
  61. #include <vfw.h>
  62. #include <msviddrv.h>
  63. #include <msvideoi.h>
  64. #ifdef WIN32
  65. #include <wownt32.h>
  66. #include <stdlib.h> // for mbstowcs and wcstombs
  67. #endif // WIN32
  68. #include "compmn16.h"
  69. //
  70. // pick up the function definitions
  71. //
  72. int thunkDebugLevel = 1;
  73. #include "vidthunk.h"
  74. /* -------------------------------------------------------------------------
  75. ** Handle and memory mapping functions.
  76. ** -------------------------------------------------------------------------
  77. */
  78. LPWOWHANDLE32 lpWOWHandle32;
  79. LPWOWHANDLE16 lpWOWHandle16;
  80. LPWOWCALLBACK16 lpWOWCallback16;
  81. LPGETVDMPOINTER GetVdmPointer;
  82. int ThunksInitialized;
  83. //
  84. // 16-bit structures
  85. //
  86. typedef struct {
  87. DWORD dwDCISize;
  88. LPCSTR lpszDCISectionName;
  89. LPCSTR lpszDCIAliasName;
  90. } DRVCONFIGINFO16;
  91. //
  92. // Useful functions
  93. //
  94. //
  95. // CopyAlloc - allocate a new piece of memory, and copy the data in
  96. // Must use LocalFree to release the memory later
  97. //
  98. PVOID CopyAlloc(PVOID pvSrc, UINT uSize)
  99. {
  100. PVOID pvDest;
  101. pvDest = (PVOID)LocalAlloc(LMEM_FIXED, uSize);
  102. if (pvDest != NULL) {
  103. CopyMemory(pvDest, pvSrc, uSize);
  104. }
  105. return pvDest;
  106. }
  107. /*
  108. * Copy data from source to dest where source is a 32bit pointer
  109. * and dest is a 16bit pointer
  110. */
  111. void CopyTo16Bit(LPVOID Dest16, LPVOID Src32, DWORD Length)
  112. {
  113. PVOID Dest32;
  114. if (Src32 == NULL) {
  115. return;
  116. }
  117. Dest32 = GetVdmPointer((DWORD)Dest16, Length, TRUE);
  118. CopyMemory(Dest32, Src32, Length);
  119. }
  120. /*
  121. * Copy data from source to dest where source is a 16bit pointer
  122. * and dest is a 32bit pointer
  123. */
  124. PVOID CopyTo32Bit(LPVOID Dest32, LPVOID Src16, DWORD Length)
  125. {
  126. PVOID Src32;
  127. if (Src16 == NULL) {
  128. return NULL;
  129. }
  130. Src32 = GetVdmPointer((DWORD)Src16, Length, TRUE);
  131. CopyMemory(Dest32, Src32, Length);
  132. return(Src32);
  133. }
  134. /*
  135. * Copy data from source to dest where source is a 16bit pointer
  136. * and dest is a 32bit pointer ONLY if the source is not aligned
  137. *
  138. * Returns which pointer to use (src or dest)
  139. */
  140. LPVOID CopyIfNotAligned(LPVOID Dest32, LPVOID Src16, DWORD Length)
  141. {
  142. PVOID Src32;
  143. if (Src16 == NULL) {
  144. return Dest32;
  145. }
  146. Src32 = GetVdmPointer((DWORD)Src16, Length, TRUE);
  147. CopyMemory(Dest32, Src32, Length);
  148. return Dest32;
  149. }
  150. #ifdef _INC_COMPMAN
  151. /*--------------------------------------------------------------------------*\
  152. | |
  153. | Now thunk the compman functions |
  154. | |
  155. | |
  156. | |
  157. | |
  158. \*--------------------------------------------------------------------------*/
  159. /*
  160. * Convert ICDRAWBEGIN structures
  161. */
  162. INLINE STATICFN void ConvertICDRAWBEGIN(ICDRAWBEGIN *DrawBegin32,
  163. LPBITMAPINFOHEADER lpBmi,
  164. DWORD dw)
  165. {
  166. ICDRAWBEGIN16 DrawBegin16;
  167. CopyTo32Bit(&DrawBegin16, (LPVOID)dw, sizeof(ICDRAWBEGIN16));
  168. DrawBegin32->dwFlags = DrawBegin16.dwFlags;
  169. DrawBegin32->hpal = ThunkHPAL(DrawBegin16.hpal);
  170. DrawBegin32->hwnd = ThunkHWND(DrawBegin16.hwnd);
  171. DrawBegin32->hdc = ThunkHDC(DrawBegin16.hdc);
  172. DrawBegin32->xDst = (int)DrawBegin16.xDst;
  173. DrawBegin32->yDst = (int)DrawBegin16.yDst;
  174. DrawBegin32->dxDst = (int)DrawBegin16.dxDst;
  175. DrawBegin32->dyDst = (int)DrawBegin16.dyDst;
  176. CopyTo32Bit(lpBmi, DrawBegin16.lpbi, sizeof(BITMAPINFOHEADER));
  177. DrawBegin32->lpbi = lpBmi;
  178. DrawBegin32->xSrc = (int)DrawBegin16.xSrc;
  179. DrawBegin32->ySrc = (int)DrawBegin16.ySrc;
  180. DrawBegin32->dxSrc = (int)DrawBegin16.dxSrc;
  181. DrawBegin32->dySrc = (int)DrawBegin16.dySrc;
  182. DrawBegin32->dwRate = DrawBegin16.dwRate;
  183. DrawBegin32->dwScale = DrawBegin16.dwScale;
  184. }
  185. /*
  186. * Following logic copied from mvdm\wow32\wstruc.c - however since we
  187. * don't have the usage parameter we're a bit stuck on the size of the
  188. * entries.
  189. *
  190. * See also the video for windows documentation - only a limited range of
  191. * bitmap types are discussed.
  192. */
  193. INT GetBMI16Size(UNALIGNED BITMAPINFOHEADER *pbmi16)
  194. {
  195. int nHdrSize;
  196. int nEntSize;
  197. int nEntries;
  198. int nBitCount;
  199. DWORD dwClrUsed;
  200. nHdrSize = (int)pbmi16->biSize;
  201. /*
  202. * We don't have some of the info we need so assume RGBQUAD
  203. */
  204. nEntSize = sizeof(RGBQUAD);
  205. nBitCount = pbmi16->biBitCount;
  206. dwClrUsed = pbmi16->biClrUsed;
  207. /* the following block of code should be this:
  208. *
  209. * if ( nBitCount >= 9 ) { // this is how Win3.1 code says == 24
  210. * nEntries = 1;
  211. * }
  212. * else if ( dwClrUsed ) {
  213. * nEntries = dwClrUsed;
  214. * }
  215. * else {
  216. * nEntries = 1 << nBitCount;
  217. * }
  218. *
  219. * but due to the fact that many apps don't initialize the biBitCount &
  220. * biClrUsed fields (especially biClrUsed) we have to do the following
  221. * sanity checking instead. v-cjones
  222. */
  223. nEntries = 1;
  224. if ( nBitCount < 9 ) {
  225. if((nBitCount == 4) || (nBitCount == 8) || (nBitCount == 1)) {
  226. nEntries = 1 << nBitCount;
  227. }
  228. // sanity check for apps (lots) that don't init the dwClrUsed field
  229. if(dwClrUsed) {
  230. nEntries = (int)min((DWORD)nEntries, dwClrUsed);
  231. }
  232. }
  233. return ( nHdrSize + (nEntries * nEntSize) );
  234. }
  235. INLINE LPBITMAPINFO CopyBitmapInfo(DWORD Bi16)
  236. {
  237. UNALIGNED BITMAPINFOHEADER *pbmi16;
  238. pbmi16 = WOW32ResolveMemory(Bi16);
  239. if ((int)pbmi16->biSize == 0) {
  240. pbmi16->biSize = sizeof(BITMAPINFOHEADER);
  241. DPF1(("WARNING: null bitmap info size, setting it correctly"));
  242. }
  243. return (LPBITMAPINFO)CopyAlloc((LPVOID)pbmi16, GetBMI16Size(pbmi16));
  244. }
  245. /*
  246. * Allocate a BITMAPINFO structure to contain 256 colours
  247. */
  248. INLINE LPBITMAPINFO AllocBitmapInfo()
  249. {
  250. return (PVOID)LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER)+
  251. (sizeof(RGBQUAD)*256));
  252. }
  253. INLINE LPBITMAPINFOHEADER CopyBitmapInfoHeader(DWORD Bi16)
  254. {
  255. UNALIGNED BITMAPINFOHEADER *pbmi16;
  256. pbmi16 = WOW32ResolveMemory(Bi16);
  257. return (LPBITMAPINFOHEADER)CopyAlloc((LPVOID)pbmi16, pbmi16->biSize);
  258. }
  259. DWORD CopyICINFOTo16bit(DWORD dw, ICINFO *IcInfoCopy, DWORD Length)
  260. {
  261. ICINFO16 IcInfo;
  262. LONG ReturnCode;
  263. /*
  264. * Make a copy since the behaviour of wcstombs is undefined
  265. * for overlapping input and output
  266. */
  267. memcpy(&IcInfo, IcInfoCopy, FIELD_OFFSET(ICINFO, szName[0]));
  268. /*
  269. * Massage the strings
  270. */
  271. wcstombs(IcInfo.szName,
  272. IcInfoCopy->szName,
  273. sizeof(IcInfo.szName));
  274. // HACK : overwrite the last five characters with "[32]\0"
  275. if ((IcInfo.szName[0]))
  276. {
  277. UINT n = min(sizeof(IcInfo.szName)-5, lstrlenA(IcInfo.szName));
  278. IcInfo.szName[n++] = '[';
  279. IcInfo.szName[n++] = '3';
  280. IcInfo.szName[n++] = '2';
  281. IcInfo.szName[n++] = ']';
  282. IcInfo.szName[n] = '\0';
  283. }
  284. wcstombs(IcInfo.szDescription,
  285. IcInfoCopy->szDescription,
  286. sizeof(IcInfo.szDescription));
  287. // HACK : overwrite the last five characters with "[32]\0"
  288. if ((IcInfo.szDescription[0]))
  289. {
  290. UINT n = min(sizeof(IcInfo.szDescription)-5, lstrlenA(IcInfo.szDescription));
  291. IcInfo.szDescription[n++] = '[';
  292. IcInfo.szDescription[n++] = '3';
  293. IcInfo.szDescription[n++] = '2';
  294. IcInfo.szDescription[n++] = ']';
  295. IcInfo.szDescription[n] = '\0';
  296. }
  297. wcstombs(IcInfo.szDriver,
  298. IcInfoCopy->szDriver,
  299. sizeof(IcInfo.szDriver));
  300. IcInfo.dwSize = sizeof(IcInfo);
  301. ReturnCode = min(Length, IcInfo.dwSize);
  302. CopyTo16Bit((LPVOID)dw, &IcInfo, ReturnCode);
  303. return ReturnCode;
  304. }
  305. STATICFN DWORD DoICM_DecompressX(DWORD hic, UINT msg, DWORD dwP1, DWORD dwP2)
  306. {
  307. /*
  308. * We need to convert the various fields in the ICDECOMPRESS/EX
  309. * structure(s). Fortunately(?) the EX structure is a simple
  310. * extension.
  311. */
  312. typedef struct {
  313. //
  314. // same as ICM_DECOMPRESS
  315. //
  316. DWORD dwFlags;
  317. LPBITMAPINFOHEADER lpbiSrc; // BITMAPINFO of compressed data
  318. LPVOID lpSrc; // compressed data
  319. LPBITMAPINFOHEADER lpbiDst; // DIB to decompress to
  320. LPVOID lpDst; // output data
  321. //
  322. // new for ICM_DECOMPRESSEX
  323. //
  324. short xDst; // destination rectangle
  325. short yDst;
  326. short dxDst;
  327. short dyDst;
  328. short xSrc; // source rectangle
  329. short ySrc;
  330. short dxSrc;
  331. short dySrc;
  332. } ICDECOMPRESSEX16;
  333. ICDECOMPRESSEX16 UNALIGNED *lpicdmpr16;
  334. ICDECOMPRESSEX ICDecompressEx;
  335. DWORD l;
  336. /* Copy the standard or extended structure */
  337. lpicdmpr16 = GetVdmPointer( dwP1, dwP2, TRUE );
  338. ICDecompressEx.dwFlags = lpicdmpr16->dwFlags;
  339. ICDecompressEx.lpbiSrc = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)lpicdmpr16->lpbiSrc);
  340. if (NULL == ICDecompressEx.lpbiSrc) {
  341. return (DWORD)ICERR_MEMORY;
  342. }
  343. ICDecompressEx.lpbiDst = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)lpicdmpr16->lpbiDst);
  344. if (NULL == ICDecompressEx.lpbiDst) {
  345. LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc );
  346. return (DWORD)ICERR_MEMORY;
  347. }
  348. ICDecompressEx.lpSrc =
  349. GetVdmPointer((DWORD)lpicdmpr16->lpSrc,
  350. ICDecompressEx.lpbiSrc->biSizeImage, TRUE);
  351. ICDecompressEx.lpDst =
  352. GetVdmPointer((DWORD)lpicdmpr16->lpDst,
  353. ICDecompressEx.lpbiDst->biSizeImage, TRUE);
  354. if (dwP2 == sizeof(ICDECOMPRESSEX16) ) {
  355. ICDecompressEx.xDst = (int)lpicdmpr16->xDst;
  356. ICDecompressEx.yDst = (int)lpicdmpr16->yDst;
  357. ICDecompressEx.dxDst = (int)lpicdmpr16->dxDst;
  358. ICDecompressEx.dyDst = (int)lpicdmpr16->dyDst;
  359. ICDecompressEx.xSrc = (int)lpicdmpr16->xSrc;
  360. ICDecompressEx.ySrc = (int)lpicdmpr16->ySrc;
  361. ICDecompressEx.dxSrc = (int)lpicdmpr16->dxSrc;
  362. ICDecompressEx.dySrc = (int)lpicdmpr16->dySrc;
  363. dwP2 = sizeof(ICDecompressEx); // Make the size relate to 32 bit
  364. }
  365. l = ICSendMessage( (HIC)hic, (UINT)msg, (DWORD)&ICDecompressEx, dwP2 );
  366. if ( l == ICERR_OK) {
  367. CopyTo16Bit( lpicdmpr16->lpbiDst, ICDecompressEx.lpbiDst,
  368. sizeof(BITMAPINFOHEADER) );
  369. }
  370. LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc );
  371. LocalFree( (HLOCAL)ICDecompressEx.lpbiDst );
  372. return l;
  373. }
  374. /*
  375. * Generate our thunks - refer to msvideo!compman.c for definitions of
  376. * functions.
  377. *
  378. * NOTE - we often rely here on the fact that most of the message
  379. * parameter structures are identical for 16 and 32-bit - ie they
  380. * contain DWORDs and 32-bit pointers.
  381. */
  382. BOOL FAR PASCAL ICInfo32(DWORD fccType, DWORD fccHandler, ICINFO16 FAR * lpicInfo)
  383. {
  384. ICINFO ReturnedICInfo;
  385. StartThunk(ICInfo);
  386. DPF2(("Calling ICInfo %4.4hs %4.4hs %8X", &fccType, &fccHandler, lpicInfo));
  387. ReturnedICInfo.fccHandler = 0; // Initialise...
  388. ReturnCode = ICInfo(fccType, fccHandler, &ReturnedICInfo);
  389. CopyICINFOTo16bit((DWORD)lpicInfo, &ReturnedICInfo, sizeof(ReturnedICInfo));
  390. EndThunk()
  391. }
  392. LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD dwP1, DWORD dwP2)
  393. {
  394. StartThunk(ICSendMessage);
  395. DPF2(("Calling ICSendMessage %4X %4X %8X %8X",
  396. hic, msg, dwP1, dwP2));
  397. switch (msg) {
  398. case ICM_GETSTATE:
  399. case ICM_SETSTATE:
  400. if (dwP1 == 0) {
  401. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  402. (UINT)msg,
  403. dwP1,
  404. dwP2);
  405. } else {
  406. PVOID pState;
  407. /*
  408. * Create some aligned memory to return or pass on the data
  409. */
  410. pState = (PVOID)LocalAlloc(LPTR, dwP2);
  411. if (pState == NULL) {
  412. ReturnCode = ICERR_MEMORY;
  413. } else {
  414. if ((UINT)msg == ICM_SETSTATE) {
  415. // Copy the data from 16 bit land
  416. CopyTo32Bit(pState, (LPVOID)dwP1, dwP2);
  417. }
  418. ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg,
  419. (DWORD)pState, dwP2);
  420. /*
  421. * Copy back the state, if the driver returned any data
  422. */
  423. if (ReturnCode > 0 && (UINT)msg == ICM_GETSTATE) {
  424. CopyTo16Bit((LPVOID)dwP1, pState,
  425. min((DWORD)ReturnCode, dwP2));
  426. }
  427. LocalFree((HLOCAL)pState);
  428. }
  429. }
  430. break;
  431. case ICM_GETINFO:
  432. {
  433. ICINFO IcInfo;
  434. ReturnCode = ICGetInfo((HIC)(DWORD)hic, &IcInfo, sizeof(IcInfo));
  435. if (ReturnCode != 0) {
  436. ReturnCode = CopyICINFOTo16bit(dwP1, &IcInfo, ReturnCode);
  437. }
  438. }
  439. break;
  440. case ICM_CONFIGURE:
  441. case ICM_ABOUT:
  442. /*
  443. * dwP1 = -1 is a special value asking if config is supported,
  444. * otherwise it's a window handle
  445. */
  446. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  447. (UINT)msg,
  448. dwP1 == (DWORD)-1 ?
  449. (DWORD)-1 :
  450. (DWORD)ThunkHWND(LOWORD(dwP1)),
  451. dwP2);
  452. break;
  453. case ICM_COMPRESS:
  454. {
  455. if (dwP2 != sizeof(ICCOMPRESS)) { // validation code
  456. ReturnCode = ICERR_BADSIZE;
  457. } else {
  458. DWORD dwFlags;
  459. LPDWORD lpdwFlags16, lpckid16;
  460. LPBITMAPINFOHEADER lpbih16;
  461. DWORD ckid;
  462. ICCOMPRESS IcCompress;
  463. ReturnCode = ICERR_OK;
  464. /*
  465. * We need to convert the various fields in the ICCOMPRESS
  466. * structure
  467. */
  468. CopyTo32Bit( &IcCompress, (LPVOID)dwP1, dwP2 );
  469. IcCompress.lpbiInput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)IcCompress.lpbiInput);
  470. if (NULL == IcCompress.lpbiInput) {
  471. ReturnCode = ICERR_MEMORY;
  472. break;
  473. }
  474. lpbih16 = IcCompress.lpbiOutput;
  475. IcCompress.lpbiOutput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)IcCompress.lpbiOutput);
  476. if (NULL == IcCompress.lpbiOutput) {
  477. LocalFree((HLOCAL)IcCompress.lpbiInput);
  478. ReturnCode = ICERR_MEMORY;
  479. break;
  480. }
  481. IcCompress.lpInput =
  482. GetVdmPointer((DWORD)IcCompress.lpInput,
  483. IcCompress.lpbiInput->biSizeImage, TRUE);
  484. IcCompress.lpOutput =
  485. GetVdmPointer((DWORD)IcCompress.lpOutput,
  486. IcCompress.lpbiOutput->biSizeImage, TRUE);
  487. if (IcCompress.lpbiPrev) {
  488. IcCompress.lpbiPrev = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)IcCompress.lpbiPrev);
  489. if (NULL == IcCompress.lpbiPrev) {
  490. LocalFree((HLOCAL)IcCompress.lpbiOutput);
  491. LocalFree((HLOCAL)IcCompress.lpbiInput);
  492. ReturnCode = ICERR_MEMORY;
  493. break;
  494. }
  495. IcCompress.lpPrev =
  496. GetVdmPointer((DWORD)IcCompress.lpPrev,
  497. IcCompress.lpbiPrev->biSizeImage, TRUE);
  498. }
  499. lpdwFlags16 = IcCompress.lpdwFlags;
  500. IcCompress.lpdwFlags = &dwFlags;
  501. if (IcCompress.lpckid != NULL) {
  502. lpckid16 = IcCompress.lpckid;
  503. IcCompress.lpckid = &ckid;
  504. }
  505. ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg,
  506. (DWORD)&IcCompress, dwP2);
  507. if (ReturnCode == ICERR_OK) {
  508. CopyTo16Bit( lpbih16, IcCompress.lpbiOutput,
  509. sizeof(BITMAPINFOHEADER) );
  510. if (lpdwFlags16 != NULL) {
  511. CopyTo16Bit(lpdwFlags16, &dwFlags, sizeof(DWORD));
  512. }
  513. if (IcCompress.lpckid != NULL) {
  514. CopyTo16Bit(lpckid16, &ckid, sizeof(DWORD));
  515. }
  516. }
  517. /*
  518. ** Free the bitmap info storage regardless of the return code
  519. */
  520. if (NULL == IcCompress.lpbiPrev) {
  521. LocalFree((HLOCAL)IcCompress.lpbiPrev);
  522. }
  523. LocalFree((HLOCAL)IcCompress.lpbiOutput);
  524. LocalFree((HLOCAL)IcCompress.lpbiInput);
  525. }
  526. }
  527. break;
  528. case ICM_DECOMPRESS_SET_PALETTE:
  529. // takes one (optionally null) bitmapinfo
  530. {
  531. LPBITMAPINFO bmi = 0;
  532. if (dwP1 != 0) {
  533. bmi = CopyBitmapInfo(dwP1);
  534. }
  535. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  536. (UINT)msg,
  537. (DWORD)bmi,
  538. (DWORD)0);
  539. if (bmi != NULL) {
  540. LocalFree((HLOCAL)bmi);
  541. }
  542. break;
  543. }
  544. case ICM_COMPRESS_GET_SIZE:
  545. case ICM_COMPRESS_BEGIN:
  546. case ICM_COMPRESS_QUERY:
  547. case ICM_DECOMPRESS_BEGIN:
  548. case ICM_DECOMPRESS_GET_PALETTE:
  549. case ICM_DECOMPRESS_QUERY:
  550. {
  551. LPBITMAPINFO bmi1, bmi2;
  552. bmi1 = CopyBitmapInfo(dwP1);
  553. if (dwP2 != 0) {
  554. bmi2 = CopyBitmapInfo(dwP2);
  555. } else {
  556. bmi2 = NULL;
  557. }
  558. if (bmi1 == NULL || bmi2 == NULL && dwP2 != 0) {
  559. ReturnCode =
  560. (UINT)msg == ICM_COMPRESS_GET_SIZE ? 0 : ICERR_MEMORY;
  561. } else {
  562. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  563. (UINT)msg,
  564. (DWORD)bmi1,
  565. (DWORD)bmi2);
  566. if (bmi2 != NULL) {
  567. // We might have to return data to the 16 bit side.
  568. // The messages for which we have to do this are:
  569. // ICM_DECOMPRESS_QUERY (iff retcode == ICERR_OK)
  570. // ICM_DECOMPRESS_GET_PALETTE (iff retcode >= 0)
  571. if (((ReturnCode == ICERR_OK) && (msg == ICM_DECOMPRESS_QUERY))
  572. || ((ReturnCode >= 0) && (msg == ICM_DECOMPRESS_GET_PALETTE)))
  573. {
  574. CopyTo16Bit((LPVOID)dwP2, bmi2, GetBMI16Size((LPBITMAPINFOHEADER)bmi2));
  575. }
  576. LocalFree((HLOCAL)bmi2);
  577. }
  578. }
  579. if (bmi1 != NULL) {
  580. LocalFree((HLOCAL)bmi1);
  581. }
  582. }
  583. break;
  584. case ICM_COMPRESS_END:
  585. case ICM_DECOMPRESS_END:
  586. case ICM_DECOMPRESSEX_END:
  587. case ICM_DRAW_END:
  588. case ICM_DRAW_FLUSH:
  589. case ICM_DRAW_START: //??
  590. case ICM_DRAW_STOP: //??
  591. case ICM_DRAW_SETTIME:
  592. case ICM_DRAW_RENDERBUFFER:
  593. case ICM_SETQUALITY:
  594. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  595. (UINT)msg,
  596. dwP1,
  597. dwP2);
  598. break;
  599. case ICM_DRAW_GETTIME:
  600. case ICM_GETBUFFERSWANTED:
  601. case ICM_GETDEFAULTQUALITY:
  602. case ICM_GETDEFAULTKEYFRAMERATE:
  603. case ICM_GETQUALITY:
  604. {
  605. DWORD dwReturn;
  606. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  607. (UINT)msg,
  608. (DWORD)&dwReturn,
  609. dwP2);
  610. // Note: although the definition of these messages state
  611. // that dwParam2 is not used, trouble will brew if the
  612. // decompressor ever tries to use dwParam2. We cannot
  613. // thunk non-standard uses of this parameter.
  614. if (ReturnCode == ICERR_OK) {
  615. CopyTo16Bit((LPVOID)dwP1, &dwReturn, sizeof(DWORD));
  616. }
  617. }
  618. break;
  619. case ICM_COMPRESS_GET_FORMAT:
  620. case ICM_DECOMPRESS_GET_FORMAT:
  621. /*
  622. * This is a tricky one - we first have to find the size of
  623. * the output format so we can get a copy of the (aligned)
  624. * version before passing it back to the app
  625. */
  626. {
  627. LPBITMAPINFO bmi1, bmi2;
  628. if ( dwP1 == 0L ) {
  629. ReturnCode = ICERR_OK;
  630. break;
  631. }
  632. bmi1 = CopyBitmapInfo(dwP1);
  633. if (bmi1 == NULL) {
  634. ReturnCode = ICERR_MEMORY;
  635. } else {
  636. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  637. (UINT)msg,
  638. (DWORD)bmi1,
  639. 0);
  640. if (ReturnCode > 0 && dwP2 != 0) {
  641. bmi2 = LocalAlloc(LMEM_FIXED, ReturnCode);
  642. if (bmi2 == NULL) {
  643. /*
  644. * Can't do anything!!! - there's not good return code
  645. */
  646. ReturnCode = ICERR_MEMORY;
  647. } else {
  648. DWORD Length;
  649. Length = ReturnCode; /* preserve length */
  650. ReturnCode =
  651. ICSendMessage((HIC)(DWORD)hic,
  652. (UINT)msg,
  653. (DWORD)bmi1,
  654. (DWORD)bmi2);
  655. if (ReturnCode >= 0) {
  656. CopyTo16Bit((LPVOID)dwP2, bmi2, Length);
  657. }
  658. LocalFree((HLOCAL)bmi2);
  659. }
  660. }
  661. LocalFree((HLOCAL)bmi1);
  662. }
  663. }
  664. break;
  665. case ICM_DECOMPRESS:
  666. if (dwP2 != sizeof(ICDECOMPRESS)) {
  667. ReturnCode = ICERR_BADSIZE;
  668. } else {
  669. ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2);
  670. }
  671. break;
  672. case ICM_DECOMPRESSEX:
  673. case ICM_DECOMPRESSEX_BEGIN:
  674. if (dwP2 != sizeof(ICDECOMPRESSEX)) {
  675. ReturnCode = ICERR_BADSIZE;
  676. } else {
  677. ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2);
  678. }
  679. break;
  680. case ICM_DECOMPRESSEX_QUERY:
  681. {
  682. /*
  683. * We need to convert the various fields in the ICDECOMPRESSEX
  684. * structure(s).
  685. */
  686. ICDECOMPRESSEX ICDecompressEx1;
  687. ICDECOMPRESSEX ICDecompressEx2;
  688. BITMAPINFOHEADER biInput1, biOutput1;
  689. BITMAPINFOHEADER biInput2, biOutput2;
  690. /* Copy the structure */
  691. CopyTo32Bit(&ICDecompressEx1,
  692. (LPVOID)dwP1,
  693. sizeof(ICDECOMPRESSEX));
  694. /*
  695. * We now need : converted forms of the bitmap info headers
  696. * an aligned version of the input bytes (CHECK and if
  697. * already aligned do nothing)
  698. * and an aligned (again only if ncessary) version of the
  699. * output data buffer - actually we'll assume there aren't
  700. * necessary
  701. */
  702. ICDecompressEx1.lpbiSrc =
  703. CopyIfNotAligned(&biInput1, ICDecompressEx1.lpbiSrc,
  704. sizeof(BITMAPINFOHEADER));
  705. ICDecompressEx1.lpbiDst =
  706. CopyIfNotAligned(&biOutput1, ICDecompressEx1.lpbiDst,
  707. sizeof(BITMAPINFOHEADER));
  708. ICDecompressEx1.lpSrc =
  709. GetVdmPointer((DWORD)ICDecompressEx1.lpSrc,
  710. ICDecompressEx1.lpbiSrc->biSizeImage, TRUE);
  711. ICDecompressEx1.lpDst =
  712. GetVdmPointer((DWORD)ICDecompressEx1.lpDst,
  713. ICDecompressEx1.lpbiDst->biSizeImage, TRUE);
  714. /* Copy the optional structure */
  715. if (dwP2) {
  716. CopyTo32Bit(&ICDecompressEx2,
  717. (LPVOID)dwP2,
  718. sizeof(ICDECOMPRESSEX));
  719. dwP2 = (DWORD)&ICDecompressEx2;
  720. ICDecompressEx2.lpbiSrc =
  721. CopyIfNotAligned(&biInput2, ICDecompressEx2.lpbiSrc,
  722. sizeof(BITMAPINFOHEADER));
  723. ICDecompressEx2.lpbiDst =
  724. CopyIfNotAligned(&biOutput2, ICDecompressEx2.lpbiDst,
  725. sizeof(BITMAPINFOHEADER));
  726. ICDecompressEx2.lpSrc =
  727. GetVdmPointer((DWORD)ICDecompressEx2.lpSrc,
  728. ICDecompressEx2.lpbiSrc->biSizeImage, TRUE);
  729. ICDecompressEx2.lpDst =
  730. GetVdmPointer((DWORD)ICDecompressEx2.lpDst,
  731. ICDecompressEx2.lpbiDst->biSizeImage, TRUE);
  732. }
  733. return ICSendMessage((HIC)hic,
  734. (UINT)msg,
  735. (DWORD)&ICDecompressEx1,
  736. (DWORD)dwP2);
  737. }
  738. break;
  739. case ICM_DRAW:
  740. /*
  741. * We can't support unknown extensions
  742. */
  743. if (dwP2 != sizeof(ICDRAW)) {
  744. ReturnCode = ICERR_BADSIZE;
  745. } else {
  746. ICDRAW ICDraw;
  747. BITMAPINFOHEADER bmi;
  748. CopyTo32Bit(&ICDraw, (LPVOID)dwP1, dwP2);
  749. /*
  750. * We have to assume this is a draw for video
  751. */
  752. CopyTo32Bit(&bmi, ICDraw.lpFormat, sizeof(BITMAPINFOHEADER));
  753. ICDraw.lpFormat = (LPVOID)&bmi;
  754. ICDraw.lpData = GetVdmPointer((DWORD)ICDraw.lpData, ICDraw.cbData, TRUE);
  755. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  756. (UINT)msg,
  757. (DWORD)&ICDraw,
  758. dwP2);
  759. }
  760. break;
  761. case ICM_DRAW_BEGIN:
  762. {
  763. ICDRAWBEGIN InputFormat;
  764. BITMAPINFOHEADER bmihInput;
  765. ConvertICDRAWBEGIN(&InputFormat, &bmihInput, dwP1);
  766. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  767. (UINT)msg,
  768. (DWORD)&InputFormat,
  769. dwP2);
  770. }
  771. break;
  772. case ICM_DRAW_CHANGEPALETTE:
  773. case ICM_DRAW_QUERY:
  774. {
  775. LPBITMAPINFO lpbi;
  776. lpbi = CopyBitmapInfo(dwP1);
  777. if (lpbi == NULL) {
  778. ReturnCode = ICERR_MEMORY;
  779. } else {
  780. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  781. (UINT)msg,
  782. (DWORD)lpbi,
  783. dwP2);
  784. LocalFree((HLOCAL)lpbi);
  785. }
  786. }
  787. break;
  788. case ICM_DRAW_REALIZE:
  789. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  790. (UINT)msg,
  791. (DWORD)ThunkHDC(LOWORD(dwP1)),
  792. dwP2);
  793. break;
  794. case ICM_DRAW_WINDOW:
  795. {
  796. RECT_SHORT SRect;
  797. RECT Rect;
  798. CopyTo32Bit(&SRect, (LPVOID)dwP1, sizeof(SRect));
  799. SHORT_RECT_TO_RECT(Rect, SRect);
  800. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  801. (UINT)msg,
  802. (DWORD)&Rect,
  803. dwP2);
  804. }
  805. break;
  806. // The next three messages are INTERNAL ones
  807. case ICM_GETERRORTEXT:
  808. break;
  809. case ICM_GETFORMATNAME:
  810. break;
  811. case ICM_ENUMFORMATS:
  812. break;
  813. case ICM_COMPRESS_FRAMES_INFO:
  814. {
  815. ICCOMPRESSFRAMES icf32;
  816. CopyTo32Bit(&icf32, (LPBYTE)dwP1, dwP2);
  817. // Now fix up the 32 bit structure
  818. icf32.PutData = icf32.GetData = NULL; // For safety. should not be used for this message
  819. if (icf32.lpbiOutput) {
  820. icf32.lpbiOutput = CopyBitmapInfoHeader((DWORD)icf32.lpbiOutput);
  821. }
  822. if (icf32.lpbiInput) {
  823. icf32.lpbiInput = CopyBitmapInfoHeader((DWORD)icf32.lpbiInput);
  824. }
  825. icf32.lInput = (LPARAM)
  826. GetVdmPointer((DWORD)icf32.lInput,
  827. icf32.lpbiInput->biSizeImage, TRUE);
  828. icf32.lOutput = (LPARAM)
  829. GetVdmPointer((DWORD)icf32.lOutput,
  830. icf32.lpbiOutput->biSizeImage, TRUE);
  831. // After the fixups have been done, call the actual routine
  832. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  833. (UINT)msg,
  834. (DWORD)&icf32,
  835. dwP2);
  836. if (icf32.lpbiOutput) {
  837. LocalFree(icf32.lpbiOutput);
  838. }
  839. if (icf32.lpbiInput) {
  840. LocalFree(icf32.lpbiInput);
  841. }
  842. }
  843. break;
  844. case ICM_DRAW_GET_PALETTE:
  845. {
  846. ReturnCode = ICSendMessage((HIC) hic,
  847. (UINT)msg,
  848. dwP1,
  849. dwP2);
  850. if ((ReturnCode != 0L) && (ReturnCode != ICERR_UNSUPPORTED)) {
  851. FARPROC lpWOWHandle16;
  852. HMODULE hmodWow;
  853. if ( (hmodWow = GetModuleHandle( GET_MAPPING_MODULE_NAME ))
  854. && (lpWOWHandle16 = GetProcAddress(hmodWow, "WOWHandle16"))) {
  855. ReturnCode = (WORD)(lpWOWHandle16((HANDLE)ReturnCode, (WOW_HANDLE_TYPE)WOW_TYPE_HPALETTE));
  856. } else {
  857. ReturnCode = ICERR_ERROR;
  858. }
  859. }
  860. }
  861. break;
  862. case ICM_DRAW_SUGGESTFORMAT:
  863. {
  864. ICDRAWSUGGEST icdrwsug;
  865. UNALIGNED ICDRAWSUGGEST * pic;
  866. UNALIGNED LPBITMAPINFOHEADER lpbmihdr16;
  867. // Remember the 16 bit address
  868. pic = (ICDRAWSUGGEST *)CopyTo32Bit(&icdrwsug, (LPBYTE)dwP1, dwP2);
  869. lpbmihdr16 = pic->lpbiSuggest;
  870. // Now fix up the 32 bit structure
  871. if (icdrwsug.lpbiIn) {
  872. icdrwsug.lpbiIn = CopyBitmapInfoHeader((DWORD)icdrwsug.lpbiIn);
  873. }
  874. if (icdrwsug.lpbiSuggest) {
  875. icdrwsug.lpbiSuggest = CopyBitmapInfoHeader((DWORD)icdrwsug.lpbiSuggest);
  876. }
  877. // After the fixups have been done, call the actual routine
  878. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  879. (UINT)msg,
  880. (DWORD)&icdrwsug,
  881. dwP2);
  882. if (icdrwsug.lpbiIn) {
  883. LocalFree(icdrwsug.lpbiIn);
  884. }
  885. // We must return the 32 bit suggested format to 16 bit land
  886. if (icdrwsug.lpbiSuggest) {
  887. if (ReturnCode == ICERR_OK) {
  888. CopyTo16Bit( pic->lpbiSuggest, icdrwsug.lpbiSuggest,
  889. lpbmihdr16->biSize);
  890. }
  891. LocalFree(icdrwsug.lpbiSuggest);
  892. }
  893. }
  894. break;
  895. case ICM_SET_STATUS_PROC:
  896. // We do not need to support this under NT. It is much
  897. // easier not to add the callback support... even if we could
  898. // guarantee to be on the right thread to actually do the callback.
  899. default:
  900. ReturnCode = ICERR_UNSUPPORTED;
  901. break;
  902. }
  903. EndThunk()
  904. }
  905. INLINE DWORD FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode)
  906. {
  907. StartThunk(ICOpen);
  908. DPF2(("Calling ICOpen %4.4hs %4.4hs %4X", &fccType, &fccHandler, wMode));
  909. ReturnCode = (LONG)ICOpen(fccType, fccHandler, (UINT)wMode);
  910. EndThunk();
  911. }
  912. INLINE LRESULT FAR PASCAL ICClose32(DWORD hic)
  913. {
  914. StartThunk(ICClose);
  915. DPF2(("Calling ICClose %4X", hic));
  916. ReturnCode = ICClose((HIC)hic);
  917. EndThunk();
  918. }
  919. #endif // _INC_COMPMAN
  920. DWORD ICMThunk32(DWORD dwThunkId,DWORD dw1,DWORD dw2,DWORD dw3,DWORD dw4)
  921. {
  922. //
  923. // Make sure we've got thunking functionality
  924. //
  925. #if 0
  926. {
  927. char szBuffer[80];
  928. char szMsg[32];
  929. switch (dwThunkId) {
  930. case compThunkICSendMessage32:
  931. lstrcpyA( szMsg, "ICSendMessage32" );
  932. break;
  933. case compThunkICInfo32:
  934. lstrcpyA( szMsg, "ICInfo32" );
  935. break;
  936. case compThunkICOpen32:
  937. lstrcpyA( szMsg, "ICOpen32" );
  938. break;
  939. case compThunkICClose32:
  940. lstrcpyA( szMsg, "ICClose32" );
  941. break;
  942. default:
  943. lstrcpyA( szMsg, "Unknown" );
  944. break;
  945. }
  946. wsprintfA( szBuffer, "%18.18s 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
  947. szMsg, dw1, dw2, dw3, dw4);
  948. OutputDebugStringA( szBuffer );
  949. }
  950. #endif
  951. if (ThunksInitialized <= 0) {
  952. HMODULE hMod;
  953. if (ThunksInitialized == -1) {
  954. return MMSYSERR_ERROR;
  955. }
  956. hMod = GetModuleHandle(GET_MAPPING_MODULE_NAME);
  957. if (hMod != NULL) {
  958. GetVdmPointer =
  959. (LPGETVDMPOINTER)GetProcAddress(hMod, GET_VDM_POINTER_NAME);
  960. lpWOWHandle32 =
  961. (LPWOWHANDLE32)GetProcAddress(hMod, GET_HANDLE_MAPPER32 );
  962. lpWOWHandle16 =
  963. (LPWOWHANDLE16)GetProcAddress(hMod, GET_HANDLE_MAPPER16 );
  964. lpWOWCallback16 =
  965. (LPWOWCALLBACK16)GetProcAddress(hMod, GET_CALLBACK16 );
  966. }
  967. if ( GetVdmPointer == NULL
  968. || lpWOWHandle16 == NULL
  969. || lpWOWHandle32 == NULL ) {
  970. ThunksInitialized = -1;
  971. return MMSYSERR_ERROR;
  972. } else {
  973. ThunksInitialized = 1;
  974. }
  975. }
  976. //
  977. // Perform the requested function
  978. //
  979. switch (dwThunkId) {
  980. case compThunkICSendMessage32:
  981. return ICSendMessage32(dw1, (UINT)dw2, dw3, dw4);
  982. break;
  983. case compThunkICInfo32:
  984. return ICInfo32(dw1, dw2, (ICINFOA FAR * )dw3);
  985. break;
  986. case compThunkICOpen32:
  987. return ICOpen32(dw1, dw2, (UINT)dw3);
  988. break;
  989. case compThunkICClose32:
  990. return ICClose32(dw1);
  991. break;
  992. default:
  993. return(0);
  994. }
  995. }