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.

940 lines
25 KiB

  1. //==========================================================================;
  2. // thunk32.c
  3. //
  4. // Copyright (c) 1991-1994 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Description:
  7. // This module contains routines for thunking the video APIs
  8. // from 16-bit Windows to 32-bit WOW.
  9. //
  10. // History:
  11. //
  12. //==========================================================================;
  13. // This stuff is not going to work 64-bit
  14. #pragma warning(disable:4312)
  15. /*
  16. WOW Thunking design:
  17. Thunks are generated as follows :
  18. 16-bit :
  19. */
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <mmsystem.h>
  23. #include <mmddk.h>
  24. #include <mmreg.h>
  25. #include <memory.h>
  26. #include <win32.h>
  27. #ifdef _WIN32
  28. #include <ivideo32.h>
  29. #ifndef _INC_MSVIDEO
  30. #define _INC_MSVIDEO 50 /* version number */
  31. #endif
  32. #else
  33. #include <vfw.h>
  34. #endif
  35. #include <msviddrv.h>
  36. #include <msvideoi.h>
  37. #ifdef _WIN32
  38. #include <wownt32.h>
  39. #include <stdlib.h> // for mbstowcs and wcstombs
  40. #include <video16.h>
  41. #ifdef UNICODE
  42. #include "profile.h" // NT only (for now?)
  43. #endif
  44. #endif // WIN32
  45. // in capinit.c
  46. BOOL capInternalGetDriverDescA(UINT wDriverIndex,
  47. LPSTR lpszName, int cbName,
  48. LPSTR lpszVer, int cbVer);
  49. //
  50. // pick up the function definitions
  51. //
  52. #include "vidthunk.h"
  53. #ifdef DEBUG
  54. #define MODNAME "AVICAP32"
  55. int videoDebugLevel = -1;
  56. void videoDebugInit(VOID)
  57. {
  58. if (videoDebugLevel == -1)
  59. videoDebugLevel = GetProfileIntA("Debug", MODNAME, 0);
  60. }
  61. #else
  62. #define videoDebugInit()
  63. #endif
  64. /* -------------------------------------------------------------------------
  65. ** Handle and memory mapping functions.
  66. ** -------------------------------------------------------------------------
  67. */
  68. LPWOWHANDLE32 lpWOWHandle32;
  69. LPWOWHANDLE16 lpWOWHandle16;
  70. LPWOWCALLBACK16 lpWOWCallback16;
  71. LPGETVDMPOINTER GetVdmPointer;
  72. int ThunksInitialized;
  73. #ifdef WIN32
  74. #ifdef DEBUG
  75. void FAR cdecl thkdprintf(LPSTR szFormat, ...)
  76. {
  77. char ach[128];
  78. va_list va;
  79. #define MARKER "AVICAP (thunk): "
  80. lstrcpyA(ach, MARKER);
  81. va_start(va, szFormat);
  82. wvsprintfA(ach+sizeof(MARKER), szFormat, va);
  83. va_end(va);
  84. OutputDebugStringA(ach);
  85. }
  86. #endif
  87. #endif
  88. //
  89. // Useful functions
  90. //
  91. //
  92. // CopyAlloc - allocate a new piece of memory, and copy the data in
  93. // Must use LocalFree to release the memory later
  94. //
  95. PVOID CopyAlloc(PVOID pvSrc, UINT uSize)
  96. {
  97. PVOID pvDest;
  98. pvDest = (PVOID)LocalAlloc(LMEM_FIXED, uSize);
  99. if (pvDest != NULL) {
  100. CopyMemory(pvDest, pvSrc, uSize);
  101. }
  102. return pvDest;
  103. }
  104. /*
  105. * Copy data from source to dest where source is a 32bit pointer
  106. * and dest is a 16bit pointer
  107. */
  108. void CopyTo16Bit(LPVOID Dest16, LPVOID Src32, DWORD Length)
  109. {
  110. PVOID Dest32;
  111. if (Src32 == NULL) {
  112. return;
  113. }
  114. Dest32 = GetVdmPointer((DWORD)(DWORD_PTR)Dest16, Length, TRUE);
  115. CopyMemory(Dest32, Src32, Length);
  116. }
  117. /*
  118. * Copy data from source to dest where source is a 16bit pointer
  119. * and dest is a 32bit pointer
  120. */
  121. void CopyTo32Bit(LPVOID Dest32, LPVOID Src16, DWORD Length)
  122. {
  123. PVOID Src32;
  124. if (Src16 == NULL) {
  125. return;
  126. }
  127. Src32 = GetVdmPointer((DWORD)(DWORD_PTR)Src16, Length, TRUE);
  128. CopyMemory(Dest32, Src32, Length);
  129. }
  130. /*
  131. * Copy data from source to dest where source is a 16bit pointer
  132. * and dest is a 32bit pointer ONLY if the source is not aligned
  133. *
  134. * Returns which pointer to use (src or dest)
  135. */
  136. LPVOID CopyIfNotAligned(LPVOID Dest32, LPVOID Src16, DWORD Length)
  137. {
  138. PVOID Src32;
  139. if (Src16 == NULL) {
  140. return Dest32;
  141. }
  142. Src32 = GetVdmPointer((DWORD)(DWORD_PTR)Src16, Length, TRUE);
  143. CopyMemory(Dest32, Src32, Length);
  144. return Dest32;
  145. }
  146. typedef struct _callback {
  147. WORD flags;
  148. WORD hVideo16;
  149. WORD msg;
  150. DWORD dwCallback16inst;
  151. DWORD dw1;
  152. DWORD dw2;
  153. } CALLBACK16;
  154. typedef CALLBACK16 * PCALLBACK16;
  155. /*
  156. * Callbacks
  157. */
  158. void MyVideoCallback(HANDLE handle,
  159. UINT msg,
  160. DWORD dwUser,
  161. DWORD dw1,
  162. DWORD dw2)
  163. {
  164. PVIDEOINSTANCEDATA32 pInst;
  165. BOOL fFree = FALSE;
  166. pInst = (PVIDEOINSTANCEDATA32)dwUser;
  167. DPF3(("Video callback - handle = %8X, msg = %8X, dwUser = %8X, dw1 = %8X, dw2 = %8X\n",
  168. handle, msg, dwUser, dw1, dw2));
  169. switch (msg) {
  170. /*
  171. * What are the parameters for these messages ??
  172. */
  173. case MM_DRVM_OPEN:
  174. /*
  175. * We get this when we INIT_STREAM
  176. */
  177. break;
  178. case MM_DRVM_CLOSE:
  179. /*
  180. * Device is closing - this is where we free our structures
  181. * (just in case the 32-bit side called close to clean up).
  182. * dwUser points to our data
  183. */
  184. fFree = TRUE;
  185. break;
  186. case MM_DRVM_DATA:
  187. /*
  188. * We have data - this means a buffer has been returned in
  189. * dw1
  190. */
  191. {
  192. PVIDEOHDR32 pHdr32;
  193. pHdr32 = CONTAINING_RECORD((PVIDEOHDR)dw1,
  194. VIDEOHDR32,
  195. videoHdr);
  196. dw1 = (DWORD)(DWORD_PTR)pHdr32->pHdr16; // For callback below
  197. /*
  198. * Map back the data and free our structure
  199. */
  200. {
  201. VIDEOHDR Hdr16;
  202. Hdr16 = pHdr32->videoHdr;
  203. Hdr16.lpData = pHdr32->lpData16;
  204. memcpy(pHdr32->pHdr32, (LPVOID)&Hdr16, sizeof(VIDEOHDR));
  205. }
  206. /*
  207. * Clean up our local structure
  208. */
  209. LocalFree((HLOCAL)pHdr32);
  210. }
  211. break;
  212. case MM_DRVM_ERROR:
  213. /*
  214. * dw1 = frames skipped - unfortunately there's nobody to tell!
  215. */
  216. break;
  217. }
  218. /*
  219. * Call back the application if appropriate
  220. */
  221. switch (pInst->dwFlags & CALLBACK_TYPEMASK) {
  222. case CALLBACK_WINDOW:
  223. PostMessage(ThunkHWND(LOWORD(pInst->dwCallback)),
  224. msg, (WPARAM)handle, (LPARAM)dw1);
  225. break;
  226. case CALLBACK_FUNCTION:
  227. #if 0
  228. // Must call a generic 16 bit callback passing a pointer to
  229. // a parameter array.
  230. {
  231. WORD hMem;
  232. PCALLBACK16 pCallStruct;
  233. pCallStruct = WOWGlobalAllocLock16(0, sizeof(CALLBACK16), &hMem);
  234. if (pCallStruct) {
  235. pCallStruct->flags = HIWORD(pInst->dwFlags);
  236. pCallStruct->hVideo16 = (WORD)pInst->hVideo;
  237. pCallStruct->msg = (WORD)msg;
  238. pCallStruct->dwCallback16inst = pInst->dwCallbackInst;
  239. pCallStruct->dw1 = (DWORD)dw1;
  240. pCallStruct->dw2 = (DWORD)dw2;
  241. lpWOWCallback16(pInst->dwCallback, pCallStruct);
  242. // Now free off the callback structure
  243. WOWGlobalUnlockFree16(pCallStruct);
  244. }
  245. }
  246. #endif
  247. break;
  248. }
  249. if (fFree) {
  250. LocalFree((HLOCAL)pInst);
  251. }
  252. }
  253. //
  254. // Thunking callbacks to WOW32 (or wherever)
  255. //
  256. typedef struct tag_video_stream_init_parms16 {
  257. DWORD dwMicroSecPerFrame;
  258. DWORD dwCallback;
  259. DWORD dwCallbackInst;
  260. DWORD dwFlags;
  261. DWORD_PTR hVideo;
  262. } VIDEO_STREAM_INIT_PARMS16, FAR * LPVIDEO_STREAM_INIT_PARMS16;
  263. //--------------------------------------------------------------------------;
  264. //
  265. // DWORD videoThunk32
  266. //
  267. // Description:
  268. //
  269. // 32-bit function dispatcher for thunks.
  270. //
  271. // Arguments:
  272. // DWORD dwThunkId:
  273. //
  274. // DWORD dw1:
  275. //
  276. // DWORD dw2:
  277. //
  278. // DWORD dw3:
  279. //
  280. // DWORD dw4:
  281. //
  282. // Return (DWORD):
  283. //
  284. // History:
  285. //
  286. //--------------------------------------------------------------------------;
  287. DWORD videoThunk32(DWORD dwThunkId,DWORD dw1,DWORD dw2,DWORD dw3,DWORD dw4)
  288. {
  289. //
  290. // Make sure we've got thunking functionality
  291. //
  292. if (ThunksInitialized <= 0) {
  293. HMODULE hMod;
  294. if (ThunksInitialized == -1) {
  295. return MMSYSERR_ERROR;
  296. }
  297. videoDebugInit();
  298. hMod = GetModuleHandle(GET_MAPPING_MODULE_NAME);
  299. if (hMod != NULL) {
  300. GetVdmPointer =
  301. (LPGETVDMPOINTER)GetProcAddress(hMod, GET_VDM_POINTER_NAME);
  302. lpWOWHandle32 =
  303. (LPWOWHANDLE32)GetProcAddress(hMod, GET_HANDLE_MAPPER32 );
  304. lpWOWHandle16 =
  305. (LPWOWHANDLE16)GetProcAddress(hMod, GET_HANDLE_MAPPER16 );
  306. lpWOWCallback16 =
  307. (LPWOWCALLBACK16)GetProcAddress(hMod, GET_CALLBACK16 );
  308. }
  309. if ( GetVdmPointer == NULL
  310. || lpWOWHandle16 == NULL
  311. || lpWOWHandle32 == NULL ) {
  312. ThunksInitialized = -1;
  313. return MMSYSERR_ERROR;
  314. } else {
  315. ThunksInitialized = 1;
  316. }
  317. }
  318. //
  319. // Perform the requested function
  320. //
  321. switch (dwThunkId) {
  322. case vidThunkvideoMessage32:
  323. return (DWORD) videoMessage32((HVIDEO)dw1, (UINT)dw2, dw3, dw4);
  324. break;
  325. case vidThunkvideoGetNumDevs32:
  326. return (DWORD) videoGetNumDevs32();
  327. break;
  328. case vidThunkvideoOpen32:
  329. return (DWORD) videoOpen32((LPHVIDEO)dw1, dw2, dw3);
  330. break;
  331. case vidThunkvideoClose32:
  332. return (DWORD) videoClose32((HVIDEO)dw1);
  333. break;
  334. case vidThunkvideoGetDriverDesc32:
  335. {
  336. LPSTR lpszName = NULL, lpszVer = NULL;
  337. short cbName, cbVer;
  338. DWORD dwRet;
  339. cbName = (short) LOWORD(dw4);
  340. cbVer = (short) HIWORD(dw4);
  341. // for chicago, need to call WOW32GetVdmPointerFix
  342. // (via getprocaddr!)
  343. if ((dw2 != 0) && (cbName > 0)) {
  344. lpszName = WOW32ResolveMemory(dw2);
  345. }
  346. if ((dw3 != 0) && (cbVer > 0)) {
  347. lpszVer = WOW32ResolveMemory(dw3);
  348. }
  349. dwRet = capInternalGetDriverDescA(
  350. dw1, // device id
  351. lpszName,
  352. cbName,
  353. lpszVer,
  354. cbVer);
  355. #if 0 //should do this for chicago
  356. if (lpszName) {
  357. WOWGetVDMPointerUnfix(dw2);
  358. }
  359. if (lpszVer) {
  360. WOWGetVDMPointerUnfix(dw3);
  361. }
  362. #endif
  363. return dwRet;
  364. }
  365. default:
  366. return(0);
  367. }
  368. }
  369. LRESULT FAR PASCAL videoMessage32(HVIDEO hVideo, UINT msg, DWORD dwP1, DWORD dwP2)
  370. {
  371. StartThunk(videoMessage);
  372. DPF2(("\tvideoMessage id = %4X, lParam1 = %8X, lParam2 = %8X",
  373. msg, dwP1, dwP2));
  374. /*
  375. * We ONLY support (and we only ever will support) messages which
  376. * have ALREADY been defined. New 32-bit driver messages will NOT
  377. * be supported from 16-bit apps.
  378. */
  379. switch (msg) {
  380. case DVM_GETVIDEOAPIVER:
  381. {
  382. DWORD ApiVer;
  383. ReturnCode = videoMessage((HVIDEO)hVideo,
  384. (UINT)msg,
  385. (DWORD_PTR)&ApiVer,
  386. dwP2);
  387. if (ReturnCode == DV_ERR_OK) {
  388. CopyTo16Bit((LPVOID)dwP1, &ApiVer, sizeof(DWORD));
  389. }
  390. }
  391. break;
  392. case DVM_GETERRORTEXT:
  393. {
  394. VIDEO_GETERRORTEXT_PARMS vet;
  395. VIDEO_GETERRORTEXT_PARMS MappedVet;
  396. /*
  397. * Get the parameter block
  398. */
  399. CopyTo32Bit((LPVOID)&vet, (LPVOID)dwP1, sizeof(vet));
  400. MappedVet = vet;
  401. /*
  402. * Map the string pointer
  403. */
  404. MappedVet.lpText = WOW32ResolveMemory(vet.lpText);
  405. ReturnCode = videoMessage(hVideo,
  406. msg,
  407. (DWORD_PTR)&MappedVet,
  408. 0);
  409. }
  410. break;
  411. case DVM_GET_CHANNEL_CAPS:
  412. {
  413. CHANNEL_CAPS Caps;
  414. ReturnCode = videoMessage((HVIDEO)hVideo,
  415. (UINT)msg,
  416. (DWORD_PTR)&Caps,
  417. dwP2);
  418. /*
  419. * If successful return the data to the 16-bit app
  420. */
  421. if (ReturnCode == DV_ERR_OK) {
  422. CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Caps,
  423. sizeof(Caps));
  424. }
  425. }
  426. break;
  427. case DVM_UPDATE:
  428. {
  429. ReturnCode = videoMessage(hVideo,
  430. msg,
  431. (DWORD_PTR)ThunkHWND(dwP1),
  432. (DWORD_PTR)ThunkHDC(dwP2));
  433. }
  434. break;
  435. case DVM_PALETTE:
  436. case DVM_PALETTERGB555:
  437. case DVM_FORMAT:
  438. /*
  439. * This stuff all comes from videoConfigure
  440. *
  441. * Let's hope this data is all DWORDs!
  442. */
  443. {
  444. VIDEOCONFIGPARMS vcp, MappedVcp;
  445. DWORD dwReturn;
  446. BOOL Ok;
  447. Ok = TRUE;
  448. CopyTo32Bit((LPVOID)&vcp, (LPVOID)dwP2, sizeof(vcp));
  449. MappedVcp.lpdwReturn = &dwReturn;
  450. MappedVcp.dwSize1 = vcp.dwSize1;
  451. MappedVcp.dwSize2 = vcp.dwSize2;
  452. /*
  453. * Get some storage to store the answer
  454. */
  455. if (MappedVcp.dwSize1 != 0) {
  456. MappedVcp.lpData1 = (LPSTR)LocalAlloc(LPTR, MappedVcp.dwSize1);
  457. if (MappedVcp.lpData1 == NULL) {
  458. Ok = FALSE;
  459. } else {
  460. if (MappedVcp.dwSize2 != 0) {
  461. MappedVcp.lpData2 = (LPSTR)LocalAlloc(LPTR, MappedVcp.dwSize2);
  462. if (MappedVcp.lpData2 == NULL) {
  463. Ok = FALSE;
  464. if (MappedVcp.dwSize1 != 0) {
  465. LocalFree((HLOCAL)MappedVcp.lpData1);
  466. }
  467. }
  468. }
  469. }
  470. }
  471. if (Ok) {
  472. CopyTo32Bit(MappedVcp.lpData1, vcp.lpData1, MappedVcp.dwSize1);
  473. CopyTo32Bit(MappedVcp.lpData2, vcp.lpData2, MappedVcp.dwSize2);
  474. ReturnCode = videoMessage(hVideo,
  475. msg,
  476. dwP1,
  477. (DWORD_PTR)&MappedVcp);
  478. if (ReturnCode == DV_ERR_OK) {
  479. if (vcp.lpdwReturn != NULL) {
  480. CopyTo16Bit(vcp.lpdwReturn, MappedVcp.lpdwReturn,
  481. sizeof(DWORD));
  482. }
  483. CopyTo16Bit(vcp.lpData1, MappedVcp.lpData1, MappedVcp.dwSize1);
  484. CopyTo16Bit(vcp.lpData2, MappedVcp.lpData2, MappedVcp.dwSize2);
  485. }
  486. if (MappedVcp.dwSize1 != 0) {
  487. LocalFree((HLOCAL)MappedVcp.lpData1);
  488. }
  489. if (MappedVcp.dwSize2 != 0) {
  490. LocalFree((HLOCAL)MappedVcp.lpData2);
  491. }
  492. } else {
  493. ReturnCode = DV_ERR_NOMEM;
  494. }
  495. }
  496. break;
  497. case DVM_CONFIGURESTORAGE:
  498. {
  499. LPSTR lpStrIdent;
  500. lpStrIdent = WOW32ResolveMemory(dwP1);
  501. ReturnCode = videoMessage(hVideo,
  502. msg,
  503. (DWORD_PTR)lpStrIdent,
  504. dwP2);
  505. }
  506. break;
  507. case DVM_DIALOG:
  508. {
  509. ReturnCode = videoMessage(hVideo,
  510. msg,
  511. (DWORD_PTR)ThunkHWND(dwP1),
  512. dwP2);
  513. }
  514. break;
  515. case DVM_SRC_RECT:
  516. case DVM_DST_RECT:
  517. /*
  518. * If it's a query only then don't bother with the
  519. * rectangle
  520. */
  521. if (dwP2 & VIDEO_CONFIGURE_QUERY) {
  522. ReturnCode = videoMessage(hVideo,
  523. msg,
  524. dwP1,
  525. dwP2);
  526. } else {
  527. /*
  528. * The rectangle is regarded as 'in' and 'out'
  529. * We need to translate between 16-bit and 32-bit rectangle structures
  530. */
  531. RECT_SHORT SRect;
  532. RECT Rect;
  533. CopyTo32Bit((LPVOID)&SRect, (LPVOID)dwP1, sizeof(SRect));
  534. SHORT_RECT_TO_RECT(Rect, SRect);
  535. ReturnCode = videoMessage(hVideo,
  536. msg,
  537. (DWORD_PTR)&Rect,
  538. dwP2);
  539. if (ReturnCode == DV_ERR_OK) {
  540. RECT_TO_SHORT_RECT(SRect, Rect);
  541. CopyTo16Bit((LPVOID)dwP1, (LPVOID)&SRect, sizeof(SRect));
  542. }
  543. }
  544. break;
  545. case DVM_STREAM_PREPAREHEADER:
  546. case DVM_STREAM_UNPREPAREHEADER:
  547. case DVM_FRAME:
  548. case DVM_STREAM_ADDBUFFER:
  549. {
  550. VIDEOHDR Hdr32;
  551. LPBYTE pData16, pData32;
  552. DWORD dwSize;
  553. dwSize = (UINT)msg == DVM_FRAME ? sizeof(VIDEOHDR) :
  554. min(dwP2, sizeof(VIDEOHDR));
  555. CopyTo32Bit((LPVOID)&Hdr32, (LPVOID)dwP1, dwSize);
  556. pData16 = Hdr32.lpData;
  557. /*
  558. * Create a mapping for the pointer
  559. */
  560. pData32 = GetVdmPointer((DWORD)(DWORD_PTR)pData16, Hdr32.dwBufferLength, TRUE);
  561. Hdr32.lpData = pData32;
  562. if (msg == DVM_STREAM_ADDBUFFER) {
  563. PVIDEOHDR32 pHdr32;
  564. /*
  565. * Allocate our callback structure and pass this
  566. * as our header (suitably offset to the video header part).
  567. */
  568. pHdr32 = (PVIDEOHDR32)LocalAlloc(LPTR, sizeof(VIDEOHDR32));
  569. if (pHdr32 == NULL) {
  570. ReturnCode = DV_ERR_NOMEM;
  571. } else {
  572. /*
  573. * Remember the old header so we can pass it back
  574. * and the old data pointer so we can flush it
  575. */
  576. pHdr32->pHdr16 = (LPVOID)dwP1;
  577. /*
  578. * Some systems can't handle GetVdmPointer at interrupt
  579. * time so get a pointer here
  580. */
  581. pHdr32->pHdr32 = WOW32ResolveMemory(dwP1);
  582. pHdr32->lpData16 = pData16;
  583. pHdr32->videoHdr = Hdr32;
  584. ReturnCode = videoMessage(hVideo,
  585. msg,
  586. (DWORD_PTR)&pHdr32->videoHdr,
  587. dwP2);
  588. /*
  589. * If everything was OK copy it back
  590. */
  591. if (ReturnCode == DV_ERR_OK) {
  592. Hdr32.lpData = pData16;
  593. CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Hdr32, dwSize);
  594. }
  595. }
  596. } else {
  597. /*
  598. * Prepare/unprepare the header for 32bit
  599. */
  600. ReturnCode = videoMessage(hVideo,
  601. msg,
  602. (DWORD_PTR)&Hdr32,
  603. dwP2);
  604. /*
  605. * If everything was OK copy it back
  606. */
  607. if (ReturnCode == DV_ERR_OK) {
  608. Hdr32.lpData = pData16;
  609. CopyTo16Bit((LPVOID)dwP1, (LPVOID)&Hdr32, dwSize);
  610. }
  611. }
  612. }
  613. break;
  614. case DVM_STREAM_RESET:
  615. case DVM_STREAM_FINI:
  616. case DVM_STREAM_STOP:
  617. case DVM_STREAM_START:
  618. /*
  619. * Note that the MM_DRVM_CLOSE message will cause us to clean up our
  620. * callback structures on DVM_STREAM_FINI.
  621. */
  622. ReturnCode = videoMessage(hVideo,
  623. msg,
  624. 0,
  625. 0);
  626. break;
  627. case DVM_STREAM_GETPOSITION:
  628. {
  629. MMTIME mmTime;
  630. MMTIME16 mmTime16;
  631. ReturnCode = videoMessage(hVideo,
  632. msg,
  633. (DWORD_PTR)&mmTime,
  634. sizeof(mmTime));
  635. if (ReturnCode == DV_ERR_OK) {
  636. mmTime16.wType = (WORD)mmTime.wType;
  637. CopyMemory((LPVOID)&mmTime16.u,
  638. (LPVOID)&mmTime.u, sizeof(mmTime16.u));
  639. CopyTo16Bit((LPVOID)dwP1, (LPVOID)&mmTime16,
  640. min(sizeof(mmTime16), dwP2));
  641. }
  642. }
  643. break;
  644. case DVM_STREAM_INIT:
  645. {
  646. VIDEO_STREAM_INIT_PARMS vsip;
  647. VIDEO_STREAM_INIT_PARMS16 vsip16;
  648. PVIDEOINSTANCEDATA32 pInst32;
  649. #if 0
  650. // always do callback
  651. VIDEO_STREAM_INIT_PARMS16 * pvsip = WOW32ResolveMemory(dwP1);
  652. if (!(pvsip->dwFlags & CALLBACK_TYPEMASK)) {
  653. // No callback wanted by the 16 bit code. Pass call
  654. // straight through
  655. ReturnCode = videoMessage((HVIDEO)hVideo,
  656. (UINT)msg,
  657. (DWORD_PTR)pvsip,
  658. (DWORD_PTR)dwP2);
  659. } else
  660. #endif
  661. {
  662. // We set up a callback to a 32 bit routine, that in
  663. // turn will callback to the 16 bit function/window
  664. pInst32 = (PVIDEOINSTANCEDATA32)
  665. LocalAlloc(LPTR, sizeof(VIDEOINSTANCEDATA32));
  666. if (pInst32 == NULL) {
  667. ReturnCode = DV_ERR_NOMEM;
  668. } else {
  669. CopyTo32Bit((LPVOID)&vsip16, (LPVOID)dwP1,
  670. min(sizeof(vsip16), dwP2));
  671. pInst32->dwFlags = vsip16.dwFlags;
  672. pInst32->dwCallbackInst = vsip16.dwCallbackInst;
  673. pInst32->dwCallback = vsip16.dwCallback;
  674. pInst32->hVideo = (HVIDEO16)vsip16.hVideo;
  675. /*
  676. * Make up our own parms. Only set up a callback if
  677. * the user wanted one
  678. */
  679. vsip.dwCallback = (DWORD_PTR)MyVideoCallback;
  680. vsip.dwFlags = (vsip.dwFlags & ~CALLBACK_TYPEMASK) |
  681. CALLBACK_FUNCTION;
  682. vsip.dwCallbackInst = (DWORD_PTR)pInst32;
  683. ReturnCode = videoMessage((HVIDEO)hVideo,
  684. (UINT)msg,
  685. (DWORD_PTR)&vsip,
  686. (DWORD_PTR)dwP2);
  687. if (ReturnCode != DV_ERR_OK) {
  688. LocalFree((HLOCAL)pInst32);
  689. } else {
  690. // The instance block will be freed off by the
  691. // 32 bit callback routine when all over
  692. }
  693. }
  694. }
  695. }
  696. break;
  697. case DVM_STREAM_GETERROR:
  698. {
  699. DWORD dwError;
  700. DWORD dwFramesSkipped;
  701. ReturnCode = videoMessage(hVideo,
  702. msg,
  703. (DWORD_PTR)&dwError,
  704. (DWORD_PTR)&dwFramesSkipped);
  705. if (ReturnCode == DV_ERR_OK) {
  706. CopyTo16Bit((LPVOID)dwP1, &dwError, sizeof(DWORD));
  707. CopyTo16Bit((LPVOID)dwP2, &dwFramesSkipped, sizeof(DWORD));
  708. }
  709. }
  710. break;
  711. default:
  712. DPF2(("videoMessage - Message not implemented %X\n", (UINT)msg));
  713. ReturnCode = DV_ERR_NOTSUPPORTED;
  714. }
  715. EndThunk();
  716. }
  717. INLINE LRESULT FAR PASCAL videoGetNumDevs32(void)
  718. {
  719. StartThunk(videoGetNumDevs);
  720. ReturnCode = videoGetNumDevs();
  721. EndThunk();
  722. }
  723. LRESULT FAR PASCAL videoClose32(HVIDEO hVideo)
  724. {
  725. StartThunk(videoClose)
  726. ReturnCode = videoClose(hVideo);
  727. EndThunk();
  728. }
  729. LRESULT FAR PASCAL videoOpen32(LPHVIDEO lphVideo, DWORD dwDeviceID, DWORD dwFlags)
  730. {
  731. HVIDEO hVideo;
  732. StartThunk(videoOpen);
  733. ReturnCode = videoOpen(
  734. &hVideo,
  735. dwDeviceID,
  736. dwFlags);
  737. if (ReturnCode == DV_ERR_OK) {
  738. lphVideo = WOW32ResolveMemory((PVOID)lphVideo);
  739. * (HVIDEO UNALIGNED *)lphVideo = hVideo;
  740. }
  741. EndThunk();
  742. }