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.

1984 lines
55 KiB

  1. //==========================================================================;
  2. // COMMENTS DO NOT YET APPLY TO MSVIDEO.DLL/MSVFW32.DLL
  3. // thunk.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. // This stuff is not going to work 64-bit
  15. #pragma warning(disable:4312)
  16. /*
  17. WOW Thunking design:
  18. Thunks are generated as follows :
  19. 16-bit :
  20. acmBootDrivers->acmInitThunks :
  21. Generate calls to 32-bit drivers if we're in WOW call across
  22. to KERNEL to find thunking entry points.
  23. If we're thunking 'load' all the 32-bit ACM drivers as well as
  24. the 16-bit ones.
  25. Priority is always to find a 32-bit driver first but this is
  26. done via searching for one on open.
  27. The internal flag ACM_DRIVERADDF_32BIT is specified when
  28. calling IDriverAdd and this flag is stored in the ACMDRIVERID
  29. structure.
  30. IDriverAdd->IDriverLoad->IDriverLoad32
  31. The 16-bit side calls the 32-bit side passing in the driver
  32. alias which is used to compare against the aliases on the 32
  33. bit side and the 32-bit HACMDRIVERID is passed back for the
  34. relevant driver and stored in the hdrvr field of the
  35. ACMDRIVERID structure.
  36. IDriverOpen->IDriverOpen32
  37. The parameters are passed to the 32-bit side using the hdrvr
  38. field deduced from the HACMDRIVERID as the 32-bit HACMDRIVERID.
  39. IDriverMessageId->IDriverMessageId32 :
  40. If the driver is 32-bit (as identified in the ACMDRIVERID
  41. structure) then call IDriverMessageId32. The hadid for
  42. the 32-bit driver is stored in the hdrvr field of ACMDRIVERID
  43. on the 16-bit side.
  44. IDriverMessage->IDriverMessage32
  45. If the driver is 32-bit (as identified in the ACMDRIVERID
  46. structure pointed to by the ACMDRIVER structure) then call
  47. IDriverMessage32. The had for the 32-bit driver is stored
  48. in the hdrvr field of ACMDRIVER on the 16-bit side.
  49. Stream headers
  50. These must be persistent on the 32-bit side too and kept
  51. in synch.
  52. They are allocated on the 32-bit side for ACMDM_STREAM_PREPARE
  53. and freed on ACMDM_STREAM_UNPREPARE. While in existence
  54. the 32-bit stream header is stored in the dwDriver field in
  55. */
  56. //==========================================================================;
  57. #define _INC_COMPMAN
  58. #include <windows.h>
  59. #include <windowsx.h>
  60. #include <mmsystem.h>
  61. #include <mmddk.h>
  62. #include <mmreg.h>
  63. #include <memory.h>
  64. #include <win32.h>
  65. #include <vfw.h>
  66. #include <msviddrv.h>
  67. #ifdef _WIN32
  68. #ifdef DAYTONA
  69. #include <wownt32.h>
  70. #endif
  71. #include <stdlib.h> // for mbstowcs and wcstombs
  72. #endif // _WIN32
  73. #ifdef _WIN32
  74. #include "compmn16.h"
  75. #endif
  76. #include "compmani.h"
  77. #include "thunk.h"
  78. #include "debug.h"
  79. #ifdef NT_THUNK32
  80. //==========================================================================;
  81. //
  82. //
  83. // --- === 32 BIT SIDE === ---
  84. //
  85. //
  86. //==========================================================================;
  87. /* -------------------------------------------------------------------------
  88. ** Handle and memory mapping functions.
  89. ** -------------------------------------------------------------------------
  90. */
  91. LPWOWHANDLE32 lpWOWHandle32;
  92. LPWOWHANDLE16 lpWOWHandle16;
  93. LPGETVDMPOINTER GetVDMPointer;
  94. LPWOWCALLBACK16 lpWOWCallback16;
  95. int ThunksInitialized;
  96. //
  97. // These wrap around whatever mapping mechanism is used on the platform
  98. // we are compiling for.
  99. //
  100. INLINE PVOID ptrFixMap16To32(const VOID * pv, DWORD cb);
  101. INLINE VOID ptrUnFix16(const VOID * pv);
  102. #ifdef CHICAGO
  103. //
  104. // -= Chicago implementation of memory mapping functions =-
  105. //
  106. //
  107. // Thunk helper routines in Chicago kernel
  108. //
  109. extern PVOID WINAPI MapSL(const VOID * pv);
  110. extern PVOID WINAPI MapSLFix(const VOID * pv);
  111. extern VOID WINAPI UnMapSLFixArray(DWORD dwCnt, const VOID * lpSels[]);
  112. PVOID INLINE ptrFixMap16To32(const VOID * pv, DWORD cb)
  113. {
  114. return MapSLFix(pv);
  115. }
  116. VOID INLINE ptrUnFix16(const VOID * pv)
  117. {
  118. UnMapSLFixArray(1, &pv);
  119. }
  120. #else // CHICAGO ELSE
  121. //
  122. // -= Daytona implementation of memory mapping functions =-
  123. //
  124. // Use #define to avoid having a function call
  125. #define ptrFixMap16To32(spv, cb) \
  126. GetVDMPointer( (DWORD) (DWORD_PTR) (spv), (cb), TRUE )
  127. //PVOID ptrFixMap16To32(const VOID * pv, DWORD cb)
  128. //{
  129. // return GetVDMPointer( (DWORD)pv, cb, TRUE );
  130. //}
  131. //
  132. // The unfix routine is a total noop.
  133. // We should really call WOWGetVDMPointerUnfix...
  134. //
  135. #define ptrUnFix16(spv)
  136. //VOID ptrUnFix16(const VOID * pv)
  137. //{
  138. // return;
  139. //}
  140. #endif // !CHICAGO
  141. //--------------------------------------------------------------------------;
  142. //
  143. //
  144. //
  145. //--------------------------------------------------------------------------;
  146. //
  147. // 16-bit structures
  148. //
  149. typedef struct {
  150. DWORD dwDCISize;
  151. LPCSTR lpszDCISectionName;
  152. LPCSTR lpszDCIAliasName;
  153. } DRVCONFIGINFO16;
  154. //
  155. // Useful functions
  156. //
  157. //
  158. // CopyAlloc - allocate a new piece of memory, and copy the data in
  159. // Must use LocalFree to release the memory later
  160. //
  161. PVOID CopyAlloc(PVOID pvSrc, UINT uSize)
  162. {
  163. PVOID pvDest;
  164. pvDest = (PVOID)LocalAlloc(LMEM_FIXED, uSize);
  165. if (pvDest != NULL) {
  166. CopyMemory(pvDest, pvSrc, uSize);
  167. }
  168. return pvDest;
  169. }
  170. /*
  171. * Copy data from source to dest where source is a 32bit pointer
  172. * and dest is a 16bit pointer
  173. */
  174. void CopyTo16Bit(LPVOID Dest16, LPVOID Src32, DWORD Length)
  175. {
  176. PVOID Dest32;
  177. if (Src32 == NULL) {
  178. return;
  179. }
  180. Dest32 = ptrFixMap16To32(Dest16, Length);
  181. CopyMemory(Dest32, Src32, Length);
  182. ptrUnFix16(Dest16);
  183. }
  184. /*
  185. * Copy data from source to dest where source is a 16bit pointer
  186. * and dest is a 32bit pointer
  187. */
  188. void CopyTo32Bit(LPVOID Dest32, LPVOID Src16, DWORD Length)
  189. {
  190. PVOID Src32;
  191. if (Src16 == NULL) {
  192. return;
  193. }
  194. Src32 = ptrFixMap16To32(Src16, Length);
  195. CopyMemory(Dest32, Src32, Length);
  196. ptrUnFix16(Src16);
  197. }
  198. #ifdef _INC_COMPMAN
  199. /*--------------------------------------------------------------------------*\
  200. | |
  201. | Now thunk the compman functions |
  202. | |
  203. | |
  204. | |
  205. | |
  206. \*--------------------------------------------------------------------------*/
  207. /*
  208. * Convert ICDRAWBEGIN structures
  209. */
  210. INLINE STATICFN void ConvertICDRAWBEGIN(ICDRAWBEGIN *DrawBegin32,
  211. LPBITMAPINFOHEADER lpBmi,
  212. DWORD dw)
  213. {
  214. ICDRAWBEGIN16 DrawBegin16;
  215. CopyTo32Bit(&DrawBegin16, (LPVOID)dw, sizeof(ICDRAWBEGIN16));
  216. DrawBegin32->dwFlags = DrawBegin16.dwFlags;
  217. DrawBegin32->hpal = ThunkHPAL(DrawBegin16.hpal);
  218. if (DrawBegin16.dwFlags & ICDRAW_HDC) {
  219. DrawBegin32->hwnd = ThunkHWND(DrawBegin16.hwnd);
  220. DrawBegin32->hdc = ThunkHDC(DrawBegin16.hdc);
  221. }
  222. DrawBegin32->xDst = (int)DrawBegin16.xDst;
  223. DrawBegin32->yDst = (int)DrawBegin16.yDst;
  224. DrawBegin32->dxDst = (int)DrawBegin16.dxDst;
  225. DrawBegin32->dyDst = (int)DrawBegin16.dyDst;
  226. CopyTo32Bit(lpBmi, DrawBegin16.lpbi, sizeof(BITMAPINFOHEADER));
  227. DrawBegin32->lpbi = lpBmi;
  228. DrawBegin32->xSrc = (int)DrawBegin16.xSrc;
  229. DrawBegin32->ySrc = (int)DrawBegin16.ySrc;
  230. DrawBegin32->dxSrc = (int)DrawBegin16.dxSrc;
  231. DrawBegin32->dySrc = (int)DrawBegin16.dySrc;
  232. DrawBegin32->dwRate = DrawBegin16.dwRate;
  233. DrawBegin32->dwScale = DrawBegin16.dwScale;
  234. }
  235. /*
  236. * Following logic copied from mvdm\wow32\wstruc.c - however since we
  237. * don't have the usage parameter we're a bit stuck on the size of the
  238. * entries.
  239. *
  240. * See also the video for windows documentation - only a limited range of
  241. * bitmap types are discussed.
  242. */
  243. INT GetBMI16Size(UNALIGNED BITMAPINFOHEADER *pbmi16)
  244. {
  245. int nHdrSize;
  246. int nEntSize;
  247. int nEntries;
  248. int nBitCount;
  249. DWORD dwClrUsed;
  250. nHdrSize = (int)pbmi16->biSize;
  251. /*
  252. * We don't have some of the info we need so assume RGBQUAD
  253. */
  254. nEntSize = sizeof(RGBQUAD);
  255. nBitCount = pbmi16->biBitCount;
  256. dwClrUsed = pbmi16->biClrUsed;
  257. /* the following block of code should be this:
  258. *
  259. * if ( nBitCount > 8 ) { // true colour
  260. * nEntries = 0; (ordinary case)
  261. * nEntries = 3; (BI_BITFIELDS case)
  262. * }
  263. * else if ( dwClrUsed ) {
  264. * nEntries = dwClrUsed;
  265. * }
  266. * else {
  267. * nEntries = 1 << nBitCount;
  268. * }
  269. *
  270. * but due to the fact that many apps don't initialize the biBitCount &
  271. * biClrUsed fields (especially biClrUsed) we have to do the following
  272. * sanity checking instead. v-cjones
  273. */
  274. if ( nBitCount <= 8 ) {
  275. nEntries = 1 << nBitCount;
  276. // sanity check for apps (lots) that don't init the dwClrUsed field
  277. if(dwClrUsed) {
  278. nEntries = (int)min((DWORD)nEntries, dwClrUsed);
  279. }
  280. } else {
  281. if (pbmi16->biCompression == BI_BITFIELDS)
  282. nEntries = 3;
  283. else
  284. nEntries = 0;
  285. }
  286. return ( nHdrSize + (nEntries * nEntSize) );
  287. }
  288. INLINE LPBITMAPINFO CopyBitmapInfo(DWORD Bi16)
  289. {
  290. UNALIGNED BITMAPINFOHEADER *pbmi16;
  291. LPBITMAPINFO lpbmi;
  292. pbmi16 = ptrFixMap16To32((PVOID)Bi16, 0);
  293. if ((int)pbmi16->biSize == 0) {
  294. pbmi16->biSize = sizeof(BITMAPINFOHEADER);
  295. DPF(0, "WARNING: null bitmap info size, setting it correctly");
  296. }
  297. lpbmi = (LPBITMAPINFO)CopyAlloc((LPVOID)pbmi16, GetBMI16Size(pbmi16));
  298. ptrUnFix16((PVOID)Bi16);
  299. return (lpbmi);
  300. }
  301. /*
  302. * Allocate a BITMAPINFO structure to contain 256 colours
  303. */
  304. INLINE LPBITMAPINFO AllocBitmapInfo()
  305. {
  306. return (PVOID)LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER)+
  307. (sizeof(RGBQUAD)*256));
  308. }
  309. INLINE LPBITMAPINFOHEADER CopyBitmapInfoHeader(DWORD Bi16)
  310. {
  311. UNALIGNED BITMAPINFOHEADER *pbmi16;
  312. LPBITMAPINFOHEADER lpbmi;
  313. pbmi16 = ptrFixMap16To32((PVOID)Bi16, 0);
  314. lpbmi = (LPBITMAPINFOHEADER)CopyAlloc((LPVOID)pbmi16, pbmi16->biSize);
  315. ptrUnFix16((PVOID)Bi16);
  316. return (lpbmi);
  317. }
  318. DWORD CopyICINFOTo16bit(DWORD dw, ICINFO *IcInfoCopy, DWORD Length)
  319. {
  320. ICINFO16 IcInfo;
  321. LONG ReturnCode;
  322. /*
  323. * Make a copy since the behaviour of wcstombs is undefined
  324. * for overlapping input and output
  325. */
  326. memcpy(&IcInfo, IcInfoCopy, FIELD_OFFSET(ICINFO, szName[0]));
  327. /*
  328. * Massage the strings
  329. */
  330. wcstombs(IcInfo.szName,
  331. IcInfoCopy->szName,
  332. sizeof(IcInfo.szName));
  333. // HACK : overwrite the last five characters with "[32]\0"
  334. if ((IcInfo.szName[0]))
  335. {
  336. UINT n = min(sizeof(IcInfo.szName)-5, lstrlenA(IcInfo.szName));
  337. IcInfo.szName[n++] = '[';
  338. IcInfo.szName[n++] = '3';
  339. IcInfo.szName[n++] = '2';
  340. IcInfo.szName[n++] = ']';
  341. IcInfo.szName[n] = '\0';
  342. }
  343. wcstombs(IcInfo.szDescription,
  344. IcInfoCopy->szDescription,
  345. sizeof(IcInfo.szDescription));
  346. // HACK : overwrite the last five characters with "[32]\0"
  347. if ((IcInfo.szDescription[0]))
  348. {
  349. UINT n = min(sizeof(IcInfo.szDescription)-5, lstrlenA(IcInfo.szDescription));
  350. IcInfo.szDescription[n++] = '[';
  351. IcInfo.szDescription[n++] = '3';
  352. IcInfo.szDescription[n++] = '2';
  353. IcInfo.szDescription[n++] = ']';
  354. IcInfo.szDescription[n] = '\0';
  355. }
  356. wcstombs(IcInfo.szDriver,
  357. IcInfoCopy->szDriver,
  358. sizeof(IcInfo.szDriver));
  359. IcInfo.dwSize = sizeof(IcInfo);
  360. ReturnCode = min(Length, IcInfo.dwSize);
  361. CopyTo16Bit((LPVOID)dw, &IcInfo, ReturnCode);
  362. return ReturnCode;
  363. }
  364. /*
  365. * We need to convert the various fields in the ICDECOMPRESS/EX
  366. * structure(s). Fortunately(?) the EX structure is a simple
  367. * extension.
  368. */
  369. typedef struct {
  370. //
  371. // same as ICM_DECOMPRESS
  372. //
  373. DWORD dwFlags;
  374. LPBITMAPINFOHEADER lpbiSrc; // BITMAPINFO of compressed data
  375. LPVOID lpSrc; // compressed data
  376. LPBITMAPINFOHEADER lpbiDst; // DIB to decompress to
  377. LPVOID lpDst; // output data
  378. //
  379. // new for ICM_DECOMPRESSEX
  380. //
  381. short xDst; // destination rectangle
  382. short yDst;
  383. short dxDst;
  384. short dyDst;
  385. short xSrc; // source rectangle
  386. short ySrc;
  387. short dxSrc;
  388. short dySrc;
  389. } ICDECOMPRESSEX16;
  390. STATICFN DWORD DoICM_DecompressX(DWORD hic, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2)
  391. {
  392. ICDECOMPRESSEX16 UNALIGNED *lpicdmpr16;
  393. ICDECOMPRESSEX ICDecompressEx;
  394. LRESULT l;
  395. BOOL fQuery = TRUE;
  396. /* Copy the standard or extended structure */
  397. lpicdmpr16 = ptrFixMap16To32( (PVOID)dwP1, (DWORD) dwP2 );
  398. ICDecompressEx.dwFlags = lpicdmpr16->dwFlags;
  399. ICDecompressEx.lpbiSrc = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)lpicdmpr16->lpbiSrc);
  400. if (NULL == ICDecompressEx.lpbiSrc) {
  401. ptrUnFix16( (PVOID)dwP1 );
  402. return (DWORD)ICERR_MEMORY;
  403. }
  404. ICDecompressEx.lpbiDst = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)lpicdmpr16->lpbiDst);
  405. if ((NULL == ICDecompressEx.lpbiDst) && (msg != ICM_DECOMPRESSEX_QUERY)) {
  406. LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc );
  407. ptrUnFix16( (PVOID)dwP1 );
  408. return (DWORD)ICERR_MEMORY;
  409. }
  410. if (msg == ICM_DECOMPRESSEX || msg == ICM_DECOMPRESS) {
  411. // map the source and destination pointers
  412. ICDecompressEx.lpSrc = ptrFixMap16To32(lpicdmpr16->lpSrc,
  413. ICDecompressEx.lpbiSrc->biSizeImage);
  414. ICDecompressEx.lpDst = ptrFixMap16To32(lpicdmpr16->lpDst,
  415. ICDecompressEx.lpbiDst->biSizeImage);
  416. fQuery = FALSE; // remember
  417. } else { // it is a query and we do not map the pointers
  418. ICDecompressEx.lpSrc = NULL;
  419. ICDecompressEx.lpDst = NULL;
  420. }
  421. if (dwP2 == sizeof(ICDECOMPRESSEX16) ) {
  422. ICDecompressEx.xDst = (int)lpicdmpr16->xDst;
  423. ICDecompressEx.yDst = (int)lpicdmpr16->yDst;
  424. ICDecompressEx.dxDst = (int)lpicdmpr16->dxDst;
  425. ICDecompressEx.dyDst = (int)lpicdmpr16->dyDst;
  426. ICDecompressEx.xSrc = (int)lpicdmpr16->xSrc;
  427. ICDecompressEx.ySrc = (int)lpicdmpr16->ySrc;
  428. ICDecompressEx.dxSrc = (int)lpicdmpr16->dxSrc;
  429. ICDecompressEx.dySrc = (int)lpicdmpr16->dySrc;
  430. dwP2 = sizeof(ICDecompressEx); // Make the size relate to 32 bit
  431. }
  432. l = ICSendMessage( (HIC)hic, (UINT)msg, (LPARAM)&ICDecompressEx, dwP2 );
  433. /* I don't think the following is needed // FrankYe 11/18/94
  434. // If we do, don't just uncomment this. You gotta use biUnMapSL
  435. if ( l == ICERR_OK) {
  436. CopyTo16Bit( lpicdmpr16->lpbiDst, ICDecompressEx.lpbiDst,
  437. sizeof(BITMAPINFOHEADER) );
  438. }
  439. */
  440. LocalFree( (HLOCAL)ICDecompressEx.lpbiSrc );
  441. if (ICDecompressEx.lpbiDst) {
  442. LocalFree( (HLOCAL)ICDecompressEx.lpbiDst );
  443. }
  444. if (!fQuery) {
  445. ptrUnFix16( lpicdmpr16->lpSrc );
  446. ptrUnFix16( lpicdmpr16->lpDst );
  447. }
  448. ptrUnFix16( (PVOID)dwP1 );
  449. return (DWORD) l;
  450. }
  451. /*
  452. * Generate our thunks - refer to msvideo!compman.c for definitions of
  453. * functions.
  454. *
  455. * NOTE - we often rely here on the fact that most of the message
  456. * parameter structures are identical for 16 and 32-bit - ie they
  457. * contain DWORDs and 32-bit pointers.
  458. */
  459. //--------------------------------------------------------------------------;
  460. //
  461. // LONG thkStatusProc32
  462. //
  463. // When a client calls the 16-bit ICSetStatusProc while using a
  464. // 32-bit codec, this function is set as the StatusProc in 32-bit codec.
  465. // This function will then thunk down to 16-bits and call the
  466. // client's StatusProc.
  467. //
  468. // Arguments:
  469. // LPARAM lParam : contains linear ptr to an ICSTATUSTHUNKDESC. The
  470. // ICSTATUSTHUNKDESC is created during the call to ICSetStatusProc.
  471. //
  472. // UINT uMsg :
  473. //
  474. // LONG l :
  475. //
  476. // Return value:
  477. // LONG :
  478. //
  479. //--------------------------------------------------------------------------;
  480. LONG CALLBACK thkStatusProc32(LPARAM lParam, UINT uMsg, LONG l)
  481. {
  482. LPICSTATUSTHUNKDESC lpstd;
  483. LONG lr;
  484. DPFS(dbgThunks, 4, "thkStatusProc32()");
  485. lpstd = (LPICSTATUSTHUNKDESC)lParam;
  486. ASSERT( lpstd->fnStatusProcS );
  487. ASSERT( lpstd->pfnthkStatusProc16S );
  488. lr = 0;
  489. //
  490. // TODO: Thunk error string for ICSTATUS_ERROR. Currently I'm not
  491. // sure if ICSTATUS_ERROR is documented.
  492. //
  493. //#pragma message(REMIND("thkStatusProc32: thunk ICSTATUS_ERROR"))
  494. if (ICSTATUS_ERROR == uMsg) {
  495. //
  496. // Is l supposed to be an LPSTR to an error string???
  497. //
  498. l = (LONG)0;
  499. }
  500. //
  501. //
  502. //
  503. lpstd->uMsg = uMsg;
  504. lpstd->l = l;
  505. lr = lpWOWCallback16(lpstd->pfnthkStatusProc16S, (DWORD)lpstd->lpstdS);
  506. return (lr);
  507. }
  508. //--------------------------------------------------------------------------;
  509. //
  510. // LRESULT thkSetStatusProc
  511. //
  512. // This function is called as a result of thunking up from a call to
  513. // the 16-bit ICSetStatusProc. It will call the 32-bit ICSetStatusProc
  514. // to install thkStatusProc32.
  515. //
  516. // Arguments:
  517. // HIC hic : handle to 32-bit codec
  518. //
  519. // LPARAM lParam : contains linear ptr to an ICSTATUSTHUNKDESC. The
  520. // ICSTATUSTHUNKDESC is created in the call to the 16-bit
  521. // ICSetStatusProc. This will be set as the lParam to be passed
  522. // to our thkStatusProc32.
  523. //
  524. // Return value:
  525. // LRESULT :
  526. //
  527. //--------------------------------------------------------------------------;
  528. LRESULT WINAPI thkSetStatusProc(HIC hic, LPICSTATUSTHUNKDESC lpstd)
  529. {
  530. DPFS(dbgThunks, 3, "thkSetStatusProc()");
  531. return ICSetStatusProc(hic, 0L, (LPARAM)lpstd, thkStatusProc32);
  532. }
  533. //--------------------------------------------------------------------------;
  534. //
  535. //
  536. //
  537. //--------------------------------------------------------------------------;
  538. LRESULT FAR PASCAL ICInfo32(DWORD fccType, DWORD fccHandler, ICINFO16 FAR * lpicInfo)
  539. {
  540. ICINFO ReturnedICInfo;
  541. StartThunk(ICInfo);
  542. //DPF2(("Calling ICInfo %4.4hs %4.4hs %8X", &fccType, &fccHandler, lpicInfo));
  543. ReturnedICInfo.fccHandler = 0; // Initialise...
  544. ReturnCode = ICInfo(fccType, fccHandler, &ReturnedICInfo);
  545. CopyICINFOTo16bit((DWORD)(DWORD_PTR)lpicInfo, &ReturnedICInfo, sizeof(ReturnedICInfo));
  546. EndThunk()
  547. }
  548. LRESULT FAR PASCAL ICInfoInternal32(DWORD fccType, DWORD fccHandler, ICINFO16 FAR * lpicInfo, ICINFOI FAR * lpicInfoI)
  549. {
  550. return ICInfo32(fccType, fccHandler, lpicInfo);
  551. #if 0
  552. ICINFO ReturnedICInfo;
  553. ICINFOI ReturnedICInfoI;
  554. StartThunk(ICInfo);
  555. // DPF(1, "Calling ICInfo %4.4hs %4.4hs %8X", &fccType, &fccHandler, lpicInfo);
  556. ReturnedICInfo.fccHandler = 0; // Initialise...
  557. ReturnCode = ICInfoInternal(fccType, fccHandler, &ReturnedICInfo, &ReturnedICInfoI);
  558. if (NULL != lpicInfoI) {
  559. //
  560. // Assuming no members of ICINFOI need special thunking
  561. //
  562. CopyTo16Bit(lpicInfoI, &ReturnedICInfoI, sizeof(*lpicInfoI));
  563. }
  564. CopyICINFOTo16bit((DWORD)(DWORD_PTR)lpicInfo, &ReturnedICInfo, sizeof(ReturnedICInfo));
  565. EndThunk()
  566. #endif
  567. }
  568. LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2)
  569. {
  570. StartThunk(ICSendMessage);
  571. DPF(2,"Calling ICSendMessage %4X %4X %8X %8X",
  572. hic, msg, dwP1, dwP2);
  573. switch (msg) {
  574. case ICM_GETSTATE:
  575. case ICM_SETSTATE:
  576. if (dwP1 == 0) {
  577. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  578. (UINT)msg,
  579. dwP1,
  580. dwP2);
  581. } else {
  582. PVOID pState;
  583. /*
  584. * Create some aligned memory to return or pass on the data
  585. */
  586. pState = (PVOID)LocalAlloc(LPTR, dwP2);
  587. if (pState == NULL) {
  588. ReturnCode = 0;
  589. } else {
  590. if ((UINT)msg == ICM_SETSTATE) {
  591. // Copy the data from 16 bit land
  592. CopyTo32Bit(pState, (LPVOID)dwP1, (DWORD) dwP2);
  593. }
  594. ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg,
  595. (DWORD_PTR)pState, dwP2);
  596. /*
  597. * Copy back the state, if the driver returned any data
  598. */
  599. if (ReturnCode > 0 && (UINT)msg == ICM_GETSTATE) {
  600. CopyTo16Bit((LPVOID)dwP1, pState,
  601. min((DWORD)ReturnCode, (DWORD) dwP2));
  602. }
  603. LocalFree((HLOCAL)pState);
  604. }
  605. }
  606. break;
  607. case ICM_GETINFO:
  608. {
  609. ICINFO IcInfo;
  610. ReturnCode = ICGetInfo((HIC)(DWORD)hic, &IcInfo, sizeof(IcInfo));
  611. if (ReturnCode != 0) {
  612. ReturnCode = CopyICINFOTo16bit((DWORD) (DWORD_PTR) dwP1, &IcInfo, (DWORD) ReturnCode);
  613. }
  614. }
  615. break;
  616. case ICM_CONFIGURE:
  617. case ICM_ABOUT:
  618. /*
  619. * dwP1 = -1 is a special value asking if config is supported,
  620. * otherwise it's a window handle
  621. */
  622. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  623. (UINT)msg,
  624. dwP1 == (DWORD_PTR)-1 ?
  625. (DWORD_PTR)-1 :
  626. (DWORD_PTR)ThunkHWND(LOWORD(dwP1)),
  627. dwP2);
  628. break;
  629. case ICM_COMPRESS:
  630. {
  631. if (dwP2 != sizeof(ICCOMPRESS)) { // validation code
  632. ReturnCode = ICERR_BADSIZE;
  633. } else {
  634. DWORD dwFlags;
  635. LPDWORD lpdwFlags16, lpckid16;
  636. LPBITMAPINFOHEADER lpbih16;
  637. LPVOID lpInput, lpOutput, lpPrev;
  638. DWORD ckid;
  639. ICCOMPRESS IcCompress;
  640. ReturnCode = ICERR_OK;
  641. /*
  642. * We need to convert the various fields in the ICCOMPRESS
  643. * structure
  644. */
  645. CopyTo32Bit( &IcCompress, (LPVOID)dwP1, (DWORD) dwP2 );
  646. IcCompress.lpbiInput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiInput);
  647. if (NULL == IcCompress.lpbiInput) {
  648. ReturnCode = ICERR_MEMORY;
  649. break;
  650. }
  651. lpbih16 = IcCompress.lpbiOutput;
  652. IcCompress.lpbiOutput = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiOutput);
  653. if (NULL == IcCompress.lpbiOutput) {
  654. LocalFree((HLOCAL)IcCompress.lpbiInput);
  655. ReturnCode = ICERR_MEMORY;
  656. break;
  657. }
  658. lpInput = IcCompress.lpInput;
  659. IcCompress.lpInput = ptrFixMap16To32(IcCompress.lpInput, IcCompress.lpbiInput->biSizeImage);
  660. lpOutput = IcCompress.lpOutput;
  661. IcCompress.lpOutput = ptrFixMap16To32(IcCompress.lpOutput, IcCompress.lpbiOutput->biSizeImage);
  662. lpPrev = NULL;
  663. if (IcCompress.lpbiPrev) {
  664. IcCompress.lpbiPrev = (LPBITMAPINFOHEADER)CopyBitmapInfo((DWORD)(DWORD_PTR)IcCompress.lpbiPrev);
  665. if (NULL == IcCompress.lpbiPrev) {
  666. LocalFree((HLOCAL)IcCompress.lpbiOutput);
  667. LocalFree((HLOCAL)IcCompress.lpbiInput);
  668. ptrUnFix16(lpOutput);
  669. ptrUnFix16(lpInput);
  670. ReturnCode = ICERR_MEMORY;
  671. break;
  672. }
  673. lpPrev = IcCompress.lpPrev;
  674. IcCompress.lpPrev = ptrFixMap16To32(IcCompress.lpPrev, IcCompress.lpbiPrev->biSizeImage);
  675. }
  676. lpdwFlags16 = IcCompress.lpdwFlags;
  677. if (lpdwFlags16 != NULL) {
  678. CopyTo32Bit(&dwFlags, lpdwFlags16, sizeof(DWORD));
  679. IcCompress.lpdwFlags = &dwFlags;
  680. }
  681. if (IcCompress.lpckid != NULL) {
  682. lpckid16 = IcCompress.lpckid;
  683. IcCompress.lpckid = &ckid;
  684. }
  685. ReturnCode = ICSendMessage((HIC)(DWORD)hic, (UINT)msg,
  686. (DWORD_PTR)&IcCompress, dwP2);
  687. if (ReturnCode == ICERR_OK) {
  688. CopyTo16Bit( lpbih16, IcCompress.lpbiOutput,
  689. sizeof(BITMAPINFOHEADER) );
  690. if (lpdwFlags16 != NULL) {
  691. CopyTo16Bit(lpdwFlags16, &dwFlags, sizeof(DWORD));
  692. }
  693. if (IcCompress.lpckid != NULL) {
  694. CopyTo16Bit(lpckid16, &ckid, sizeof(DWORD));
  695. }
  696. }
  697. /*
  698. ** Free the bitmap info storage regardless of the return code
  699. */
  700. if (NULL != IcCompress.lpbiPrev) {
  701. LocalFree((HLOCAL)IcCompress.lpbiPrev);
  702. }
  703. LocalFree((HLOCAL)IcCompress.lpbiOutput);
  704. LocalFree((HLOCAL)IcCompress.lpbiInput);
  705. if (NULL != lpPrev)
  706. {
  707. ptrUnFix16(lpPrev);
  708. }
  709. ptrUnFix16(lpOutput);
  710. ptrUnFix16(lpInput);
  711. }
  712. }
  713. break;
  714. case ICM_COMPRESS_GET_SIZE:
  715. case ICM_COMPRESS_BEGIN:
  716. case ICM_COMPRESS_QUERY:
  717. case ICM_DECOMPRESS_BEGIN:
  718. case ICM_DECOMPRESS_GET_PALETTE:
  719. case ICM_DECOMPRESS_SET_PALETTE: // only takes one BitmapInfoHeader
  720. case ICM_DECOMPRESS_QUERY:
  721. {
  722. LPBITMAPINFO bmi1, bmi2;
  723. bmi1 = bmi2 = NULL;
  724. if (dwP1 != 0) {
  725. bmi1 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1);
  726. }
  727. if (dwP2 != 0) {
  728. bmi2 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP2);
  729. }
  730. if ( (NULL == bmi1 && 0 != dwP1) || (NULL == bmi2 && 0 != dwP2) )
  731. {
  732. if (NULL != bmi1) LocalFree((HLOCAL)bmi1);
  733. if (NULL != bmi2) LocalFree((HLOCAL)bmi2);
  734. ReturnCode = (UINT)msg == ICM_COMPRESS_GET_SIZE ? 0 : ICERR_MEMORY;
  735. } else {
  736. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  737. (UINT)msg,
  738. (DWORD_PTR)bmi1,
  739. (DWORD_PTR)bmi2);
  740. if (bmi2 != NULL) {
  741. // We might have to return data to the 16 bit side.
  742. // The messages for which we have to do this are:
  743. // ICM_DECOMPRESS_QUERY (iff retcode == ICERR_OK)
  744. // ICM_DECOMPRESS_GET_PALETTE (iff retcode >= 0)
  745. if (((ReturnCode == ICERR_OK) && (msg == ICM_DECOMPRESS_QUERY))
  746. || ((ReturnCode >= 0) && (msg == ICM_DECOMPRESS_GET_PALETTE)))
  747. {
  748. CopyTo16Bit((LPVOID)dwP2, bmi2, GetBMI16Size((LPBITMAPINFOHEADER)bmi2));
  749. }
  750. LocalFree((HLOCAL)bmi2);
  751. }
  752. }
  753. if (bmi1 != NULL) {
  754. LocalFree((HLOCAL)bmi1);
  755. }
  756. }
  757. break;
  758. case ICM_COMPRESS_END:
  759. case ICM_DECOMPRESS_END:
  760. case ICM_DECOMPRESSEX_END:
  761. case ICM_DRAW_END:
  762. case ICM_DRAW_FLUSH:
  763. case ICM_DRAW_START: //??
  764. case ICM_DRAW_STOP: //??
  765. case ICM_DRAW_SETTIME:
  766. case ICM_DRAW_RENDERBUFFER:
  767. case ICM_SETQUALITY:
  768. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  769. (UINT)msg,
  770. dwP1,
  771. dwP2);
  772. break;
  773. case ICM_DRAW_GETTIME:
  774. case ICM_GETBUFFERSWANTED:
  775. case ICM_GETDEFAULTQUALITY:
  776. case ICM_GETDEFAULTKEYFRAMERATE:
  777. case ICM_GETQUALITY:
  778. {
  779. DWORD dwReturn;
  780. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  781. (UINT)msg,
  782. (DWORD_PTR)&dwReturn,
  783. dwP2);
  784. // Note: although the definition of these messages state
  785. // that dwParam2 is not used, trouble will brew if the
  786. // decompressor ever tries to use dwParam2. We cannot
  787. // thunk non-standard uses of this parameter.
  788. if (ReturnCode == ICERR_OK) {
  789. CopyTo16Bit((LPVOID)dwP1, &dwReturn, sizeof(DWORD));
  790. }
  791. }
  792. break;
  793. case ICM_COMPRESS_GET_FORMAT:
  794. case ICM_DECOMPRESS_GET_FORMAT:
  795. /*
  796. * This is a tricky one - we first have to find the size of
  797. * the output format so we can get a copy of the (aligned)
  798. * version before passing it back to the app
  799. */
  800. {
  801. LPBITMAPINFO bmi1, bmi2;
  802. if ( dwP1 == 0L ) {
  803. ReturnCode = ICERR_OK;
  804. break;
  805. }
  806. bmi1 = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1);
  807. if (bmi1 == NULL) {
  808. ReturnCode = ICERR_MEMORY;
  809. } else {
  810. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  811. (UINT)msg,
  812. (DWORD_PTR)bmi1,
  813. 0);
  814. if (ReturnCode > 0 && dwP2 != 0) {
  815. bmi2 = LocalAlloc(LMEM_FIXED, ReturnCode);
  816. if (bmi2 == NULL) {
  817. /*
  818. * Can't do anything!!! - there's not good return code
  819. */
  820. ReturnCode = ICERR_MEMORY;
  821. } else {
  822. DWORD Length;
  823. Length = (DWORD) ReturnCode; /* preserve length */
  824. ReturnCode =
  825. ICSendMessage((HIC)(DWORD)hic,
  826. (UINT)msg,
  827. (DWORD_PTR)bmi1,
  828. (DWORD_PTR)bmi2);
  829. if (ReturnCode >= 0) {
  830. CopyTo16Bit((LPVOID)dwP2, bmi2, Length);
  831. }
  832. LocalFree((HLOCAL)bmi2);
  833. }
  834. }
  835. LocalFree((HLOCAL)bmi1);
  836. }
  837. }
  838. break;
  839. case ICM_DECOMPRESS:
  840. if (dwP2 != sizeof(ICDECOMPRESS)) {
  841. ReturnCode = ICERR_BADSIZE;
  842. } else {
  843. ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2);
  844. }
  845. break;
  846. case ICM_DECOMPRESSEX:
  847. case ICM_DECOMPRESSEX_BEGIN:
  848. case ICM_DECOMPRESSEX_QUERY:
  849. if (dwP2 != sizeof(ICDECOMPRESSEX16)) {
  850. ReturnCode = ICERR_BADSIZE;
  851. } else {
  852. ReturnCode = DoICM_DecompressX(hic, msg, dwP1, dwP2);
  853. }
  854. break;
  855. case ICM_DRAW:
  856. /*
  857. * We can't support unknown extensions
  858. */
  859. if (dwP2 != sizeof(ICDRAW)) {
  860. ReturnCode = ICERR_BADSIZE;
  861. } else {
  862. ICDRAW ICDraw;
  863. BITMAPINFOHEADER bmi;
  864. LPVOID lpData;
  865. CopyTo32Bit(&ICDraw, (LPVOID)dwP1, (DWORD) dwP2);
  866. /*
  867. * We have to assume this is a draw for video
  868. */
  869. CopyTo32Bit(&bmi, ICDraw.lpFormat, sizeof(BITMAPINFOHEADER));
  870. ICDraw.lpFormat = (LPVOID)&bmi;
  871. lpData = ICDraw.lpData;
  872. ICDraw.lpData = ptrFixMap16To32(ICDraw.lpData, ICDraw.cbData);
  873. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  874. (UINT)msg,
  875. (DWORD_PTR)&ICDraw,
  876. dwP2);
  877. ptrUnFix16(lpData);
  878. }
  879. break;
  880. case ICM_DRAW_BEGIN:
  881. {
  882. ICDRAWBEGIN InputFormat;
  883. BITMAPINFOHEADER bmihInput;
  884. ConvertICDRAWBEGIN(&InputFormat, &bmihInput, (DWORD) (DWORD_PTR) dwP1);
  885. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  886. (UINT)msg,
  887. (DWORD_PTR)&InputFormat,
  888. dwP2);
  889. }
  890. break;
  891. case ICM_DRAW_CHANGEPALETTE:
  892. case ICM_DRAW_QUERY:
  893. {
  894. LPBITMAPINFO lpbi;
  895. lpbi = CopyBitmapInfo((DWORD) (DWORD_PTR) dwP1);
  896. if (lpbi == NULL) {
  897. ReturnCode = ICERR_MEMORY;
  898. } else {
  899. ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic,
  900. (UINT)msg,
  901. (DWORD_PTR)lpbi,
  902. dwP2);
  903. LocalFree((HLOCAL)lpbi);
  904. }
  905. }
  906. break;
  907. case ICM_DRAW_REALIZE:
  908. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  909. (UINT)msg,
  910. (DWORD_PTR)ThunkHDC(LOWORD(dwP1)),
  911. dwP2);
  912. break;
  913. case ICM_DRAW_WINDOW:
  914. {
  915. RECT_SHORT SRect;
  916. RECT Rect;
  917. CopyTo32Bit(&SRect, (LPVOID)dwP1, sizeof(SRect));
  918. SHORT_RECT_TO_RECT(Rect, SRect);
  919. ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic,
  920. (UINT)msg,
  921. (DWORD_PTR)&Rect,
  922. dwP2);
  923. }
  924. break;
  925. // The next three messages are INTERNAL ones
  926. case ICM_GETERRORTEXT:
  927. break;
  928. case ICM_GETFORMATNAME:
  929. break;
  930. case ICM_ENUMFORMATS:
  931. break;
  932. case ICM_COMPRESS_FRAMES_INFO:
  933. {
  934. ICCOMPRESSFRAMES icf32;
  935. // We might explode if we get too small a length and start treating
  936. // some of the elements as pointers anyway. Just fail the call.
  937. // (WIN95C bug 8615).
  938. // dwP2 is the length of the 16 bit structure and we only know
  939. // the size of the 32 bit structure, but thankfully they're the
  940. // same.
  941. if (dwP2 < sizeof(ICCOMPRESSFRAMES)) {
  942. ReturnCode = ICERR_BADPARAM;
  943. break;
  944. }
  945. CopyTo32Bit(&icf32, (LPBYTE)dwP1, (DWORD) dwP2);
  946. // Now fix up the 32 bit structure
  947. icf32.PutData = icf32.GetData = NULL; // For safety. should not be used for this message
  948. if (icf32.lpbiOutput) {
  949. icf32.lpbiOutput = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icf32.lpbiOutput);
  950. }
  951. if (icf32.lpbiInput) {
  952. icf32.lpbiInput = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icf32.lpbiInput);
  953. }
  954. // According to the documentation, lInput and lOutput are undefined. Treating
  955. // them as pointers is as scary as a really scary thing.
  956. #if 0
  957. lInput = icf32.lInput;
  958. icf32.lInput = (LPARAM)ptrFixMap16To32((LPVOID)icf32.lInput, icf32.lpbiInput->biSizeImage);
  959. lOutput = icf32.lOutput;
  960. icf32.lOutput = (LPARAM)ptrFixMap16To32((LPVOID)icf32.lOutput, icf32.lpbiOutput->biSizeImage);
  961. #endif
  962. // After the fixups have been done, call the actual routine
  963. ReturnCode = ICSendMessage((HIC)(DWORD_PTR)hic,
  964. (UINT)msg,
  965. (DWORD_PTR)&icf32,
  966. dwP2);
  967. #if 0
  968. ptrUnFix16((LPVOID)lOutput);
  969. ptrUnFix16((LPVOID)lInput);
  970. #endif
  971. if (icf32.lpbiOutput) {
  972. LocalFree(icf32.lpbiOutput);
  973. }
  974. if (icf32.lpbiInput) {
  975. LocalFree(icf32.lpbiInput);
  976. }
  977. }
  978. break;
  979. case ICM_DRAW_GET_PALETTE:
  980. {
  981. ReturnCode = ICSendMessage((HIC) hic,
  982. (UINT)msg,
  983. dwP1,
  984. dwP2);
  985. if ((ReturnCode != 0L) && (ReturnCode != ICERR_UNSUPPORTED)) {
  986. #ifdef CHICAGO
  987. ReturnCode = (LRESULT)(WORD)ReturnCode;
  988. #else
  989. FARPROC lpWOWHandle16;
  990. HMODULE hmodWow;
  991. if ( (hmodWow = GetModuleHandle( GET_MAPPING_MODULE_NAME ))
  992. && (lpWOWHandle16 = GetProcAddress(hmodWow, "WOWHandle16"))) {
  993. ReturnCode = (WORD)(lpWOWHandle16((HANDLE)ReturnCode, (WOW_HANDLE_TYPE)WOW_TYPE_HPALETTE));
  994. } else {
  995. ReturnCode = ICERR_ERROR;
  996. }
  997. #endif
  998. }
  999. }
  1000. break;
  1001. case ICM_DRAW_SUGGESTFORMAT:
  1002. {
  1003. ICDRAWSUGGEST icdrwsug;
  1004. LPBITMAPINFOHEADER lpbiSuggest16;
  1005. LPBITMAPINFOHEADER lpbiSuggest;
  1006. DPF(4, "!ICMSendMessage32: ICM_DRAW_SUGGESTFORMAT: dwP1=%08lXh, dwP2=%08lXh", dwP1, dwP2);
  1007. //
  1008. CopyTo32Bit(&icdrwsug, (LPBYTE)dwP1, (DWORD) dwP2);
  1009. lpbiSuggest = NULL;
  1010. lpbiSuggest16 = icdrwsug.lpbiSuggest;
  1011. if (lpbiSuggest16) {
  1012. lpbiSuggest = ptrFixMap16To32(lpbiSuggest16, 0);
  1013. }
  1014. // Now fix up the 32 bit structure
  1015. if (icdrwsug.lpbiIn) {
  1016. icdrwsug.lpbiIn = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icdrwsug.lpbiIn);
  1017. }
  1018. if (icdrwsug.lpbiSuggest) {
  1019. icdrwsug.lpbiSuggest = CopyBitmapInfoHeader((DWORD)(DWORD_PTR)icdrwsug.lpbiSuggest);
  1020. }
  1021. // After the fixups have been done, call the actual routine
  1022. ReturnCode = ICSendMessage((HIC)(DWORD)hic,
  1023. (UINT)msg,
  1024. (DWORD_PTR)&icdrwsug,
  1025. dwP2);
  1026. if (icdrwsug.lpbiIn) {
  1027. LocalFree(icdrwsug.lpbiIn);
  1028. }
  1029. // We must return the 32 bit suggested format to 16 bit land
  1030. if (icdrwsug.lpbiSuggest) {
  1031. if (ReturnCode == ICERR_OK) {
  1032. CopyMemory( lpbiSuggest, icdrwsug.lpbiSuggest,
  1033. lpbiSuggest->biSize);
  1034. }
  1035. LocalFree(icdrwsug.lpbiSuggest);
  1036. ptrUnFix16(lpbiSuggest16);
  1037. }
  1038. }
  1039. break;
  1040. case ICM_SET_STATUS_PROC:
  1041. // We do not need to support this under NT. It is much
  1042. // easier not to add the callback support... even if we could
  1043. // guarantee to be on the right thread to actually do the callback.
  1044. //
  1045. // This message has its own thunk!
  1046. //
  1047. ASSERT( FALSE );
  1048. default:
  1049. ReturnCode = ICERR_UNSUPPORTED;
  1050. break;
  1051. }
  1052. EndThunk()
  1053. }
  1054. INLINE LRESULT FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode)
  1055. {
  1056. StartThunk(ICOpen);
  1057. DPF(1, "Calling ICOpen %4.4hs %4.4hs %4X", &fccType, &fccHandler, wMode);
  1058. ReturnCode = (LONG_PTR)ICOpen(fccType, fccHandler, (UINT)wMode);
  1059. EndThunk();
  1060. }
  1061. INLINE LRESULT FAR PASCAL ICClose32(DWORD hic)
  1062. {
  1063. StartThunk(ICClose);
  1064. ReturnCode = ICClose((HIC)hic);
  1065. EndThunk();
  1066. }
  1067. #endif // _INC_COMPMAN
  1068. DWORD ICMThunk32(DWORD dwThunkId,DWORD dw1,DWORD dw2,DWORD dw3,DWORD dw4)
  1069. {
  1070. //
  1071. // Make sure we've got thunking functionality
  1072. //
  1073. #if 0
  1074. {
  1075. char szBuffer[80];
  1076. char szMsg[32];
  1077. switch (dwThunkId) {
  1078. case compThunkICSendMessage32:
  1079. lstrcpyA( szMsg, "ICSendMessage32" );
  1080. break;
  1081. case compThunkICInfoInternal32:
  1082. lstrcpyA( szMsg, "ICInfoInternal32" );
  1083. break;
  1084. case compThunkICOpen32:
  1085. lstrcpyA( szMsg, "ICOpen32" );
  1086. break;
  1087. case compThunkICClose32:
  1088. lstrcpyA( szMsg, "ICClose32" );
  1089. break;
  1090. default:
  1091. lstrcpyA( szMsg, "Unknown" );
  1092. break;
  1093. }
  1094. wsprintfA( szBuffer, "%18.18s 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
  1095. szMsg, dw1, dw2, dw3, dw4);
  1096. OutputDebugStringA( szBuffer );
  1097. }
  1098. #endif
  1099. if (ThunksInitialized <= 0) {
  1100. HMODULE hMod;
  1101. if (ThunksInitialized == -1) {
  1102. return (DWORD)ICERR_ERROR;
  1103. }
  1104. hMod = GetModuleHandle(GET_MAPPING_MODULE_NAME);
  1105. if (hMod != NULL) {
  1106. GetVDMPointer =
  1107. (LPGETVDMPOINTER)GetProcAddress(hMod, GET_VDM_POINTER_NAME);
  1108. lpWOWHandle32 =
  1109. (LPWOWHANDLE32)GetProcAddress(hMod, GET_HANDLE_MAPPER32 );
  1110. lpWOWHandle16 =
  1111. (LPWOWHANDLE16)GetProcAddress(hMod, GET_HANDLE_MAPPER16 );
  1112. lpWOWCallback16 =
  1113. (LPWOWCALLBACK16)GetProcAddress(hMod, GET_CALLBACK16);
  1114. }
  1115. if ( GetVDMPointer == NULL ||
  1116. lpWOWHandle16 == NULL ||
  1117. lpWOWHandle32 == NULL ||
  1118. lpWOWCallback16 == NULL ) {
  1119. ThunksInitialized = -1;
  1120. return (DWORD)ICERR_ERROR;
  1121. } else {
  1122. ThunksInitialized = 1;
  1123. }
  1124. }
  1125. //
  1126. // Perform the requested function
  1127. //
  1128. switch (dwThunkId) {
  1129. case compThunkICSendMessage32:
  1130. return (DWORD) ICSendMessage32(dw1, (UINT)dw2, dw3, dw4);
  1131. break;
  1132. case compThunkICInfoInternal32:
  1133. return (DWORD) ICInfoInternal32(dw1, dw2, (ICINFOA FAR * )dw3, (ICINFOI FAR *)dw4);
  1134. break;
  1135. case compThunkICOpen32:
  1136. return (DWORD) ICOpen32(dw1, dw2, (UINT)dw3);
  1137. break;
  1138. case compThunkICClose32:
  1139. return (DWORD) ICClose32(dw1);
  1140. break;
  1141. case compThunkICOpenFunction32:
  1142. {
  1143. DWORD fccType;
  1144. DWORD fccHandler;
  1145. UINT uMode;
  1146. FARPROC lpfnHandler;
  1147. fccType = dw1;
  1148. fccHandler = dw2;
  1149. uMode = (UINT)dw3;
  1150. lpfnHandler = (FARPROC)dw4;
  1151. // !!! this won't work
  1152. return (DWORD) (DWORD_PTR) ICOpenFunction( fccType, fccHandler, uMode, lpfnHandler );
  1153. break;
  1154. }
  1155. case compThunkICSetStatusProc32:
  1156. {
  1157. DWORD lpstdS;
  1158. DWORD cbStruct;
  1159. HIC hic;
  1160. LPICSTATUSTHUNKDESC lpstd;
  1161. LRESULT lr;
  1162. hic = (HIC)dw1;
  1163. lpstdS = dw2;
  1164. cbStruct = dw3;
  1165. lpstd = ptrFixMap16To32((LPVOID)lpstdS, sizeof(*lpstd));
  1166. lr = thkSetStatusProc(hic, lpstd);
  1167. ptrUnFix16((LPVOID)lpstdS);
  1168. return (DWORD)lr;
  1169. }
  1170. default:
  1171. return(0);
  1172. }
  1173. }
  1174. #endif // NT_THUNK32
  1175. #ifdef NT_THUNK16
  1176. //==========================================================================;
  1177. //
  1178. //
  1179. // --- === 16 BIT SIDE === ---
  1180. //
  1181. //
  1182. //==========================================================================;
  1183. //
  1184. // --== Global garbage ==--
  1185. //
  1186. DWORD (FAR PASCAL *lpfnCallproc32W)(DWORD, DWORD, DWORD,
  1187. DWORD, DWORD,
  1188. LPVOID, DWORD, DWORD);
  1189. DWORD (FAR PASCAL *lpfnFreeLibrary32W)(DWORD);
  1190. TCHAR gszKernel[] = TEXT("KERNEL");
  1191. TCHAR gszLoadLibraryEx32W[] = TEXT("LoadLibraryEx32W");
  1192. TCHAR gszFreeLibrary32W[] = TEXT("FreeLibrary32W");
  1193. TCHAR gszGetProcAddress32W[] = TEXT("GetProcAddress32W");
  1194. TCHAR gszCallproc32W[] = TEXT("CallProc32W");
  1195. TCHAR gszThunkEntry[] = TEXT("ICMThunk32");
  1196. TCHAR gszMsvfw32[] = TEXT("msvfw32.dll");
  1197. //
  1198. // --== ==--
  1199. //
  1200. //--------------------------------------------------------------------------;
  1201. //
  1202. // PICMGARB thunkInitialize
  1203. //
  1204. // Description:
  1205. // Thunk initialization under NT WOW or Chicago 16-bit.
  1206. //
  1207. // Arguments:
  1208. //
  1209. // Return (PICMGARB):
  1210. // NULL if thunks are not functional. Otherwise, a pointer to the
  1211. // ICMGARB structure for the current process is returned.
  1212. //
  1213. // History:
  1214. // 07/07/94 frankye
  1215. //
  1216. // Notes:
  1217. // The lack of a pig for the current process implies that a thunk
  1218. // is being called in the context of a process in which we were never
  1219. // loaded. If this happens, we allocate a new pig for this process
  1220. // and continue the thunk initialization. Since we were never
  1221. // loaded in the process, we *probably* will never be freed. We
  1222. // cannot reliably determine when we can thunkTerminate in the process.
  1223. //
  1224. //--------------------------------------------------------------------------;
  1225. PICMGARB WINAPI thunkInitialize(VOID)
  1226. {
  1227. HMODULE hmodKernel;
  1228. DWORD (FAR PASCAL *lpfnLoadLibraryEx32W)(LPCSTR, DWORD, DWORD);
  1229. LPVOID (FAR PASCAL *lpfnGetProcAddress32W)(DWORD, LPCSTR);
  1230. PICMGARB pig;
  1231. if (NULL == (pig = pigFind()))
  1232. {
  1233. DPF(0, "thunkInitialize: WARNING: ICM called from process %08lXh in which it was never loaded.", GetCurrentProcessId());
  1234. DebugErr(DBF_WARNING, "thunkInitialize: WARNING: ICM called from process in which it was never loaded.");
  1235. return NULL;
  1236. }
  1237. //
  1238. // If we've already tried and failed...
  1239. //
  1240. if (pig->fThunkError)
  1241. {
  1242. return NULL;
  1243. }
  1244. //
  1245. // If we already successfully initialized thunks...
  1246. //
  1247. if (pig->fThunksInitialized)
  1248. {
  1249. return pig;
  1250. }
  1251. //
  1252. // Try to initialize our connection the the 32-bit side...
  1253. //
  1254. DPFS(dbgInit, 1, "thunkInitialize()");
  1255. //
  1256. // For now, we'll assume we hit an error...
  1257. //
  1258. pig->fThunkError = TRUE;
  1259. //
  1260. // See if we can find the thunking routine entry points in KERNEL
  1261. //
  1262. hmodKernel = GetModuleHandle(gszKernel);
  1263. if (hmodKernel == NULL)
  1264. {
  1265. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetModuleHandle(kernel)");
  1266. return NULL;
  1267. }
  1268. *(FARPROC *)&lpfnLoadLibraryEx32W =
  1269. GetProcAddress(hmodKernel, gszLoadLibraryEx32W);
  1270. if (lpfnLoadLibraryEx32W == NULL)
  1271. {
  1272. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, LoadLibraryEx32W)");
  1273. return NULL;
  1274. }
  1275. *(FARPROC *)&lpfnFreeLibrary32W =
  1276. GetProcAddress(hmodKernel, gszFreeLibrary32W);
  1277. if (lpfnFreeLibrary32W == NULL)
  1278. {
  1279. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, FreeLibrary32W)");
  1280. return NULL;
  1281. }
  1282. *(FARPROC *)&lpfnGetProcAddress32W = GetProcAddress(hmodKernel, gszGetProcAddress32W);
  1283. if (lpfnGetProcAddress32W == NULL)
  1284. {
  1285. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, GetProcAddress32W)");
  1286. return NULL;
  1287. }
  1288. *(FARPROC *)&lpfnCallproc32W = GetProcAddress(hmodKernel, gszCallproc32W);
  1289. if (lpfnCallproc32W == NULL)
  1290. {
  1291. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress(kernel, CallProc32W)");
  1292. return NULL;
  1293. }
  1294. //
  1295. // See if we can get a pointer to our thunking entry points
  1296. //
  1297. pig->dwMsvfw32Handle = (*lpfnLoadLibraryEx32W)(gszMsvfw32, 0L, 0L);
  1298. if (pig->dwMsvfw32Handle == 0)
  1299. {
  1300. DPFS(dbgInit, 0, "thunkInitialize: Couldn't LoadLibraryEx32W(msvfw32.dll)");
  1301. return NULL;
  1302. }
  1303. pig->lpvThunkEntry = (*lpfnGetProcAddress32W)(pig->dwMsvfw32Handle, gszThunkEntry);
  1304. if (pig->lpvThunkEntry == NULL)
  1305. {
  1306. DPFS(dbgInit, 0, "thunkInitialize: Couldn't GetProcAddress32W(msvfw32, ICMThunk32)");
  1307. (*lpfnFreeLibrary32W)(pig->dwMsvfw32Handle);
  1308. return NULL;
  1309. }
  1310. pig->fThunkError = FALSE;
  1311. pig->fThunksInitialized = TRUE;
  1312. DPFS(dbgInit, 4, "thunkInitialize: Done!");
  1313. return pig;
  1314. }
  1315. //--------------------------------------------------------------------------;
  1316. //
  1317. // VOID thunkTerminate
  1318. //
  1319. // Description:
  1320. // Thunk termination under NT WOW or Chicago. Called for each process
  1321. // by 16-bit side to terminate thunks.
  1322. //
  1323. // Arguments:
  1324. // PICMGARB pig:
  1325. //
  1326. // Return (VOID):
  1327. //
  1328. // History:
  1329. // 07/07/94 frankye
  1330. //
  1331. // Notes:
  1332. //
  1333. //--------------------------------------------------------------------------;
  1334. VOID WINAPI thunkTerminate(PICMGARB pig)
  1335. {
  1336. ASSERT( NULL != pig );
  1337. if (pig->fThunksInitialized)
  1338. {
  1339. lpfnFreeLibrary32W(pig->dwMsvfw32Handle);
  1340. pig->fThunksInitialized = FALSE;
  1341. }
  1342. return;
  1343. }
  1344. //--------------------------------------------------------------------------;
  1345. //
  1346. //
  1347. //
  1348. //
  1349. //--------------------------------------------------------------------------;
  1350. /*
  1351. * Generate our thunks - refer to msvideo!compman.c for definitions of
  1352. * functions.
  1353. *
  1354. * NOTE - we often rely here on the fact that most of the message
  1355. * parameter structures are identical for 16 and 32-bit - ie they
  1356. * contain DWORDs and 32-bit pointers.
  1357. */
  1358. //--------------------------------------------------------------------------;
  1359. //
  1360. // LONG thkStatusProc
  1361. //
  1362. // This is reached by thunking down from the 32-bit thkStatusProc32.
  1363. // It will call the client's StatusProc.
  1364. //
  1365. // Arguments:
  1366. // DWORD dwParam : contains segmented ptr to an ICSTATUSTHUNKDESC.
  1367. // The ICSTATUSTHUNKDESC is created during the call to ICSetStatusProc.
  1368. //
  1369. // Return value:
  1370. // LONG :
  1371. //
  1372. //--------------------------------------------------------------------------;
  1373. LONG FAR PASCAL _loadds thkStatusProc(DWORD dwParam)
  1374. {
  1375. LPICSTATUSTHUNKDESC lpstd;
  1376. DPFS(dbgThunks, 4, "thkStatusProc()");
  1377. lpstd = (LPICSTATUSTHUNKDESC)dwParam;
  1378. ASSERT( NULL != lpstd );
  1379. ASSERT( NULL != lpstd->fnStatusProcS );
  1380. return (lpstd->fnStatusProcS)(lpstd->lParam, (UINT)lpstd->uMsg, lpstd->l);
  1381. }
  1382. //--------------------------------------------------------------------------;
  1383. //
  1384. // LRESULT ICSendSetStatusProc32
  1385. //
  1386. // Called from 16-bit ICSendMessage to thunk the ICM_SET_STATUS_PROC
  1387. // message to 32-bits
  1388. //
  1389. // Arguments:
  1390. // HIC hic :
  1391. //
  1392. // LPICSETSTATUSPROC lpissp :
  1393. //
  1394. // DWORD : cbStruct
  1395. //
  1396. // Return value:
  1397. // LRESULT :
  1398. //
  1399. // Notes:
  1400. // !!! For Daytona, we fail this. If we ever decide to support this
  1401. // on Daytona, then I think we have much more work to do since linear
  1402. // addresses in use by the 32-bit codec may change when the status
  1403. // callback thunks down to 16-bits. On Chicago, all the linear addresses
  1404. // our fixed when we convert from the segmented address to the linear
  1405. // address. WHY DOESN'T NT GIVE US AN EASY WAY TO FIX LINEAR ADDRESSES?
  1406. //
  1407. //--------------------------------------------------------------------------;
  1408. LRESULT WINAPI ICSendSetStatusProc32(HIC hic, ICSETSTATUSPROC FAR* lpissp, DWORD cbStruct)
  1409. {
  1410. #ifdef DAYTONA
  1411. return ICERR_UNSUPPORTED;
  1412. #else
  1413. PICMGARB pig;
  1414. PIC pic;
  1415. LPICSTATUSTHUNKDESC lpstd;
  1416. LRESULT lr;
  1417. DPFS(dbgThunks, 4, "ICSendSetStatusProc32()");
  1418. if (NULL == (pig = thunkInitialize())) {
  1419. return ICERR_ERROR;
  1420. }
  1421. pic = (PIC)hic;
  1422. //
  1423. // This should never fail since the structure was allocated by
  1424. // our own code in the ICSetStatusProc macro.
  1425. //
  1426. if (cbStruct < sizeof(*lpissp)) {
  1427. ASSERT( FALSE );
  1428. return ICERR_BADPARAM;
  1429. }
  1430. //
  1431. //
  1432. //
  1433. if (NULL != pic->lpstd) {
  1434. DPFS(dbgThunks, 1, "ICSendSetStatusProc32: replacing existing status proc!");
  1435. GlobalUnfix(GlobalPtrHandle(pic->lpstd));
  1436. GlobalFreePtr(pic->lpstd);
  1437. pic->lpstd = NULL;
  1438. }
  1439. //
  1440. // Allocate a ICSTATUSTHUNKDESC status thunk descriptor. We fix it
  1441. // in linear memory here so that it's linear address remains constant
  1442. // throughout it use. It's linear address will be given to the 32-bit
  1443. // codec which will cache it for use in callbacks.
  1444. //
  1445. lpstd = (LPICSTATUSTHUNKDESC)GlobalAllocPtr(GHND, sizeof(*lpstd));
  1446. if (NULL == lpstd) {
  1447. return (ICERR_MEMORY);
  1448. }
  1449. GlobalFix(GlobalPtrHandle(lpstd));
  1450. pic->lpstd = lpstd;
  1451. lpstd->lpstdS = lpstd;
  1452. lpstd->dwFlags = lpissp->dwFlags;
  1453. lpstd->lParam = lpissp->lParam;
  1454. lpstd->fnStatusProcS = lpissp->Status;
  1455. lpstd->pfnthkStatusProc16S = thkStatusProc;
  1456. lr = (LRESULT)(*lpfnCallproc32W)(compThunkICSetStatusProc32,
  1457. (DWORD)pic->h32,
  1458. (DWORD)lpstd,
  1459. (DWORD)0,
  1460. (DWORD)0,
  1461. pig->lpvThunkEntry,
  1462. 0L, // Don't map pointers
  1463. 5L);
  1464. if (0 != lr) {
  1465. DPFS(dbgThunks, 1, "ICSendSetStatusProc32: fail");
  1466. GlobalUnfix(GlobalPtrHandle(pic->lpstd));
  1467. GlobalFreePtr(pic->lpstd);
  1468. pic->lpstd = NULL;
  1469. }
  1470. return lr;
  1471. #endif
  1472. }
  1473. BOOL FAR PASCAL ICInfoInternal32(DWORD fccType, DWORD fccHandler, ICINFO FAR * lpicInfo, ICINFOI FAR * lpicInfoI)
  1474. {
  1475. PICMGARB pig;
  1476. DPFS(dbgThunks, 4, "ICInfoInternal32");
  1477. if (NULL == (pig = thunkInitialize()))
  1478. {
  1479. return FALSE;
  1480. }
  1481. return (BOOL)(*lpfnCallproc32W)(compThunkICInfoInternal32,
  1482. (DWORD)fccType,
  1483. (DWORD)fccHandler,
  1484. (DWORD)lpicInfo,
  1485. (DWORD)lpicInfoI,
  1486. pig->lpvThunkEntry,
  1487. 0L, // Don't map pointers
  1488. 5L);
  1489. }
  1490. LRESULT FAR PASCAL ICSendMessage32(DWORD hic, UINT msg, DWORD dwP1, DWORD dwP2)
  1491. {
  1492. PICMGARB pig;
  1493. DPFS(dbgThunks, 4, "ICSendMessage32(hic=%08lXh, msg=%04Xh, dwP1=%08lXh, dwP2=%08lXh)", hic, msg, dwP1, dwP2);
  1494. if (NULL == (pig = thunkInitialize()))
  1495. {
  1496. switch (msg) {
  1497. case ICM_GETSTATE:
  1498. case ICM_SETSTATE:
  1499. case ICM_GETINFO:
  1500. case ICM_COMPRESS_GET_SIZE:
  1501. return 0;
  1502. }
  1503. return (LRESULT)ICERR_ERROR;
  1504. }
  1505. return (LRESULT)(*lpfnCallproc32W)(compThunkICSendMessage32,
  1506. (DWORD)hic,
  1507. (DWORD)msg,
  1508. (DWORD)dwP1,
  1509. (DWORD)dwP2,
  1510. pig->lpvThunkEntry,
  1511. 0L, // Don't map pointers
  1512. 5L);
  1513. }
  1514. LRESULT FAR PASCAL ICOpen32(DWORD fccType, DWORD fccHandler, UINT wMode)
  1515. {
  1516. PICMGARB pig;
  1517. DPFS(dbgThunks, 4, "ICOpen32");
  1518. if (NULL == (pig = thunkInitialize()))
  1519. {
  1520. return NULL;
  1521. }
  1522. return (DWORD)(lpfnCallproc32W)(compThunkICOpen32,
  1523. (DWORD)fccType,
  1524. (DWORD)fccHandler,
  1525. (DWORD)wMode,
  1526. (DWORD)0L,
  1527. pig->lpvThunkEntry,
  1528. 0L, // Don't map pointers
  1529. 5L);
  1530. }
  1531. LRESULT FAR PASCAL ICOpenFunction32(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler)
  1532. {
  1533. PICMGARB pig;
  1534. DPFS(dbgThunks, 4, "ICOpenFunction32");
  1535. if (NULL == (pig = thunkInitialize()))
  1536. {
  1537. return NULL;
  1538. }
  1539. return (LRESULT)(lpfnCallproc32W)(compThunkICOpenFunction32,
  1540. (DWORD)fccType,
  1541. (DWORD)fccHandler,
  1542. (DWORD)wMode,
  1543. (DWORD)lpfnHandler,
  1544. pig->lpvThunkEntry,
  1545. 0L, // Don't map pointers
  1546. 5L);
  1547. }
  1548. LRESULT FAR PASCAL ICClose32(DWORD hic)
  1549. {
  1550. PICMGARB pig;
  1551. DPFS(dbgThunks, 4, "ICClose32");
  1552. if (NULL == (pig = thunkInitialize()))
  1553. {
  1554. return (LRESULT)ICERR_ERROR;
  1555. }
  1556. return (DWORD)(lpfnCallproc32W)(compThunkICClose32,
  1557. (DWORD)hic,
  1558. (DWORD)0L,
  1559. (DWORD)0L,
  1560. (DWORD)0L,
  1561. pig->lpvThunkEntry,
  1562. 0L, // Don't map pointers
  1563. 5L);
  1564. }
  1565. #endif // NT_THUNK16