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.

4065 lines
116 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: thop32.cxx
  7. //
  8. // Contents: Thop implementations for 32->16
  9. //
  10. // History: 22-Feb-94 DrewB Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. #include <ole2.h>
  16. #include <string.h>
  17. #include <valid.h>
  18. #include "olethk32.hxx"
  19. #include "struct16.hxx"
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Function: EXECUTE_THOP3216, public
  23. //
  24. // Synopsis: Debugging version of thop dispatch routine
  25. //
  26. // Arguments: [pti] - Thunking info
  27. //
  28. // Returns: Appropriate status
  29. //
  30. // History: 24-Feb-94 DrewB Created
  31. //
  32. //----------------------------------------------------------------------------
  33. #if DBG == 1
  34. DWORD EXECUTE_THOP3216(THUNKINFO *pti)
  35. {
  36. thkDebugOut((DEB_THOPS, "%sIn ExThop3216: %s (0x%02X), s16 %p, s32 %p\n",
  37. NestingLevelString(),
  38. ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
  39. pti->s32.pbCurrent));
  40. DebugIncrementNestingLevel();
  41. // Local variable
  42. DWORD dwRet;
  43. // Sanity check
  44. thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
  45. dwRet = (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti);
  46. DebugDecrementNestingLevel();
  47. thkDebugOut((DEB_THOPS, "%sOut ExThop3216\n", NestingLevelString()));
  48. return(dwRet);
  49. }
  50. #endif
  51. #if DBG == 1
  52. DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti)
  53. {
  54. thkDebugOut((DEB_THOPS, "%sIn ExEnumThop3216: %s (0x%02X), s16 %p, s32 %p\n",
  55. NestingLevelString(),
  56. EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
  57. pti->s32.pbCurrent));
  58. DebugIncrementNestingLevel();
  59. // Local variable
  60. DWORD dwRet;
  61. dwRet = (*aThopEnumFunctions3216[*(pti)->pThop])(pti);
  62. DebugDecrementNestingLevel();
  63. thkDebugOut((DEB_THOPS, "%sOut ExEnumThop3216\n", NestingLevelString()));
  64. return(dwRet);
  65. }
  66. #endif
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Function: FixedThopHandler, public
  70. //
  71. // Synopsis: Generic function which handles the high-level details
  72. // of thop execution for thops that operate on known-size
  73. // data
  74. //
  75. // Arguments: [pti] - Thunking state information
  76. // [thop] - Thop being executed
  77. // [cb16] - 16-bit size
  78. // [pfn1632] - 16->32 conversion routine
  79. // [cb32] - 32-bit size
  80. // [pfn3216] - 32->16 conversion routine
  81. //
  82. // Returns: Appropriate status code
  83. //
  84. // History: 05-Apr-94 DrewB Created
  85. //
  86. // Notes: Automatically increments pThop
  87. //
  88. //----------------------------------------------------------------------------
  89. DWORD FixedThopHandler3216(THUNKINFO *pti,
  90. THOP thop,
  91. UINT cb16,
  92. FIXEDHANDLERROUTINE pfn1632,
  93. UINT cb32,
  94. FIXEDHANDLERROUTINE pfn3216)
  95. {
  96. DWORD dwResult;
  97. VPVOID vp16;
  98. BYTE *pb16;
  99. BYTE *pb32;
  100. if ((thop & (THOP_IN | THOP_OUT)) != 0)
  101. {
  102. vp16 = 0;
  103. GET_STACK32(pti, pb32, BYTE *);
  104. if ( pb32 != 0 )
  105. {
  106. if ((thop & THOP_IN) != 0)
  107. {
  108. if (IsBadReadPtr(pb32, cb32))
  109. {
  110. return (DWORD)E_INVALIDARG;
  111. }
  112. }
  113. if ((thop & THOP_OUT) != 0)
  114. {
  115. if (IsBadWritePtr(pb32, cb32))
  116. {
  117. return (DWORD)E_INVALIDARG;
  118. }
  119. }
  120. vp16 = STACKALLOC16(cb16);
  121. if (vp16 == 0)
  122. {
  123. return (DWORD)E_OUTOFMEMORY;
  124. }
  125. else if ((thop & THOP_IN) != 0)
  126. {
  127. pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
  128. (pfn3216)(pb32, pb16, cb32, cb16);
  129. WOWRELVDMPTR(vp16);
  130. }
  131. }
  132. TO_STACK16(pti, vp16, VPVOID);
  133. pti->pThop++;
  134. dwResult = EXECUTE_THOP3216(pti);
  135. if ((thop & THOP_OUT) != 0 && pb32 != NULL)
  136. {
  137. if (SUCCEEDED(dwResult))
  138. {
  139. pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
  140. (pfn1632)(pb16, pb32, cb16, cb32);
  141. WOWRELVDMPTR(vp16);
  142. }
  143. else if ((thop & THOP_IN) == 0)
  144. {
  145. // Zero out-only parameters on failure
  146. memset(pb32, 0, cb32);
  147. }
  148. }
  149. if (vp16 != 0)
  150. {
  151. STACKFREE16(vp16, cb16);
  152. }
  153. }
  154. else
  155. {
  156. (pfn3216)(PTR_STACK32(&pti->s32), PTR_STACK16(&pti->s16, cb16),
  157. cb32, cb16);
  158. SKIP_STACK16(&pti->s16, cb16);
  159. SKIP_STACK32(&pti->s32, cb32);
  160. pti->pThop++;
  161. dwResult = EXECUTE_THOP3216(pti);
  162. }
  163. return dwResult;
  164. }
  165. //-----------------------------------------------------------------------------
  166. //
  167. // Handler-based thunks
  168. //
  169. // These thunks use the fixed-size generic thop handler to do their work
  170. //
  171. //-----------------------------------------------------------------------------
  172. // Handle straight copy
  173. DWORD Thop_Copy_3216(THUNKINFO *pti)
  174. {
  175. THOP thopSize;
  176. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
  177. thopSize = *++pti->pThop;
  178. return FixedThopHandler3216(pti,
  179. *(pti->pThop-1),
  180. thopSize, FhCopyMemory,
  181. thopSize, FhCopyMemory);
  182. }
  183. DWORD Thop_ShortToLong_3216(THUNKINFO *pti)
  184. {
  185. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
  186. return FixedThopHandler3216(pti,
  187. *pti->pThop,
  188. sizeof(SHORT), FhShortToLong,
  189. sizeof(LONG), FhLongToShort);
  190. }
  191. DWORD Thop_WordToDword_3216(THUNKINFO *pti)
  192. {
  193. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
  194. return FixedThopHandler3216(pti,
  195. *pti->pThop,
  196. sizeof(WORD), FhWordToDword,
  197. sizeof(DWORD), FhDwordToWord);
  198. }
  199. DWORD Thop_GdiHandle_3216(THUNKINFO *pti)
  200. {
  201. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
  202. return FixedThopHandler3216(pti,
  203. *pti->pThop,
  204. sizeof(HAND16), FhGdiHandle1632,
  205. sizeof(HANDLE), FhGdiHandle3216);
  206. }
  207. DWORD Thop_UserHandle_3216(THUNKINFO *pti)
  208. {
  209. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
  210. return FixedThopHandler3216(pti,
  211. *pti->pThop,
  212. sizeof(HAND16), FhUserHandle1632,
  213. sizeof(HANDLE), FhUserHandle3216);
  214. }
  215. DWORD Thop_HACCEL_3216(THUNKINFO *pti)
  216. {
  217. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
  218. return FixedThopHandler3216(pti,
  219. *pti->pThop,
  220. sizeof(HAND16), FhHaccel1632,
  221. sizeof(HANDLE), FhHaccel3216);
  222. }
  223. DWORD Thop_HTASK_3216(THUNKINFO *pti)
  224. {
  225. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
  226. return FixedThopHandler3216(pti,
  227. *pti->pThop,
  228. sizeof(HAND16), FhHtask1632,
  229. sizeof(HANDLE), FhHtask3216);
  230. }
  231. DWORD Thop_HRESULT_3216( THUNKINFO *pti )
  232. {
  233. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
  234. return FixedThopHandler3216(pti,
  235. *pti->pThop,
  236. sizeof(HRESULT), FhHresult1632,
  237. sizeof(HRESULT), FhHresult3216);
  238. }
  239. DWORD Thop_NULL_3216(THUNKINFO *pti)
  240. {
  241. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
  242. return FixedThopHandler3216(pti,
  243. *pti->pThop,
  244. sizeof(void *), FhNull,
  245. sizeof(void *), FhNull);
  246. }
  247. DWORD Thop_RECT_3216( THUNKINFO *pti )
  248. {
  249. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
  250. return FixedThopHandler3216(pti,
  251. *pti->pThop,
  252. sizeof(RECT16), FhRect1632,
  253. sizeof(RECT), FhRect3216);
  254. }
  255. DWORD Thop_BINDOPTS_3216( THUNKINFO *pti )
  256. {
  257. LPBIND_OPTS pbo;
  258. UINT cb;
  259. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
  260. PEEK_STACK32(pti, pbo, LPBIND_OPTS);
  261. if (!IsBadReadPtr(pbo, sizeof(LPBIND_OPTS)))
  262. {
  263. cb = pbo->cbStruct;
  264. }
  265. else
  266. {
  267. return (DWORD)E_INVALIDARG;
  268. }
  269. return FixedThopHandler3216(pti,
  270. *pti->pThop,
  271. cb, FhCopyMemory,
  272. cb, FhCopyMemory);
  273. }
  274. DWORD Thop_SIZE_3216( THUNKINFO *pti )
  275. {
  276. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
  277. return FixedThopHandler3216(pti,
  278. *pti->pThop,
  279. sizeof(SIZE16), FhSize1632,
  280. sizeof(SIZE), FhSize3216);
  281. }
  282. DWORD Thop_MSG_3216( THUNKINFO *pti )
  283. {
  284. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
  285. return FixedThopHandler3216(pti,
  286. *pti->pThop,
  287. sizeof(MSG16), FhMsg1632,
  288. sizeof(MSG), FhMsg3216);
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Function: Thop_ERROR_3216, public
  293. //
  294. // Synopsis: Any Thop type which should just fail with an error
  295. // should go be directed here.
  296. //
  297. // Arguments: [pti] - Thunk state information
  298. //
  299. // Returns: Appropriate status code
  300. //
  301. // History: 23-Feb-94 BobDay Created
  302. //
  303. //----------------------------------------------------------------------------
  304. DWORD Thop_ERROR_3216 ( THUNKINFO *pti )
  305. {
  306. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
  307. thkAssert( FALSE && "Hey we hit an ERROR Thop in 32->16" );
  308. return (DWORD)E_UNEXPECTED;
  309. }
  310. //+---------------------------------------------------------------------------
  311. //
  312. // Function: ThunkInString3216, public
  313. //
  314. // Synopsis: Converts an in param string or filename
  315. //
  316. // Arguments: [pti] - Thunk state information
  317. // [fFile] - Filename or plain string
  318. // [cchMax] - Maximum length allowed or zero
  319. //
  320. // Returns: Appropriate status code
  321. //
  322. // History: 24-Aug-94 DrewB Created
  323. //
  324. //----------------------------------------------------------------------------
  325. DWORD ThunkInString3216(THUNKINFO *pti,
  326. BOOL fFile,
  327. UINT cchMax)
  328. {
  329. DWORD dwResult;
  330. LPOLESTR lpstr32;
  331. VPSTR vpstr16;
  332. UINT uiSize;
  333. LPOLESTR lpstrConv;
  334. LPOLESTR lpstrShort;
  335. dwResult = (DWORD)S_OK;
  336. lpstrShort = NULL;
  337. GET_STACK32(pti, lpstr32, LPOLESTR);
  338. lpstrConv = lpstr32;
  339. vpstr16 = 0;
  340. if (lpstr32 != NULL)
  341. {
  342. if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
  343. {
  344. return (DWORD)E_INVALIDARG;
  345. }
  346. if (fFile)
  347. {
  348. DWORD cchNeeded, cchShort;
  349. // Special case zero-length paths since the length returns from
  350. // GetShortPathName become ambiguous when zero characters are
  351. // processed
  352. cchNeeded = lstrlenW(lpstr32);
  353. if (cchNeeded > 0)
  354. {
  355. cchNeeded = GetShortPathName(lpstr32, NULL, 0);
  356. }
  357. // If we can't convert, simply pass through the name we're given
  358. if (cchNeeded > 0)
  359. {
  360. lpstrShort = (LPOLESTR)CoTaskMemAlloc(cchNeeded*sizeof(WCHAR));
  361. if (lpstrShort == NULL)
  362. {
  363. return (DWORD)E_OUTOFMEMORY;
  364. }
  365. cchShort = GetShortPathName(lpstr32, lpstrShort,
  366. cchNeeded);
  367. if (cchShort == 0 || cchShort > cchNeeded)
  368. {
  369. dwResult = (DWORD)E_UNEXPECTED;
  370. }
  371. else
  372. {
  373. lpstrConv = lpstrShort;
  374. }
  375. }
  376. }
  377. if (SUCCEEDED(dwResult))
  378. {
  379. uiSize = lstrlenW( lpstrConv ) + 1;
  380. vpstr16 = STACKALLOC16(uiSize*2);
  381. if (vpstr16 == 0)
  382. {
  383. dwResult = (DWORD)E_OUTOFMEMORY;
  384. }
  385. else
  386. {
  387. char *psz;
  388. dwResult = Convert_LPOLESTR_to_VPSTR(lpstrConv, vpstr16,
  389. uiSize, uiSize*2);
  390. // If a maximum length was given, truncate the converted
  391. // string if necessary
  392. if (SUCCEEDED(dwResult) && cchMax > 0 && cchMax < uiSize)
  393. {
  394. psz = (char *)WOWFIXVDMPTR(vpstr16, 0);
  395. psz[cchMax] = 0;
  396. WOWRELVDMPTR(vpstr16);
  397. }
  398. }
  399. }
  400. }
  401. if (SUCCEEDED(dwResult))
  402. {
  403. #if DBG == 1
  404. thkDebugOut((DEB_ARGS, "%sIn3216 LPSTR %p -> %p '%s'\n",
  405. NestingLevelString(), lpstr32, vpstr16,
  406. vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
  407. if (vpstr16 != 0)
  408. {
  409. WOWRELVDMPTR(vpstr16);
  410. }
  411. #endif
  412. TO_STACK16(pti, vpstr16, VPSTR);
  413. pti->pThop++;
  414. dwResult = EXECUTE_THOP3216(pti);
  415. }
  416. if (vpstr16 != 0)
  417. {
  418. STACKFREE16(vpstr16, uiSize*2);
  419. }
  420. if (lpstrShort != NULL)
  421. {
  422. CoTaskMemFree(lpstrShort);
  423. }
  424. return( dwResult );
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // Function: Thop_LPSTR_3216, public
  429. //
  430. // Synopsis: Converts 32-bit LPOLESTR to 16-bit LPSTR pointer
  431. //
  432. // Arguments: [pti] - Thunk state information
  433. //
  434. // Returns: Appropriate status code
  435. //
  436. // History: 23-Feb-94 BobDay Created
  437. //
  438. //----------------------------------------------------------------------------
  439. DWORD Thop_LPSTR_3216( THUNKINFO *pti )
  440. {
  441. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
  442. //
  443. // We have only input LPSTRs
  444. //
  445. thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
  446. "LPSTR must be input only!" );
  447. return ThunkInString3216(pti, FALSE, 0);
  448. }
  449. //+---------------------------------------------------------------------------
  450. //
  451. // Function: ConvertTaskString1632, public
  452. //
  453. // Synopsis: Converts a task-memory string
  454. //
  455. // Arguments: [pti] - Thunk info
  456. // [vpstr16] - String
  457. // [posPreAlloc] - Preallocated string or NULL
  458. // [cchPreAlloc] - Preallocated size or zero
  459. // [ppos32] - String
  460. //
  461. // Returns: Appropriate status code
  462. //
  463. // Modifies: [pti]
  464. // [ppos32]
  465. //
  466. // History: 14-May-94 DrewB Created
  467. //
  468. // Notes: Frees preallocation if successful and:
  469. // Name is too large or
  470. // Name is NULL
  471. //
  472. // Always frees source string if non-zero
  473. //
  474. //----------------------------------------------------------------------------
  475. SCODE ConvertTaskString1632(THUNKINFO *pti,
  476. VPSTR vpstr16,
  477. LPOLESTR posPreAlloc,
  478. UINT cchPreAlloc,
  479. LPOLESTR *ppos32)
  480. {
  481. LPOLESTR pos32;
  482. if (vpstr16 == 0)
  483. {
  484. pos32 = NULL;
  485. }
  486. else
  487. {
  488. pos32 = Convert_VPSTR_to_LPOLESTR(pti, vpstr16, posPreAlloc,
  489. cchPreAlloc);
  490. TaskFree16(vpstr16);
  491. if (pos32 == NULL)
  492. {
  493. return pti->scResult;
  494. }
  495. }
  496. // If there was a preallocated string we didn't use,
  497. // free it
  498. if (posPreAlloc != NULL && posPreAlloc != pos32)
  499. {
  500. TaskFree32(posPreAlloc);
  501. }
  502. *ppos32 = pos32;
  503. return S_OK;
  504. }
  505. //+---------------------------------------------------------------------------
  506. //
  507. // Function: ThunkOutString3216, public
  508. //
  509. // Synopsis: Converts an out param string
  510. //
  511. // Arguments: [pti] - Thunk state information
  512. //
  513. // Returns: Appropriate status code
  514. //
  515. // History: 24-Aug-94 DrewB Created
  516. //
  517. //----------------------------------------------------------------------------
  518. DWORD ThunkOutString3216(THUNKINFO *pti)
  519. {
  520. DWORD dwResult;
  521. LPOLESTR *lplpstr32;
  522. VPVOID vpvpstr16;
  523. VPSTR UNALIGNED *lpvpstr16;
  524. LPOLESTR lpstr32;
  525. GET_STACK32(pti, lplpstr32, LPOLESTR FAR *);
  526. if ( lplpstr32 == NULL )
  527. {
  528. vpvpstr16 = 0;
  529. }
  530. else
  531. {
  532. if (IsBadWritePtr(lplpstr32, sizeof(LPOLESTR)))
  533. {
  534. return (DWORD)E_INVALIDARG;
  535. }
  536. vpvpstr16 = STACKALLOC16(sizeof(VPSTR));
  537. if (vpvpstr16 == 0)
  538. {
  539. return (DWORD)E_OUTOFMEMORY;
  540. }
  541. lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
  542. *lpvpstr16 = 0;
  543. RELVDMPTR(vpvpstr16);
  544. lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
  545. if (lpstr32 == NULL)
  546. {
  547. STACKFREE16(vpvpstr16, sizeof(VPSTR));
  548. return (DWORD)E_OUTOFMEMORY;
  549. }
  550. }
  551. TO_STACK16(pti, vpvpstr16, VPVOID);
  552. pti->pThop++;
  553. dwResult = EXECUTE_THOP3216(pti);
  554. if (lplpstr32 != NULL)
  555. {
  556. if (SUCCEEDED(dwResult))
  557. {
  558. lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
  559. if (lpvpstr16 == NULL)
  560. {
  561. dwResult = (DWORD)E_INVALIDARG;
  562. }
  563. else
  564. {
  565. SCODE sc;
  566. sc = ConvertTaskString1632(pti, *lpvpstr16, lpstr32,
  567. CWCSTRINGPREALLOC, &lpstr32);
  568. if (FAILED(sc))
  569. {
  570. dwResult = sc;
  571. }
  572. RELVDMPTR(vpvpstr16);
  573. }
  574. }
  575. if (FAILED(dwResult))
  576. {
  577. TaskFree32(lpstr32);
  578. *lplpstr32 = NULL;
  579. }
  580. else
  581. {
  582. *lplpstr32 = lpstr32;
  583. }
  584. thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR: %p -> %p, '%ws'\n",
  585. *lpvpstr16, lpstr32, lpstr32));
  586. }
  587. else
  588. {
  589. thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR NULL\n"));
  590. }
  591. if (vpvpstr16 != 0)
  592. {
  593. STACKFREE16(vpvpstr16, sizeof(VPSTR));
  594. }
  595. return( dwResult );
  596. }
  597. //+---------------------------------------------------------------------------
  598. //
  599. // Function: Thop_LPLPSTR_3216, public
  600. //
  601. // Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
  602. //
  603. // Arguments: [pti] - Thunk state information
  604. //
  605. // Returns: Appropriate status code
  606. //
  607. // History: 26-Feb-94 BobDay Created
  608. //
  609. //----------------------------------------------------------------------------
  610. DWORD Thop_LPLPSTR_3216( THUNKINFO *pti )
  611. {
  612. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
  613. //
  614. // We don't have anything but unmodified LPLPSTRs
  615. //
  616. thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
  617. "LPLPSTR must be unmodified only!" );
  618. return ThunkOutString3216(pti);
  619. }
  620. //+---------------------------------------------------------------------------
  621. //
  622. // Function: Thop_BUFFER_3216, public
  623. //
  624. // Synopsis: Converts 32-bit block of memory to 16-bit block of memory
  625. //
  626. // Arguments: [pti] - Thunk state information
  627. //
  628. // Returns: Appropriate status code
  629. //
  630. // History: 25-Feb-94 BobDay Created
  631. //
  632. // Notes: WARNING! WARNING! WARNING! For an out parameter this expects
  633. // three parameters on the stack in the following format and order:
  634. // VOID * pointer to buffer
  635. // DWORD count of bytes in buffer
  636. // DWORD * count of bytes returned in the buffer
  637. //
  638. //----------------------------------------------------------------------------
  639. #define WATCH_VALUE 0xfef1f0
  640. DWORD Thop_BUFFER_3216( THUNKINFO *pti )
  641. {
  642. DWORD dwResult;
  643. BOOL fThopInput;
  644. BOOL fThopOutput;
  645. LPVOID lp32;
  646. VPVOID vp16;
  647. LPVOID lp16;
  648. DWORD dwCount;
  649. VPVOID vp16CountOut;
  650. LPVOID pvCountOut32;
  651. DWORD * pdwCountOut32;
  652. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
  653. fThopInput = IS_THOP_IN(pti);
  654. fThopOutput = IS_THOP_OUT(pti);
  655. //
  656. // Buffers can only be in or out
  657. //
  658. thkAssert( (fThopInput || fThopOutput) &&
  659. (fThopInput != fThopOutput) &&
  660. "BUFFER must be in or out only!" );
  661. GET_STACK32(pti, lp32, LPVOID);
  662. GET_STACK32(pti, dwCount, DWORD);
  663. if (fThopOutput)
  664. {
  665. GET_STACK32(pti, pvCountOut32, LPVOID);
  666. pdwCountOut32 = (DWORD *) pvCountOut32;
  667. }
  668. if ( lp32 == NULL )
  669. {
  670. vp16 = 0;
  671. }
  672. else if (dwCount == 0)
  673. {
  674. // If the count is zero then we can pass any valid 16-bit
  675. // pointer
  676. #if DBG == 1
  677. // In debug, make sure that no data is written back to the
  678. // memory we pass on
  679. vp16 = STACKALLOC16(sizeof(DWORD));
  680. if ( vp16 == 0 )
  681. {
  682. return (DWORD)E_OUTOFMEMORY;
  683. }
  684. *FIXVDMPTR(vp16, DWORD) = WATCH_VALUE;
  685. RELVDMPTR(vp16);
  686. #else
  687. vp16 = gdata16Data.atfnProxy1632Vtbl;
  688. #endif
  689. }
  690. else
  691. {
  692. if ((fThopInput && IsBadReadPtr(lp32, dwCount)) ||
  693. (fThopOutput && IsBadWritePtr(lp32, dwCount)))
  694. {
  695. return (DWORD)E_INVALIDARG;
  696. }
  697. vp16 = (VPVOID)WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
  698. if ( vp16 == 0 )
  699. {
  700. return (DWORD)E_OUTOFMEMORY;
  701. }
  702. if ( fThopInput )
  703. {
  704. lp16 = (LPVOID)WOWFIXVDMPTR(vp16, dwCount);
  705. memcpy( lp16, lp32, dwCount );
  706. WOWRELVDMPTR(vp16);
  707. }
  708. }
  709. if (fThopOutput)
  710. {
  711. // We always allocate storage so we can guarantee that we
  712. // only copy the correct number of bytes.
  713. vp16CountOut = STACKALLOC16(sizeof(DWORD));
  714. if (vp16CountOut == 0)
  715. {
  716. return (DWORD) E_OUTOFMEMORY;
  717. }
  718. }
  719. thkDebugOut((DEB_ARGS, "3216 BUFFER: %p -> %p, %u\n",
  720. lp32, vp16, dwCount));
  721. TO_STACK16(pti, vp16, VPVOID );
  722. TO_STACK16(pti, dwCount, DWORD );
  723. if (fThopOutput)
  724. {
  725. TO_STACK16(pti, vp16CountOut, VPVOID );
  726. }
  727. pti->pThop++;
  728. dwResult = EXECUTE_THOP3216(pti);
  729. if ( SUCCEEDED(dwResult) && fThopOutput )
  730. {
  731. // Count of bytes to copy into the output buffer
  732. DWORD dwCountOut;
  733. // Get the output data count
  734. DWORD UNALIGNED *pdw16 = (DWORD UNALIGNED *)
  735. WOWFIXVDMPTR(vp16CountOut, sizeof(DWORD));
  736. // Save count to return to 32 bit caller.
  737. dwCountOut = *pdw16;
  738. if (pdwCountOut32)
  739. {
  740. // Note: this parameter can be a NULL pointer
  741. *pdwCountOut32 = dwCountOut;
  742. }
  743. WOWRELVDMPTR(vp16CountOut);
  744. // Copy data into output buffer if necessary.
  745. if (dwCountOut > 0)
  746. {
  747. lp16 = (LPVOID) WOWFIXVDMPTR( vp16, dwCountOut );
  748. memcpy( lp32, lp16, dwCountOut );
  749. WOWRELVDMPTR(vp16);
  750. }
  751. }
  752. #if DBG == 1
  753. if (vp16 != 0 && dwCount == 0)
  754. {
  755. thkAssert(*FIXVDMPTR(vp16, DWORD) == WATCH_VALUE &&
  756. (RELVDMPTR(vp16), TRUE));
  757. STACKFREE16(vp16, sizeof(DWORD));
  758. }
  759. #endif
  760. //
  761. // Now free the buffers
  762. //
  763. if ( vp16 != 0 && dwCount > 0 )
  764. {
  765. WgtUnlockFree( vp16 );
  766. }
  767. if (fThopOutput && (vp16CountOut != 0))
  768. {
  769. STACKFREE16(vp16CountOut, sizeof(DWORD));
  770. }
  771. return( dwResult );
  772. }
  773. //+---------------------------------------------------------------------------
  774. //
  775. // Function: Thop_SNB_3216, public
  776. //
  777. // Synopsis: Converts 32-bit SNB to 16-bit SNB pointer
  778. //
  779. // Arguments: [pti] - Thunk state information
  780. //
  781. // Returns: Appropriate status code
  782. //
  783. // History: 23-Feb-94 BobDay Created
  784. //
  785. //----------------------------------------------------------------------------
  786. DWORD Thop_SNB_3216( THUNKINFO *pti )
  787. {
  788. DWORD dwResult;
  789. BOOL fThopInput;
  790. BOOL fThopOutput;
  791. SNB snbSrc32; // Ptr to 32 bit Source SNB.
  792. LPOLESTR FAR *lplpsTabSrc32; // Ptr into 32 bit Source ptr table.
  793. LPOLESTR lpstr32; // Ptr into a Source Unicode data block.
  794. VPVOID snbDest16s; // Seg:Ptr to 16 bit Destination SNB.
  795. VPSTR UNALIGNED FAR *lpvpsTabDest16f; // Flat Ptr into 16 bit Dest ptr table.
  796. char UNALIGNED *lpstrDest16f; // Flat Ptr into 16 bit Dest data block.
  797. VPVOID lpstrDest16s; // Seg:Ptr into 16 bit Dest data block.
  798. UINT cPointers; // Count of number of string pointers.
  799. UINT cbStrings; // Count of number of bytes in data table.
  800. UINT cLength;
  801. UINT cChars;
  802. UINT cbAlloc;
  803. UINT i;
  804. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
  805. fThopInput = IS_THOP_IN(pti);
  806. fThopOutput = IS_THOP_OUT(pti);
  807. //
  808. // We don't have anything but unmodified SNBs
  809. //
  810. thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
  811. GET_STACK32(pti, snbSrc32, LPOLESTR FAR *);
  812. if ( snbSrc32 == NULL )
  813. {
  814. snbDest16s = 0;
  815. }
  816. else
  817. {
  818. //
  819. // Count the strings in the 32-bit snb
  820. //
  821. lplpsTabSrc32 = snbSrc32;
  822. cPointers = 0;
  823. cbStrings = 0;
  824. do
  825. {
  826. cPointers++;
  827. if (IsBadReadPtr(lplpsTabSrc32, sizeof(LPOLESTR)))
  828. {
  829. return (DWORD)E_INVALIDARG;
  830. }
  831. lpstr32 = *lplpsTabSrc32++;
  832. if ( lpstr32 == NULL )
  833. {
  834. break;
  835. }
  836. if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
  837. {
  838. return (DWORD)E_INVALIDARG;
  839. }
  840. cbStrings += lstrlenW(lpstr32)+1;
  841. }
  842. while ( TRUE );
  843. //
  844. // Allocate a table for the 16-bit snb
  845. // cPointers is a count of pointers plus the NULL pointer at the end.
  846. //
  847. cbAlloc = cPointers*sizeof(VPSTR)+cbStrings;
  848. snbDest16s = (VPVOID)STACKALLOC16(cbAlloc);
  849. if (snbDest16s == 0)
  850. {
  851. return (DWORD)E_OUTOFMEMORY;
  852. }
  853. //
  854. // Set up the pointers to the destination table and string block.
  855. // This gets a flat pointer to the pointer table, a both flat and
  856. // segmented pointers to the data block.
  857. //
  858. lpvpsTabDest16f = (VPSTR UNALIGNED FAR *)WOWFIXVDMPTR( snbDest16s, cbAlloc );
  859. lpstrDest16f = (char UNALIGNED *)
  860. ((BYTE UNALIGNED *)lpvpsTabDest16f+cPointers*sizeof(VPSTR));
  861. lpstrDest16s = (VPVOID)((DWORD)snbDest16s+cPointers*sizeof(VPSTR));
  862. //
  863. // Now convert the strings
  864. //
  865. cPointers -= 1;
  866. lplpsTabSrc32 = snbSrc32;
  867. for(i=0; i<cPointers; i++)
  868. {
  869. lpstr32 = *lplpsTabSrc32++;
  870. thkAssert( lpstr32 != NULL && "Loop is processing end of snb\n" );
  871. cLength = lstrlenW( lpstr32 ) + 1;
  872. cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  873. 0, lpstr32, cLength,
  874. lpstrDest16f, cbStrings, NULL, NULL );
  875. if ( cChars == 0 && cLength != 0 )
  876. {
  877. WOWRELVDMPTR(snbDest16s);
  878. STACKFREE16(snbDest16s, cbAlloc);
  879. return (DWORD)E_UNEXPECTED;
  880. }
  881. //
  882. // Assign the Segmented pointer into the pointer table.
  883. //
  884. *lpvpsTabDest16f++ = lpstrDest16s;
  885. //
  886. // Advance both the flat and segmented data pointers.
  887. //
  888. lpstrDest16f += cChars;
  889. lpstrDest16s = (VPVOID)((DWORD)lpstrDest16s + cChars);
  890. //
  891. // As we advance the Dest pointer the size of the remaining
  892. // space in the buffer decreases.
  893. //
  894. cbStrings -= cChars;
  895. }
  896. // Terminate SNB
  897. *lpvpsTabDest16f = NULL;
  898. thkAssert( *lplpsTabSrc32 == NULL &&
  899. "Loop is out of sync with count\n" );
  900. WOWRELVDMPTR(snbDest16s);
  901. }
  902. thkDebugOut((DEB_ARGS, "In3216 SNB: %p -> %p\n", snbSrc32, snbDest16s));
  903. TO_STACK16(pti, snbDest16s, VPVOID );
  904. pti->pThop++;
  905. dwResult = EXECUTE_THOP3216(pti);
  906. //
  907. // Free SNB data if necessary
  908. //
  909. if ( snbDest16s != 0 )
  910. {
  911. STACKFREE16( snbDest16s, cbAlloc );
  912. }
  913. return( dwResult );
  914. }
  915. //+---------------------------------------------------------------------------
  916. //
  917. // Function: ThunkInterface3216, private
  918. //
  919. // Synopsis: Handles 32->16 interface thunking for THOP_IFACE and
  920. // THOP_IFACEGEN
  921. //
  922. // Arguments: [pti] - Thunking state information
  923. // [iidx] - Interface IID or index
  924. // [thop] - Thop being executed
  925. // [vpvOuter] - Controlling unknown passed to the 16-bit world
  926. //
  927. // Returns: Status code
  928. //
  929. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  930. // proper thunking of IN/OUT interfaces
  931. //
  932. // Notes: Assumes pti->pThop is adjusted by caller
  933. //----------------------------------------------------------------------------
  934. DWORD ThunkInterface3216(THUNKINFO *pti, IIDIDX iidx, THOP thop, VPVOID vpvOuter)
  935. {
  936. // Local variables
  937. DWORD dwResult, dwStatus;
  938. void *pv;
  939. VPVOID vpvOutParam;
  940. VPVOID vpvThis16In, vpvThis16Out;
  941. IUnknown *punkOut;
  942. IUnknown *punkIn;
  943. THUNK3216OBJ *ptoPreAlloc = NULL;
  944. PROXYHOLDER *pph = NULL;
  945. PROXYHOLDER *pAggHolder = NULL;
  946. SAggHolder aggHolderNode;
  947. BOOL bUnlinkAggHolder = FALSE;
  948. // Validate the IID of the interface
  949. thkAssert(IIDIDX_IS_IID(iidx) ||
  950. (IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) < THI_COUNT));
  951. // Initialize
  952. dwResult = (DWORD) S_OK;
  953. vpvOutParam = NULL;
  954. vpvThis16In = NULL;
  955. // Retrieve interface pointer
  956. GET_STACK32(pti, pv, void *);
  957. // Check for valid OUT parameter. It also verifies IN-OUT case as well
  958. if((thop & THOP_OUT) && pv) {
  959. if(IsBadReadPtr(pv, sizeof(void *)) || IsBadWritePtr(pv, sizeof(void *))) {
  960. thkDebugOut((DEB_WARN, "WARNING: failing - bad pointer %p\n", pv));
  961. return (DWORD) E_INVALIDARG;
  962. }
  963. // Check if the interface needs to be thunked IN as well.
  964. // In other words, IN-OUT paramenter case
  965. if(thop & THOP_IN)
  966. punkIn = *(IUnknown **)pv;
  967. else
  968. punkIn = NULL;
  969. }
  970. else {
  971. // It must be IN parameter or a NULL OUT parameter
  972. punkIn = (IUnknown *)pv;
  973. }
  974. // Check if interface needs to be thunked IN
  975. if(thop & THOP_IN) {
  976. if(punkIn) {
  977. // Validate the interface
  978. if(IsValidInterface(punkIn)) {
  979. if((thop & THOP_OPMASK) == THOP_UNKOUTER) {
  980. // Aggregation being carried out
  981. // Assert that it is only being thunked IN
  982. thkAssert(!(thop & THOP_OUT));
  983. thkAssert(iidx == THI_IUnknown);
  984. // Either find the actual 16-bit identity or generate a
  985. // new 16-bit proxy identity for the 32-bit identity
  986. vpvThis16In = pti->pThkMgr->CreateOuter16(punkIn, &pAggHolder, &dwStatus);
  987. aggHolderNode.pph = pAggHolder;
  988. TlsThkLinkAggHolder(&aggHolderNode);
  989. bUnlinkAggHolder = TRUE;
  990. // We use this pAggHolder for proxies of inner unk(s). Since
  991. // we cannot put it in the proxy table (as it is private
  992. // and we do not want other thunk calls to use it), we put
  993. // it in a linked list in the TLS. The holder gets used by
  994. // calls to FindAggregate() when the pUnkInner is being
  995. // thunked out. The holder is revoked from the list when
  996. // the ThunkInterface call for the pUnkOuter unwinds.
  997. }
  998. else {
  999. // Find/Generate the proxy for the 32-bit interface
  1000. // to be thunked IN
  1001. vpvThis16In = pti->pThkMgr->FindProxy1632(NULL, punkIn, NULL,
  1002. iidx, &dwStatus);
  1003. }
  1004. if(vpvThis16In) {
  1005. thkAssert(!((thop & THOP_OPMASK) == THOP_UNKOUTER) ||
  1006. (dwStatus == FST_CREATED_NEW) ||
  1007. (dwStatus == FST_SHORTCUT));
  1008. }
  1009. else {
  1010. thkDebugOut((DEB_WARN, "WARNING: failing - Can't create proxy for %p\n",
  1011. punkIn));
  1012. return (DWORD) E_OUTOFMEMORY;
  1013. }
  1014. }
  1015. else {
  1016. thkDebugOut((DEB_WARN, "WARNING: failing - invalid interface %p\n",
  1017. punkIn));
  1018. return (DWORD) E_INVALIDARG;
  1019. }
  1020. }
  1021. else {
  1022. // No interface to be thunked IN
  1023. vpvThis16In = NULL;
  1024. }
  1025. thkDebugOut((DEB_ARGS, "%sIn3216 %s %p -> %p\n",
  1026. NestingLevelString(), IidIdxString(iidx),
  1027. punkIn, vpvThis16In));
  1028. }
  1029. // Check if interface needs to be thunked OUT
  1030. if((thop & THOP_OUT) && pv) {
  1031. // Preallocate a proxy for the out parameter
  1032. ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx);
  1033. if(ptoPreAlloc) {
  1034. // Allocate space for OUT parameter from the 16-bit heap
  1035. vpvOutParam = STACKALLOC16(sizeof(VPVOID));
  1036. if(vpvOutParam) {
  1037. // Assert that no interface is being thunked IN for
  1038. // pure OUT parameter case
  1039. thkAssert((thop & THOP_IN) || !vpvThis16In);
  1040. // Assign the interface being thunked IN
  1041. *FIXVDMPTR(vpvOutParam, VPVOID) = vpvThis16In;
  1042. RELVDMPTR(vpvOutParam);
  1043. // Push the OUT/IN-OUT parameter onto the stack
  1044. TO_STACK16(pti, vpvOutParam, VPVOID);
  1045. }
  1046. else {
  1047. thkDebugOut((DEB_WARN, "WARNING: failing - Allocation on 16-bit heap failed\n"));
  1048. dwResult = (DWORD)E_OUTOFMEMORY;
  1049. }
  1050. }
  1051. else {
  1052. thkDebugOut((DEB_WARN, "WARNING: failing - Cannot allocate proxy\n"));
  1053. dwResult = (DWORD) E_OUTOFMEMORY;
  1054. }
  1055. }
  1056. else {
  1057. // Assert invariant
  1058. thkAssert((pv && vpvThis16In) || (!pv && !vpvThis16In));
  1059. // Push the IN parameter onto the stack
  1060. TO_STACK16(pti, vpvThis16In, VPVOID);
  1061. }
  1062. if(SUCCEEDED((SCODE)dwResult)) {
  1063. // Execute the next THOP operation
  1064. dwResult = EXECUTE_THOP3216(pti);
  1065. }
  1066. if((thop & THOP_OUT) && pv) {
  1067. punkOut = NULL;
  1068. if(SUCCEEDED((SCODE)dwResult)) {
  1069. // Obtain the 16-bit interface to be thunked OUT
  1070. vpvThis16Out = *FIXVDMPTR(vpvOutParam, VPVOID);
  1071. RELVDMPTR(vpvOutParam);
  1072. // Check if a 16-bit interface was returned
  1073. if(vpvThis16Out) {
  1074. // Obtain 32-bit proxy for the 16-bit interface
  1075. if(vpvOuter) {
  1076. //Get the holder that was linked into TLS when the pUnkOuter
  1077. //was being thunked in.
  1078. pAggHolder = (TlsThkGetAggHolder())->pph;
  1079. punkOut = pti->pThkMgr->FindAggregate3216(ptoPreAlloc, vpvOuter,
  1080. vpvThis16Out, iidx, pAggHolder,
  1081. &dwStatus);
  1082. }
  1083. else {
  1084. punkOut = pti->pThkMgr->FindProxy3216(ptoPreAlloc, vpvThis16Out,
  1085. NULL, iidx, FALSE, &dwStatus);
  1086. }
  1087. if(punkOut) {
  1088. if((thop & THOP_OPMASK) == THOP_UNKINNER) {
  1089. if (dwStatus != FST_SHORTCUT) {
  1090. // Obtain the holder
  1091. pph = ((THUNK3216OBJ *)punkOut)->pphHolder ;
  1092. // Assert invariants in debug builds
  1093. thkAssert(pph->dwFlags & PH_AGGREGATEE);
  1094. thkAssert(dwStatus == FST_CREATED_NEW);
  1095. // Mark the proxy as representing inner unknown
  1096. ((THUNK3216OBJ *)punkOut)->grfFlags = PROXYFLAG_PUNKINNER;
  1097. }
  1098. }
  1099. // Either the preallocated proxy was used and freed
  1100. ptoPreAlloc = NULL;
  1101. }
  1102. else {
  1103. dwResult = (DWORD)E_OUTOFMEMORY;
  1104. }
  1105. // Release the actual 16-bit interface. If a proxy to the
  1106. // 16-bit interface could not be created above, this could
  1107. // be the last release on the 16-bit interface
  1108. ReleaseOnObj16(vpvThis16Out);
  1109. }
  1110. }
  1111. // Set the OUT parameter
  1112. *(void **)pv = (void *)punkOut;
  1113. thkDebugOut((DEB_ARGS, "%sOut3216 %s %p -> %p\n",
  1114. NestingLevelString(), IidIdxString(iidx),
  1115. vpvThis16Out, punkOut));
  1116. }
  1117. if(vpvThis16In) {
  1118. if((thop & THOP_INOUT) == THOP_INOUT) {
  1119. // IN-OUT parameter.
  1120. thkAssert(punkIn);
  1121. // Release the 32-bit side interface
  1122. punkIn->Release();
  1123. }
  1124. else {
  1125. // Just an IN parameter
  1126. thkAssert(thop & THOP_IN);
  1127. #if DBG==1
  1128. // Ensure that the following is not the last release
  1129. // on the IN parameter
  1130. THKSTATE thkstate;
  1131. // Remember the current thunk state
  1132. thkstate = pti->pThkMgr->GetThkState();
  1133. // Set the thunk state to THKSTATE_VERIFYINPARAM
  1134. pti->pThkMgr->SetThkState(THKSTATE_VERIFY32INPARAM);
  1135. #endif
  1136. // Release the 16-bit side interface
  1137. ReleaseOnObj16(vpvThis16In);
  1138. #if DBG==1
  1139. // Restore previous thunk state
  1140. pti->pThkMgr->SetThkState(thkstate);
  1141. #endif
  1142. }
  1143. // We should never receive a call IRpcStubBuffer::DebugServerRelease
  1144. Win4Assert((thop & THOP_OPMASK) != THOP_IFACECLEAN);
  1145. }
  1146. // Cleanup
  1147. if(ptoPreAlloc) {
  1148. // Free preallocated proxy as it was not used
  1149. pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
  1150. }
  1151. if(vpvOutParam) {
  1152. // Free the space created on the 16-bit for the OUT parameter
  1153. STACKFREE16(vpvOutParam, sizeof(VPVOID));
  1154. }
  1155. if (bUnlinkAggHolder) {
  1156. TlsThkUnlinkAggHolder();
  1157. }
  1158. return dwResult;
  1159. }
  1160. //+---------------------------------------------------------------------------
  1161. //
  1162. // Function: Thop_IFACEGEN_3216, public
  1163. //
  1164. // Synopsis: Thunks riid,ppv pairs from 16->32
  1165. //
  1166. // Arguments: [pti] - Thunk state information
  1167. //
  1168. // Returns: Appropriate status code
  1169. //
  1170. // History: 23-Feb-94 DrewB Created
  1171. //
  1172. //----------------------------------------------------------------------------
  1173. DWORD Thop_IFACEGEN_3216(THUNKINFO *pti)
  1174. {
  1175. IIDIDX iidx;
  1176. THOP thop, thopOp, thopWeakOffset;
  1177. VPVOID vpvOuter;
  1178. IID const *piid;
  1179. thop = *pti->pThop++;
  1180. thopOp = thop & THOP_OPMASK;
  1181. thkAssert(thopOp == THOP_IFACEGEN ||
  1182. thopOp == THOP_IFACEGENOWNER);
  1183. // The current thop byte indicates how many bytes to look
  1184. // back in the stack to find the IID which identifies the
  1185. // interface being returned
  1186. INDEX_STACK32(pti, piid, IID const *, *pti->pThop);
  1187. #if DBG == 1
  1188. if (!IsValidIid(*piid))
  1189. {
  1190. return (DWORD)E_INVALIDARG;
  1191. }
  1192. #endif
  1193. pti->pThop++;
  1194. iidx = IidToIidIdx(*piid);
  1195. vpvOuter = 0;
  1196. if (thopOp == THOP_IFACEGENOWNER)
  1197. {
  1198. // Obtain the outer unknown that is being passed to the 16 bit world
  1199. thopWeakOffset = *pti->pThop++;
  1200. INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
  1201. if(vpvOuter) {
  1202. // Aggregation across 32-16 boundary
  1203. // Assert that the IID requested is IID_IUnknown
  1204. thkAssert(iidx == THI_IUnknown ||
  1205. (pti->iidx==THI_IPSFactoryBuffer && pti->dwMethod==3));
  1206. // Change thop to indicate that inner unknown is being thunked
  1207. if(iidx == THI_IUnknown)
  1208. thop = (thop & THOP_IOMASK) | THOP_UNKINNER;
  1209. }
  1210. }
  1211. return ThunkInterface3216(pti, iidx, thop, vpvOuter);
  1212. }
  1213. //+---------------------------------------------------------------------------
  1214. //
  1215. // Function: Thop_OIFI_3216, public
  1216. //
  1217. // Synopsis: Convert OLEINPLACEFRAMEINFO
  1218. //
  1219. // Arguments: [pti] - Thunking state information
  1220. //
  1221. // Returns: Appropriate status code
  1222. //
  1223. // History: 26-May-94 DrewB Created
  1224. //
  1225. //----------------------------------------------------------------------------
  1226. DWORD Thop_OIFI_3216( THUNKINFO *pti )
  1227. {
  1228. DWORD dwResult;
  1229. VPVOID vpoifi16;
  1230. OIFI16 UNALIGNED *poifi16;
  1231. OLEINPLACEFRAMEINFO *poifi32;
  1232. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
  1233. thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
  1234. // OIFIs are out-only parameters for their contents
  1235. // However, cb is in/out, so we need to copy cb on the way in
  1236. // Furthermore, cb may not be set to a valid value, in which
  1237. // case the documentation mentions that it should be assumed
  1238. // that this is an OLE 2.0 OIFI
  1239. // This thop simply ignores cb on the way in and always sets
  1240. // it to the OLE 2.0 size
  1241. // Since we're out-only, this always works since the number of
  1242. // fields we thunk is the size of the structure that we give out
  1243. // If OLEINPLACEFRAMEINFO is extended, this thop will break
  1244. // Assert that OLEINPLACEFRAMEINFO is what we expect it to be
  1245. thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
  1246. GET_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
  1247. vpoifi16 = 0;
  1248. if (poifi32 != NULL)
  1249. {
  1250. if (IsBadWritePtr(poifi32, sizeof(OLEINPLACEFRAMEINFO)))
  1251. {
  1252. return (DWORD)E_INVALIDARG;
  1253. }
  1254. vpoifi16 = STACKALLOC16(sizeof(OIFI16));
  1255. if (vpoifi16 == 0)
  1256. {
  1257. return (DWORD)E_OUTOFMEMORY;
  1258. }
  1259. // OIFI's may be an out only parameters but if the "cb" field is
  1260. // "in" RPC doesn't slice up structs, so the whole thing is "in"
  1261. // as well. We are Thoping here but if we want this to match
  1262. // the RPC sematics then we need to copy all the fields.
  1263. poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
  1264. poifi16->cb = sizeof(OIFI16);
  1265. poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
  1266. poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
  1267. poifi16->cAccelEntries =
  1268. ClampULongToUShort(poifi32->cAccelEntries);
  1269. if (poifi32->haccel == NULL)
  1270. {
  1271. poifi16->haccel = NULL;
  1272. }
  1273. else
  1274. {
  1275. // WOW will clean up any dangling accelerator tables when
  1276. // tasks die
  1277. poifi16->haccel = HACCEL_16(poifi32->haccel);
  1278. if (poifi16->haccel == NULL)
  1279. {
  1280. dwResult = (DWORD)E_UNEXPECTED;
  1281. }
  1282. }
  1283. RELVDMPTR(vpoifi16);
  1284. }
  1285. TO_STACK16(pti, vpoifi16, VPVOID);
  1286. pti->pThop++;
  1287. dwResult = EXECUTE_THOP3216(pti);
  1288. if (vpoifi16 != NULL)
  1289. {
  1290. poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
  1291. if (SUCCEEDED(dwResult))
  1292. {
  1293. poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
  1294. poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
  1295. poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
  1296. poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
  1297. if (poifi16->haccel == NULL)
  1298. {
  1299. poifi32->haccel = NULL;
  1300. }
  1301. else
  1302. {
  1303. // WOW will clean up any dangling accelerator tables when
  1304. // tasks die
  1305. // Check that the haccel is valid. We don't need to lock
  1306. // the pointer. We just want some means of validating it.
  1307. // HACCEL_32 faults in krnl386 if the handle is bad.
  1308. if(NULL != WOWGlobalLock16(poifi16->haccel))
  1309. {
  1310. poifi32->haccel = HACCEL_32(poifi16->haccel);
  1311. WOWGlobalUnlock16(poifi16->haccel);
  1312. }
  1313. else
  1314. {
  1315. poifi32->haccel = NULL;
  1316. }
  1317. if (poifi32->haccel == NULL)
  1318. {
  1319. dwResult = (DWORD)E_UNEXPECTED;
  1320. }
  1321. }
  1322. #if DBG == 1
  1323. if (SUCCEEDED(dwResult))
  1324. {
  1325. thkDebugOut((DEB_ARGS, "Out3216 OIFI: "
  1326. "%p {%d, %d, 0x%04X, 0x%04X, %d} -> "
  1327. "%p {%d, %d, 0x%p, 0x%p, %d}\n",
  1328. vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
  1329. (DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
  1330. poifi16->cAccelEntries,
  1331. poifi32, poifi32->cb, poifi32->fMDIApp,
  1332. poifi32->hwndFrame, poifi32->haccel,
  1333. poifi32->cAccelEntries));
  1334. }
  1335. #endif
  1336. }
  1337. RELVDMPTR(vpoifi16);
  1338. if (FAILED(dwResult))
  1339. {
  1340. memset(poifi32, 0, sizeof(OLEINPLACEFRAMEINFO));
  1341. }
  1342. STACKFREE16(vpoifi16, sizeof(OIFI16));
  1343. }
  1344. return dwResult;
  1345. }
  1346. //+---------------------------------------------------------------------------
  1347. //
  1348. // Function: Thop_STGMEDIUM_3216, public
  1349. //
  1350. // Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
  1351. // structure
  1352. //
  1353. // Arguments: [pti] - Thunk state information
  1354. //
  1355. // Returns: Appropriate status code
  1356. //
  1357. // History: 23-Feb-94 BobDay Created
  1358. //
  1359. //----------------------------------------------------------------------------
  1360. DWORD Thop_STGMEDIUM_3216(THUNKINFO *pti)
  1361. {
  1362. DWORD dwResult;
  1363. BOOL fThopInput;
  1364. BOOL fThopOutput;
  1365. VPVOID vpstgmedium16;
  1366. STGMEDIUM *lpstgmedium32;
  1367. DWORD dwSize;
  1368. SCODE sc;
  1369. BOOL fReleaseParam;
  1370. BOOL fTransferOwnership;
  1371. FORMATETC *pfe;
  1372. THOP thopFeOffset;
  1373. DWORD vpIStream = 0;
  1374. STGMEDIUM UNALIGNED *psm16;
  1375. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
  1376. fThopInput = IS_THOP_IN(pti);
  1377. fThopOutput = IS_THOP_OUT(pti);
  1378. //
  1379. // We currently don't have any unmodified or inout thops for STGMEDIUMs
  1380. //
  1381. thkAssert( (fThopInput || fThopOutput) &&
  1382. (fThopInput != fThopOutput) &&
  1383. "STGMEDIUM must be input or output only" );
  1384. // +2 thop byte indicates whether there's a FORMATETC to look at
  1385. // or not
  1386. // We need to reference this now before the stack is modified
  1387. // by argument recovery
  1388. thopFeOffset = *(pti->pThop+2);
  1389. if (thopFeOffset > 0)
  1390. {
  1391. INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
  1392. }
  1393. else
  1394. {
  1395. pfe = NULL;
  1396. }
  1397. GET_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
  1398. // Next thop byte indicates whether there's an ownership transfer
  1399. // argument or not
  1400. pti->pThop++;
  1401. fReleaseParam = (BOOL)*pti->pThop++;
  1402. if (fReleaseParam)
  1403. {
  1404. GET_STACK32(pti, fTransferOwnership, BOOL);
  1405. }
  1406. else
  1407. {
  1408. fTransferOwnership = FALSE;
  1409. }
  1410. // Skip FORMATETC offset thop
  1411. pti->pThop++;
  1412. vpstgmedium16 = 0;
  1413. if ( lpstgmedium32 != NULL )
  1414. {
  1415. if ((fThopInput && IsBadReadPtr(lpstgmedium32, sizeof(STGMEDIUM))) ||
  1416. (fThopOutput && IsBadWritePtr(lpstgmedium32, sizeof(STGMEDIUM))))
  1417. {
  1418. return (DWORD)E_INVALIDARG;
  1419. }
  1420. vpstgmedium16 = STACKALLOC16(sizeof(STGMEDIUM));
  1421. if (vpstgmedium16 == 0)
  1422. {
  1423. return (DWORD)E_OUTOFMEMORY;
  1424. }
  1425. if ( fThopInput )
  1426. {
  1427. sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
  1428. pfe, fTransferOwnership, &dwSize);
  1429. if (SUCCEEDED(sc))
  1430. {
  1431. // Apparently if you pass TYMED_NULL into GetDataHere
  1432. // it's supposed to work like GetData, so switch input-only
  1433. // TYMED_NULLs to output
  1434. if (lpstgmedium32->tymed == TYMED_NULL &&
  1435. !fTransferOwnership)
  1436. {
  1437. fThopInput = FALSE;
  1438. fThopOutput = TRUE;
  1439. }
  1440. else if (lpstgmedium32->tymed == TYMED_ISTREAM)
  1441. {
  1442. //
  1443. // Excel has a bug in its Clipboard data object that when
  1444. // GetDataHere is done providing a IStream interface, it
  1445. // will create its own stream and pounce on the pointer
  1446. // being passed in. So, if the thing is input, and the
  1447. // TYMED is ISTREAM we need to stash away the original
  1448. // 16-bit stream pointer for use later.
  1449. //
  1450. psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
  1451. vpIStream = (DWORD)psm16->pstm;
  1452. RELVDMPTR(vpstgmedium16);
  1453. }
  1454. }
  1455. else
  1456. {
  1457. STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
  1458. return (DWORD)sc;
  1459. }
  1460. }
  1461. else
  1462. {
  1463. if( !((TlsThkGetAppCompatFlags() & OACF_CORELTRASHMEM) &&
  1464. lpstgmedium32->tymed == 0x66666666 ))
  1465. {
  1466. // Even though this is an out parameter, some apps
  1467. // (Graph 5 is one) check its values and depend on it
  1468. // being zeroed out
  1469. // However, if we are in CorelDraw *and* we're being
  1470. // called by wGetMonikerAndClassFromObject (tymed set to
  1471. // all 6's), then we do not want to set the tymed to zero.
  1472. // Corel5 relies on the memory being trashed in order to
  1473. // prevent paste-link-to-yourself.
  1474. memset(FIXVDMPTR(vpstgmedium16, STGMEDIUM), 0,
  1475. sizeof(STGMEDIUM));
  1476. RELVDMPTR(vpstgmedium16);
  1477. }
  1478. }
  1479. }
  1480. TO_STACK16(pti, vpstgmedium16, VPVOID);
  1481. if (fReleaseParam)
  1482. {
  1483. TO_STACK16(pti, (SHORT)fTransferOwnership, SHORT);
  1484. }
  1485. dwResult = EXECUTE_THOP3216(pti);
  1486. if (lpstgmedium32 != NULL)
  1487. {
  1488. if (fThopInput)
  1489. {
  1490. if (SUCCEEDED(dwResult) &&
  1491. (lpstgmedium32->tymed == TYMED_ISTREAM) &&
  1492. (vpIStream != 0))
  1493. {
  1494. //
  1495. // To continue our Excel Clipboard GetDataHere hack, if the
  1496. // TYMED was ISTREAM, and the medium was input (as it is now)
  1497. // then we need to detect the case where the IStream pointer
  1498. // changed. If it did change, then we have a special function
  1499. // in the 16-bit world that will copy the contents of the
  1500. // 'new' stream into 'our' stream, and release the 'new'
  1501. // stream. This should make the clipboard work properly.
  1502. //
  1503. psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
  1504. if( (psm16->tymed == TYMED_ISTREAM) &&
  1505. (vpIStream != (DWORD)psm16->pstm))
  1506. {
  1507. BYTE b32Args[WCB16_MAX_CBARGS];
  1508. *(DWORD *)&b32Args[0] = vpIStream;
  1509. *(DWORD *)&b32Args[sizeof(DWORD)] = (DWORD)psm16->pstm;
  1510. RELVDMPTR(vpstgmedium16);
  1511. if( !CallbackTo16Ex(
  1512. (DWORD)gdata16Data.fnStgMediumStreamHandler16,
  1513. WCB16_PASCAL,
  1514. 2*sizeof(DWORD),
  1515. b32Args,
  1516. &dwResult) )
  1517. {
  1518. dwResult = (DWORD)E_UNEXPECTED;
  1519. }
  1520. }
  1521. else
  1522. {
  1523. //
  1524. // Two possibilites
  1525. // The stream pointers are the same. Good news
  1526. // The tymed was changed. Bad news. There isn't anything
  1527. // we can safely do with the different tymed, so ignore
  1528. // the whole thing.
  1529. //
  1530. RELVDMPTR(vpstgmedium16);
  1531. }
  1532. }
  1533. if (!fTransferOwnership || FAILED(dwResult))
  1534. {
  1535. sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
  1536. dwSize, TRUE, pfe);
  1537. if (FAILED(sc))
  1538. {
  1539. dwResult = (DWORD)sc;
  1540. }
  1541. }
  1542. else if (SUCCEEDED(dwResult))
  1543. {
  1544. if (lpstgmedium32->pUnkForRelease == NULL)
  1545. {
  1546. sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
  1547. 0, FALSE, pfe);
  1548. thkAssert(SUCCEEDED(sc));
  1549. }
  1550. }
  1551. }
  1552. else
  1553. {
  1554. thkAssert(fThopOutput);
  1555. if (SUCCEEDED(dwResult))
  1556. {
  1557. sc = ConvertStgMed1632(pti, vpstgmedium16, lpstgmedium32,
  1558. pfe, FALSE, &dwSize);
  1559. if (FAILED(sc))
  1560. {
  1561. dwResult = (DWORD)sc;
  1562. CallbackTo16(gdata16Data.fnReleaseStgMedium16,
  1563. vpstgmedium16);
  1564. }
  1565. else if (lpstgmedium32->pUnkForRelease == NULL)
  1566. {
  1567. sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
  1568. dwSize, FALSE, pfe);
  1569. thkAssert(SUCCEEDED(sc));
  1570. }
  1571. }
  1572. if (FAILED(dwResult))
  1573. {
  1574. memset(lpstgmedium32, 0, sizeof(STGMEDIUM));
  1575. }
  1576. }
  1577. }
  1578. if (vpstgmedium16 != 0)
  1579. {
  1580. STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
  1581. }
  1582. return dwResult;
  1583. }
  1584. //+---------------------------------------------------------------------------
  1585. //
  1586. // Function: ConvertStatStg1632, public
  1587. //
  1588. // Synopsis: Converts a STATSTG
  1589. //
  1590. // Arguments: [pti] - Thunk info
  1591. // [vpss16] - STATSTG
  1592. // [pss32] - STATSTG
  1593. // [posPreAlloc] - Preallocated string memory or NULL
  1594. // [cchPreAlloc] - Amount preallocated
  1595. //
  1596. // Returns: Appropriate status code
  1597. //
  1598. // Modifies: [pss32]
  1599. //
  1600. // History: 14-May-94 DrewB Created
  1601. //
  1602. // Notes: Assumes input STATSTG memory is valid
  1603. // Assumes task memory for the string
  1604. //
  1605. //----------------------------------------------------------------------------
  1606. SCODE ConvertStatStg1632(THUNKINFO *pti,
  1607. VPVOID vpss16,
  1608. STATSTG *pss32,
  1609. LPOLESTR posPreAlloc,
  1610. UINT cchPreAlloc)
  1611. {
  1612. STATSTG UNALIGNED *pss16;
  1613. SCODE sc;
  1614. LPOLESTR pos32;
  1615. VPSTR vpstr;
  1616. pss16 = FIXVDMPTR(vpss16, STATSTG);
  1617. vpstr = (VPSTR)pss16->pwcsName;
  1618. RELVDMPTR(vpss16);
  1619. sc = ConvertTaskString1632(pti, vpstr,
  1620. posPreAlloc, cchPreAlloc,
  1621. &pos32);
  1622. if (SUCCEEDED(sc))
  1623. {
  1624. pss16 = FIXVDMPTR(vpss16, STATSTG);
  1625. memcpy(pss32, pss16, sizeof(STATSTG));
  1626. pss32->pwcsName = pos32;
  1627. RELVDMPTR(vpss16);
  1628. }
  1629. return sc;
  1630. }
  1631. //+---------------------------------------------------------------------------
  1632. //
  1633. // Function: Thop_STATSTG_3216, public
  1634. //
  1635. // Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
  1636. //
  1637. // Arguments: [pti] - Thunk state information
  1638. //
  1639. // Returns: Appropriate status code
  1640. //
  1641. // History: 23-Feb-94 BobDay Created
  1642. //
  1643. //----------------------------------------------------------------------------
  1644. DWORD Thop_STATSTG_3216( THUNKINFO *pti )
  1645. {
  1646. DWORD dwResult;
  1647. STATSTG *lpstatstg32;
  1648. VPVOID vpstatstg16;
  1649. LPOLESTR lpstr32;
  1650. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
  1651. //
  1652. // We currently don't have any input thops for STATSTGs
  1653. //
  1654. thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
  1655. "STATSTG must be output only" );
  1656. GET_STACK32(pti, lpstatstg32, STATSTG FAR *);
  1657. if (IsBadWritePtr(lpstatstg32, sizeof(STATSTG)))
  1658. {
  1659. return (DWORD)E_INVALIDARG;
  1660. }
  1661. vpstatstg16 = STACKALLOC16(sizeof(STATSTG));
  1662. if (vpstatstg16 == 0)
  1663. {
  1664. return (DWORD)E_OUTOFMEMORY;
  1665. }
  1666. lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
  1667. if (lpstr32 == NULL)
  1668. {
  1669. STACKFREE16(vpstatstg16, sizeof(STATSTG));
  1670. return (DWORD)E_OUTOFMEMORY;
  1671. }
  1672. TO_STACK16(pti, vpstatstg16, VPVOID);
  1673. pti->pThop++;
  1674. dwResult = EXECUTE_THOP3216(pti);
  1675. if (SUCCEEDED(dwResult))
  1676. {
  1677. SCODE sc;
  1678. sc = ConvertStatStg1632(pti, vpstatstg16, lpstatstg32,
  1679. lpstr32, CWCSTRINGPREALLOC);
  1680. if (FAILED(sc))
  1681. {
  1682. dwResult = sc;
  1683. }
  1684. }
  1685. if (FAILED(dwResult))
  1686. {
  1687. TaskFree32(lpstr32);
  1688. memset(lpstatstg32, 0, sizeof(STATSTG));
  1689. }
  1690. STACKFREE16(vpstatstg16, sizeof(STATSTG));
  1691. return dwResult;
  1692. }
  1693. //+---------------------------------------------------------------------------
  1694. //
  1695. // Function: Thop_DVTARGETDEVICE_3216, public
  1696. //
  1697. // Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
  1698. //
  1699. // Arguments: [pti] - Thunk state information
  1700. //
  1701. // Returns: Appropriate status code
  1702. //
  1703. // History: 23-Feb-94 BobDay Created
  1704. //
  1705. //----------------------------------------------------------------------------
  1706. DWORD Thop_DVTARGETDEVICE_3216( THUNKINFO *pti )
  1707. {
  1708. DWORD dwResult;
  1709. UINT uiSize;
  1710. DVTARGETDEVICE FAR *lpdv32;
  1711. VPVOID vpdv16;
  1712. SCODE sc;
  1713. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
  1714. //
  1715. // We currently don't have any output thops for DVTARGETDEVICEs
  1716. //
  1717. thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
  1718. "DVTARGETDEVICE must be input only" );
  1719. //
  1720. // Processing for a DVTARGETDEVICE FAR * as input
  1721. //
  1722. GET_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
  1723. vpdv16 = 0;
  1724. if ( lpdv32 != NULL )
  1725. {
  1726. sc = ConvertDvtd3216(pti, lpdv32, ArStack16, FrStack16, &vpdv16,
  1727. &uiSize);
  1728. if (FAILED(sc))
  1729. {
  1730. return (DWORD)sc;
  1731. }
  1732. }
  1733. TO_STACK16(pti, vpdv16, VPVOID);
  1734. pti->pThop++;
  1735. dwResult = EXECUTE_THOP3216(pti);
  1736. if ( lpdv32 != NULL )
  1737. {
  1738. FrStack16((void *)vpdv16, uiSize);
  1739. }
  1740. return dwResult;
  1741. }
  1742. //+---------------------------------------------------------------------------
  1743. //
  1744. // Function: Thop_FORMATETC_3216, public
  1745. //
  1746. // Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
  1747. //
  1748. // Arguments: [pti] - Thunk state information
  1749. //
  1750. // Returns: Appropriate status code
  1751. //
  1752. // History: 24-Feb-94 BobDay Created
  1753. //
  1754. //----------------------------------------------------------------------------
  1755. DWORD Thop_FORMATETC_3216( THUNKINFO *pti )
  1756. {
  1757. DWORD dwResult;
  1758. BOOL fThopInput;
  1759. BOOL fThopOutput;
  1760. VPVOID vpformatetc16;
  1761. FORMATETC16 UNALIGNED *lpformatetc16;
  1762. LPFORMATETC lpformatetc32;
  1763. VPVOID vpdv16;
  1764. SCODE sc;
  1765. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
  1766. fThopInput = IS_THOP_IN(pti);
  1767. fThopOutput = IS_THOP_OUT(pti);
  1768. vpdv16 = 0;
  1769. //
  1770. // We have only input or output thops
  1771. //
  1772. thkAssert( (fThopInput || fThopOutput) &&
  1773. (fThopInput != fThopOutput) &&
  1774. "formatetc must be input or output only" );
  1775. GET_STACK32(pti, lpformatetc32, LPFORMATETC);
  1776. if ( lpformatetc32 == NULL )
  1777. {
  1778. vpformatetc16 = 0;
  1779. }
  1780. else
  1781. {
  1782. if ((fThopInput && IsBadReadPtr(lpformatetc32, sizeof(LPFORMATETC))) ||
  1783. (fThopOutput && IsBadWritePtr(lpformatetc32, sizeof(LPFORMATETC))))
  1784. {
  1785. return (DWORD)E_INVALIDARG;
  1786. }
  1787. vpformatetc16 = STACKALLOC16(sizeof(FORMATETC16));
  1788. if (vpformatetc16 == 0)
  1789. {
  1790. return (DWORD)E_OUTOFMEMORY;
  1791. }
  1792. if ( fThopInput )
  1793. {
  1794. sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, FALSE);
  1795. if (FAILED(sc))
  1796. {
  1797. STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
  1798. return (DWORD)sc;
  1799. }
  1800. }
  1801. else
  1802. {
  1803. thkAssert( fThopOutput );
  1804. //
  1805. // The below memset is needed at least for the DATA_S_SAMEFORMATETC
  1806. // case. This allows it to be cleaned up because all its pointers
  1807. // will be null.
  1808. //
  1809. lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
  1810. memset(lpformatetc16, 0, sizeof(FORMATETC16) );
  1811. RELVDMPTR(vpformatetc16);
  1812. }
  1813. }
  1814. TO_STACK16(pti, vpformatetc16, VPVOID);
  1815. pti->pThop++;
  1816. dwResult = EXECUTE_THOP3216(pti);
  1817. if (fThopInput && vpformatetc16 != 0)
  1818. {
  1819. VPVOID vptd;
  1820. lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
  1821. vptd = (VPVOID)lpformatetc16->ptd;
  1822. RELVDMPTR(vpformatetc16);
  1823. if (vptd != 0)
  1824. {
  1825. TaskFree16(vptd);
  1826. }
  1827. }
  1828. if ( fThopOutput && lpformatetc32 != NULL)
  1829. {
  1830. if (SUCCEEDED(dwResult))
  1831. {
  1832. sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, TRUE);
  1833. if (FAILED(sc))
  1834. {
  1835. dwResult = sc;
  1836. }
  1837. }
  1838. if (FAILED(dwResult))
  1839. {
  1840. memset(lpformatetc32, 0, sizeof(FORMATETC));
  1841. }
  1842. }
  1843. if (vpformatetc16 != 0)
  1844. {
  1845. STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
  1846. }
  1847. return dwResult;
  1848. }
  1849. //+---------------------------------------------------------------------------
  1850. //
  1851. // Function: Thop_LOGPALETTE_3216, public
  1852. //
  1853. // Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
  1854. // and converts 32-bit LOGPALETTE returned to 16-bit structure
  1855. //
  1856. // Arguments: [pti] - Thunk state information
  1857. //
  1858. // Returns: Appropriate status code
  1859. //
  1860. // History: 23-Feb-94 BobDay Created
  1861. //
  1862. //----------------------------------------------------------------------------
  1863. DWORD Thop_LOGPALETTE_3216 ( THUNKINFO *pti )
  1864. {
  1865. DWORD dwResult;
  1866. UINT uiSize;
  1867. LPLOGPALETTE lplogpal32;
  1868. VPVOID vplogpal16;
  1869. LOGPALETTE UNALIGNED *lplogpal16;
  1870. LPLOGPALETTE *lplplogpal32;
  1871. VPVOID vpvplogpal16;
  1872. VPVOID UNALIGNED *lpvplogpal16;
  1873. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
  1874. //
  1875. // It must be either an input or output LOGPALETTE
  1876. //
  1877. thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
  1878. (*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
  1879. "Hey, LOGPALETTE can't be input and output!" );
  1880. if ( (*pti->pThop & THOP_IN) != 0 )
  1881. {
  1882. //
  1883. // Processing for a LPLOGPALETTE as input
  1884. //
  1885. GET_STACK32(pti, lplogpal32, LPLOGPALETTE);
  1886. if ( lplogpal32 == NULL )
  1887. {
  1888. vplogpal16 = 0;
  1889. }
  1890. else
  1891. {
  1892. if (IsBadReadPtr(lplogpal32, sizeof(LOGPALETTE)))
  1893. {
  1894. return (DWORD)E_INVALIDARG;
  1895. }
  1896. uiSize = CBPALETTE(lplogpal32->palNumEntries);
  1897. if (IsBadReadPtr(lplogpal32, uiSize))
  1898. {
  1899. return (DWORD)E_INVALIDARG;
  1900. }
  1901. vplogpal16 = STACKALLOC16(uiSize);
  1902. if (vplogpal16 == 0)
  1903. {
  1904. return (DWORD)E_OUTOFMEMORY;
  1905. }
  1906. lplogpal16 = (LOGPALETTE UNALIGNED *)
  1907. WOWFIXVDMPTR( vplogpal16, uiSize );
  1908. memcpy( lplogpal16, lplogpal32, uiSize );
  1909. WOWRELVDMPTR(vplogpal16);
  1910. }
  1911. TO_STACK16(pti, vplogpal16, VPVOID);
  1912. pti->pThop++;
  1913. dwResult = EXECUTE_THOP3216(pti);
  1914. if ( vplogpal16 != 0 )
  1915. {
  1916. STACKFREE16(vplogpal16, uiSize);
  1917. }
  1918. }
  1919. else
  1920. {
  1921. //
  1922. // Processing for LPLPLOGPALETTE as output
  1923. //
  1924. thkAssert((*pti->pThop & THOP_OUT) != 0);
  1925. GET_STACK32(pti, lplplogpal32, LPLOGPALETTE FAR *);
  1926. if (IsBadWritePtr(lplplogpal32, sizeof(LPLOGPALETTE)))
  1927. {
  1928. return (DWORD)E_INVALIDARG;
  1929. }
  1930. vpvplogpal16 = (VPVOID)STACKALLOC16(sizeof(LPLOGPALETTE));
  1931. if (vpvplogpal16 == 0)
  1932. {
  1933. return (DWORD)E_OUTOFMEMORY;
  1934. }
  1935. lplogpal32 = (LPLOGPALETTE)TaskMalloc32(CBPALETTE(NPALETTEPREALLOC));
  1936. if (lplogpal32 == NULL)
  1937. {
  1938. STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
  1939. return (DWORD)E_OUTOFMEMORY;
  1940. }
  1941. //
  1942. // We DO need to zero out the pointer on the way in.
  1943. //
  1944. *FIXVDMPTR(vpvplogpal16, LPLOGPALETTE) = 0;
  1945. RELVDMPTR(vpvplogpal16);
  1946. TO_STACK16(pti, vpvplogpal16, VPVOID);
  1947. pti->pThop++;
  1948. dwResult = EXECUTE_THOP3216(pti);
  1949. if (SUCCEEDED(dwResult))
  1950. {
  1951. lpvplogpal16 = FIXVDMPTR( vpvplogpal16, VPVOID);
  1952. vplogpal16 = *lpvplogpal16;
  1953. RELVDMPTR(vpvplogpal16);
  1954. if ( vplogpal16 == 0 )
  1955. {
  1956. TaskFree32(lplogpal32);
  1957. lplogpal32 = NULL;
  1958. }
  1959. else
  1960. {
  1961. lplogpal16 = FIXVDMPTR( vplogpal16, LOGPALETTE );
  1962. //
  1963. // Copy the returned LOGPALETTE into 16-bit memory
  1964. //
  1965. uiSize = CBPALETTE(lplogpal16->palNumEntries);
  1966. if (uiSize > CBPALETTE(NPALETTEPREALLOC))
  1967. {
  1968. TaskFree32(lplogpal32);
  1969. lplogpal32 = (LPLOGPALETTE)TaskMalloc32(uiSize);
  1970. if ( lplogpal32 == NULL )
  1971. {
  1972. dwResult = (DWORD)E_OUTOFMEMORY;
  1973. }
  1974. }
  1975. if (lplogpal32 != NULL)
  1976. {
  1977. memcpy( lplogpal32, lplogpal16, uiSize );
  1978. }
  1979. RELVDMPTR(vplogpal16);
  1980. TaskFree16( vplogpal16 );
  1981. }
  1982. }
  1983. else
  1984. {
  1985. TaskFree32(lplogpal32);
  1986. lplogpal32 = NULL;
  1987. }
  1988. //
  1989. // Update the value pointed to by the parameter on the 16-bit stack
  1990. //
  1991. *lplplogpal32 = lplogpal32;
  1992. if (vpvplogpal16 != 0)
  1993. {
  1994. STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
  1995. }
  1996. }
  1997. return dwResult;
  1998. }
  1999. //+---------------------------------------------------------------------------
  2000. //
  2001. // Function: Thop_CRGIID_3216, public
  2002. //
  2003. // Synopsis: Converts 32-bit CRGIID to 16-bit CRGIID structure
  2004. //
  2005. // Arguments: [pti] - Thunk state information
  2006. //
  2007. // Returns: Appropriate status code
  2008. //
  2009. // History: 23-Feb-94 BobDay Created
  2010. //
  2011. //----------------------------------------------------------------------------
  2012. DWORD Thop_CRGIID_3216( THUNKINFO *pti )
  2013. {
  2014. DWORD dwResult;
  2015. DWORD dwCount;
  2016. VPVOID vpiid16;
  2017. IID UNALIGNED *lpiid16;
  2018. IID *lpiid32;
  2019. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
  2020. //
  2021. // We currently don't have any output thops for CRGIIDs
  2022. //
  2023. thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
  2024. "CRGIID must be unmodified only" );
  2025. GET_STACK32(pti, dwCount, DWORD);
  2026. GET_STACK32(pti, lpiid32, IID FAR *);
  2027. if ( lpiid32 == NULL )
  2028. {
  2029. vpiid16 = 0;
  2030. }
  2031. else
  2032. {
  2033. if (IsBadReadPtr(lpiid32, dwCount*sizeof(IID)))
  2034. {
  2035. return (DWORD)E_INVALIDARG;
  2036. }
  2037. vpiid16 = STACKALLOC16( dwCount * sizeof(IID) );
  2038. if (vpiid16 == 0)
  2039. {
  2040. return (DWORD)E_OUTOFMEMORY;
  2041. }
  2042. lpiid16 = (IID UNALIGNED *)
  2043. WOWFIXVDMPTR( vpiid16, dwCount*sizeof(IID) );
  2044. memcpy( lpiid16, lpiid32, dwCount*sizeof(IID) );
  2045. WOWRELVDMPTR(vpiid16);
  2046. }
  2047. TO_STACK16(pti, dwCount, DWORD);
  2048. TO_STACK16(pti, vpiid16, VPVOID);
  2049. pti->pThop++;
  2050. dwResult = EXECUTE_THOP3216(pti);
  2051. if ( vpiid16 != 0 )
  2052. {
  2053. STACKFREE16( vpiid16, dwCount * sizeof(IID) );
  2054. }
  2055. return( dwResult );
  2056. }
  2057. //+---------------------------------------------------------------------------
  2058. //
  2059. // Function: Thop_INTERFACEINFO_3216, public
  2060. //
  2061. // Synopsis: Converts an INTERFACEINFO
  2062. //
  2063. // Arguments: [pti] - Thunking state information
  2064. //
  2065. // Returns: Appropriate status code
  2066. //
  2067. // History: 19-May-94 DrewB Created
  2068. //
  2069. //----------------------------------------------------------------------------
  2070. DWORD Thop_INTERFACEINFO_3216(THUNKINFO *pti)
  2071. {
  2072. INTERFACEINFO *pii32;
  2073. INTERFACEINFO16 UNALIGNED *pii16;
  2074. VPVOID vpii16;
  2075. DWORD dwResult;
  2076. VPVOID vpunk16;
  2077. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
  2078. thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
  2079. vpunk16 = 0;
  2080. GET_STACK32(pti, pii32, INTERFACEINFO *);
  2081. if (pii32 == NULL)
  2082. {
  2083. vpii16 = 0;
  2084. }
  2085. else
  2086. {
  2087. if (IsBadReadPtr(pii32, sizeof(INTERFACEINFO)))
  2088. {
  2089. return (DWORD)E_INVALIDARG;
  2090. }
  2091. vpii16 = STACKALLOC16(sizeof(INTERFACEINFO16));
  2092. if (vpii16 == 0)
  2093. {
  2094. return (DWORD)E_OUTOFMEMORY;
  2095. }
  2096. if (pii32->pUnk != NULL)
  2097. {
  2098. vpunk16 = pti->pThkMgr->FindProxy1632(NULL, pii32->pUnk, NULL,
  2099. INDEX_IIDIDX(THI_IUnknown),
  2100. NULL);
  2101. if (vpunk16 == 0)
  2102. {
  2103. STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
  2104. return (DWORD)E_OUTOFMEMORY;
  2105. }
  2106. }
  2107. pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
  2108. pii16->pUnk = vpunk16;
  2109. pii16->iid = pii32->iid;
  2110. pii16->wMethod = pii32->wMethod;
  2111. thkDebugOut((DEB_ARGS,
  2112. "In3216 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
  2113. pii32, vpii16, pii16->pUnk, pii32->pUnk,
  2114. IidOrInterfaceString(&pii16->iid), pii16->wMethod));
  2115. RELVDMPTR(vpii16);
  2116. }
  2117. TO_STACK16(pti, vpii16, VPVOID);
  2118. pti->pThop++;
  2119. dwResult = EXECUTE_THOP3216(pti);
  2120. if (vpunk16 != 0)
  2121. {
  2122. // Release the 16-bit interface as it is an IN parameter
  2123. ReleaseOnObj16(vpunk16);
  2124. }
  2125. if (vpii16 != 0)
  2126. {
  2127. STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
  2128. }
  2129. return dwResult;
  2130. }
  2131. //+---------------------------------------------------------------------------
  2132. //
  2133. // Function: Thop_RETURNTYPE_3216, public
  2134. //
  2135. // Synopsis: Thunks the return value of a call
  2136. //
  2137. // Arguments: [pti] - Thunk state information
  2138. //
  2139. // Returns: Appropriate status code
  2140. //
  2141. // History: 24-Feb-94 DrewB Created
  2142. //
  2143. // Notes: This thunk assumes that the return value will always fit
  2144. // in 32 bits and that the thops for it are only one thop
  2145. // long. This fits the existing APIs and methods
  2146. //
  2147. //----------------------------------------------------------------------------
  2148. DWORD Thop_RETURNTYPE_3216(THUNKINFO *pti)
  2149. {
  2150. THOP thops[2];
  2151. DWORD dwResult;
  2152. THUNK3216OBJ *ptoPreAlloc = NULL;
  2153. IIDIDX iidx;
  2154. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RETURNTYPE);
  2155. thkAssert((*pti->pThop & THOP_IOMASK) == 0);
  2156. pti->fResultThunked = TRUE;
  2157. pti->pThop++;
  2158. // Remember return type thop
  2159. thops[0] = *pti->pThop++;
  2160. if ((thops[0] & THOP_OPMASK) == THOP_COPY ||
  2161. (thops[0] & THOP_OPMASK) == THOP_IFACE ||
  2162. (thops[0] & THOP_OPMASK) == THOP_ALIAS32)
  2163. {
  2164. thops[1] = *pti->pThop++;
  2165. }
  2166. // Preallocate any necessary resources
  2167. switch(thops[0])
  2168. {
  2169. case THOP_IFACE | THOP_IN:
  2170. iidx = INDEX_IIDIDX(thops[1]);
  2171. if ((ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx)) == NULL)
  2172. {
  2173. return (DWORD)E_OUTOFMEMORY;
  2174. }
  2175. break;
  2176. }
  2177. dwResult = EXECUTE_THOP3216(pti);
  2178. // Now that we have the return value thunk it from 16->32
  2179. switch(thops[0])
  2180. {
  2181. case THOP_COPY:
  2182. // Only handle DWORD copies
  2183. thkAssert(thops[1] == sizeof(DWORD));
  2184. break;
  2185. case THOP_SHORTLONG:
  2186. // For boolean results, not necessary to clamp
  2187. dwResult = (DWORD)(LONG)*(SHORT *)&dwResult;
  2188. break;
  2189. case THOP_IFACE | THOP_IN:
  2190. // Thunking an interface as a return value is completly broken
  2191. // First, such an interface needs to be thunked as an OUT parameter
  2192. // which I am fixing below. Second, the IID of the interface being
  2193. // thunked needs to be in the THOP string for proper thunking of
  2194. // interface. The only known case where an interface is returned
  2195. // is IRpcStubBuffer::IsIIDSupported() and the interface returned
  2196. // is of type IRpcStubBuffer, not IUnknown. As this method is not
  2197. // used in the curremt COM code, I am not changing THOP strings
  2198. // to reflect the IID of the interface being thunked
  2199. // Gopalk Mar 27, 97
  2200. if (dwResult != 0)
  2201. {
  2202. // BUGBUG - What if another thop failed and returned an HRESULT?
  2203. // This will break
  2204. VPVOID vpvUnk = (VPVOID) dwResult;
  2205. dwResult =
  2206. (DWORD)pti->pThkMgr->FindProxy3216(ptoPreAlloc, dwResult, NULL,
  2207. iidx, FALSE, NULL);
  2208. // Release actual interface as it is an OUT parameter
  2209. // This could be the last release on the interface if the
  2210. // above call failed;
  2211. ReleaseOnObj16(vpvUnk);
  2212. thkAssert(dwResult);
  2213. thkDebugOut((DEB_ARGS, "Ret3216 %s %p\n",
  2214. inInterfaceNames[thops[1]].pszInterface,
  2215. dwResult));
  2216. }
  2217. else
  2218. {
  2219. pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
  2220. }
  2221. break;
  2222. default:
  2223. thkAssert(!"Unhandled 3216 return type");
  2224. break;
  2225. }
  2226. return dwResult;
  2227. }
  2228. //+---------------------------------------------------------------------------
  2229. //
  2230. // Function: Thop_IFACE_3216, public
  2231. //
  2232. // Synopsis: Thunks a known interface pointer
  2233. //
  2234. // Arguments: [pti] - Thunk state information
  2235. //
  2236. // Returns: Appropriate status code
  2237. //
  2238. // History: 24-Feb-94 DrewB Created
  2239. //
  2240. //----------------------------------------------------------------------------
  2241. DWORD Thop_IFACE_3216(THUNKINFO *pti)
  2242. {
  2243. IIDIDX iidx;
  2244. THOP thop, thopOp, thopWeakOffset;
  2245. VPVOID vpvOuter;
  2246. thop = *pti->pThop++;
  2247. thopOp = thop & THOP_OPMASK;
  2248. thkAssert( thopOp == THOP_IFACE
  2249. || thopOp == THOP_IFACEOWNER
  2250. || thopOp == THOP_IFACECLEAN
  2251. || thopOp == THOP_UNKOUTER);
  2252. iidx = INDEX_IIDIDX(*pti->pThop++);
  2253. // There's a bit of a special case here in that IMalloc is
  2254. // not thunked so it doesn't have a real index but it's used
  2255. // in thop strings so it has a fake index to function as a placeholder
  2256. // The fake index is THI_COUNT so allow that in the assert
  2257. thkAssert(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) <= THI_COUNT);
  2258. thkAssert(thopOp != THOP_UNKOUTER || iidx == THI_IUnknown);
  2259. vpvOuter = 0;
  2260. if (thopOp == THOP_IFACEOWNER)
  2261. {
  2262. // Obtain the outer unknown that is being passed to the 16 bit world
  2263. thopWeakOffset = *pti->pThop++;
  2264. INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
  2265. if(vpvOuter) {
  2266. // Aggregation across 32-16 boundary
  2267. // Assert invariants
  2268. thkAssert(iidx == THI_IRpcProxyBuffer || iidx == THI_IRpcProxy);
  2269. // Change thop to indicate that inner unknown is being thunked
  2270. thop = (thop & THOP_IOMASK) | THOP_UNKINNER;
  2271. }
  2272. }
  2273. return ThunkInterface3216(pti, iidx, thop, vpvOuter);
  2274. }
  2275. //+---------------------------------------------------------------------------
  2276. //
  2277. // Function: Thop_ALIAS32_3216, public
  2278. //
  2279. // Synopsis: Handles 16-bit aliases to 32-bit quantities
  2280. //
  2281. // Arguments: [pti] - Thunking state information
  2282. //
  2283. // Returns: Appropriate status code
  2284. //
  2285. // History: 27-May-94 DrewB Created
  2286. //
  2287. //----------------------------------------------------------------------------
  2288. DWORD Thop_ALIAS32_3216(THUNKINFO *pti)
  2289. {
  2290. ALIAS alias;
  2291. DWORD dwValue;
  2292. THOP thopAction;
  2293. BOOL fTemporary = FALSE;
  2294. DWORD dwResult;
  2295. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
  2296. thkAssert((*pti->pThop & THOP_IOMASK) == 0);
  2297. pti->pThop++;
  2298. GET_STACK32(pti, dwValue, DWORD);
  2299. // Second byte indicates how the alias should be handled
  2300. thopAction = *pti->pThop++;
  2301. if (dwValue != 0)
  2302. {
  2303. switch(thopAction)
  2304. {
  2305. case ALIAS_RESOLVE:
  2306. alias = gAliases32.ValueAlias(dwValue);
  2307. // There may be cases where there is no existing alias
  2308. // for a value (for example, remoted SetMenu calls where
  2309. // the HOLEMENU is a temporary RPC object)
  2310. // so create a temporary one
  2311. if (alias == INVALID_ALIAS)
  2312. {
  2313. alias = gAliases32.AddValue(dwValue);
  2314. if (alias == INVALID_ALIAS)
  2315. {
  2316. return (DWORD)E_OUTOFMEMORY;
  2317. }
  2318. fTemporary = TRUE;
  2319. }
  2320. break;
  2321. default:
  2322. thkAssert(!"Default hit in Thop_ALIAS32_3216");
  2323. alias = 0;
  2324. break;
  2325. }
  2326. }
  2327. else
  2328. {
  2329. alias = 0;
  2330. }
  2331. thkDebugOut((DEB_ARGS, "In3216 ALIAS32: 0x%08lX -> 0x%04X\n",
  2332. dwValue, alias));
  2333. TO_STACK16(pti, alias, ALIAS);
  2334. dwResult = EXECUTE_THOP3216(pti);
  2335. if (fTemporary)
  2336. {
  2337. gAliases32.RemoveAlias(alias);
  2338. }
  2339. return dwResult;
  2340. }
  2341. //+---------------------------------------------------------------------------
  2342. //
  2343. // Function: Thop_RPCOLEMESSAGE_3216, public
  2344. //
  2345. // Synopsis: Converts 32-bit RPCOLEMESSAGE to 16-bit RPCOLEMESSAGE
  2346. //
  2347. // Arguments: [pti] - Thunk state information
  2348. //
  2349. // Returns: Appropriate status code
  2350. //
  2351. // History: 23-Feb-94 JohannP Created
  2352. //
  2353. //----------------------------------------------------------------------------
  2354. DWORD Thop_RPCOLEMESSAGE_3216( THUNKINFO *pti )
  2355. {
  2356. DWORD dwResult;
  2357. PRPCOLEMESSAGE prom32;
  2358. VPVOID vprom16;
  2359. RPCOLEMESSAGE UNALIGNED *prom16;
  2360. VPVOID vpvBuffer16;
  2361. LPVOID lp16;
  2362. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
  2363. //
  2364. // We currently have only IN/OUT RPCOLEMESSAGE
  2365. //
  2366. thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
  2367. "RPCOLEMESSAGE must be input/output only" );
  2368. vprom16 = 0;
  2369. vpvBuffer16 = 0;
  2370. //
  2371. // Processing for a RPCOLEMESSAGE FAR * as input/output
  2372. //
  2373. GET_STACK32(pti, prom32, RPCOLEMESSAGE *);
  2374. if ( prom32 != 0 )
  2375. {
  2376. // Copy over the input RPCOLEMESSAGE structure
  2377. vprom16 = STACKALLOC16(sizeof(RPCOLEMESSAGE));
  2378. if (vprom16 == NULL)
  2379. {
  2380. return (DWORD)E_OUTOFMEMORY;
  2381. }
  2382. prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
  2383. *prom16 = *prom32;
  2384. ROM_THUNK_FIELD(prom16) = (void *)prom32;
  2385. RELVDMPTR(vprom16);
  2386. // If there's a buffer, copy it
  2387. if (prom32->cbBuffer != 0)
  2388. {
  2389. vpvBuffer16 = TaskMalloc16(prom32->cbBuffer);
  2390. if (vpvBuffer16 == NULL)
  2391. {
  2392. STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
  2393. return (DWORD)E_OUTOFMEMORY;
  2394. }
  2395. prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
  2396. prom16->Buffer = (LPVOID) vpvBuffer16;
  2397. lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer16, prom32->cbBuffer);
  2398. memcpy( lp16, prom32->Buffer, prom32->cbBuffer );
  2399. WOWRELVDMPTR(vpvBuffer16);
  2400. RELVDMPTR(vprom16);
  2401. }
  2402. }
  2403. TO_STACK16(pti, vprom16, VPVOID);
  2404. pti->pThop++;
  2405. dwResult = EXECUTE_THOP3216(pti);
  2406. prom16 = (PRPCOLEMESSAGE)FIXVDMPTR(vprom16, RPCOLEMESSAGE);
  2407. if (prom16 == NULL)
  2408. {
  2409. dwResult = (DWORD)E_UNEXPECTED;
  2410. }
  2411. else
  2412. {
  2413. VPVOID vpvBuffer;
  2414. vpvBuffer = (VPVOID)prom16->Buffer;
  2415. RELVDMPTR(vprom16);
  2416. if (SUCCEEDED(dwResult))
  2417. {
  2418. if ( prom32->Buffer != NULL )
  2419. {
  2420. lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer, prom16->cbBuffer);
  2421. if (lp16 == NULL)
  2422. {
  2423. dwResult = (DWORD)E_UNEXPECTED;
  2424. }
  2425. else
  2426. {
  2427. memcpy( prom32->Buffer, lp16, prom16->cbBuffer );
  2428. WOWRELVDMPTR(vpvBuffer);
  2429. }
  2430. }
  2431. }
  2432. if ( vpvBuffer16 != 0 )
  2433. {
  2434. // We'd better have a buffer at this point
  2435. thkAssert( vpvBuffer != 0);
  2436. // Free up the buffer that we've been dealing with
  2437. TaskFree16(vpvBuffer);
  2438. }
  2439. }
  2440. if ( vprom16 != 0 )
  2441. {
  2442. STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
  2443. }
  2444. return dwResult;
  2445. }
  2446. //+---------------------------------------------------------------------------
  2447. //
  2448. // Function: Thop_ENUM_3216, public
  2449. //
  2450. // Synopsis: Thunks Enum::Next parameters
  2451. //
  2452. // Arguments: [pti] - Thunk state information
  2453. //
  2454. // Returns: Appropriate status code
  2455. //
  2456. // History: 1-Mar-94 BobDay Created
  2457. //
  2458. // Notes: This thunk is the start of a 2-byte thop. The next thop
  2459. // byte references a function in the enumerator table, rather
  2460. // than the standard thop table.
  2461. //
  2462. //----------------------------------------------------------------------------
  2463. DWORD Thop_ENUM_3216(THUNKINFO *pti)
  2464. {
  2465. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
  2466. thkAssert((*pti->pThop & THOP_IOMASK) == 0);
  2467. //
  2468. // Get then next thop byte and execute it as a Enum thop
  2469. //
  2470. pti->pThop++;
  2471. return EXECUTE_ENUMTHOP3216(pti);
  2472. }
  2473. //+---------------------------------------------------------------------------
  2474. //
  2475. // Function: CallbackProcessing_3216, public
  2476. //
  2477. // Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
  2478. //
  2479. // Arguments: [pti] - Thunk state information
  2480. //
  2481. // Returns: Appropriate status code
  2482. //
  2483. // History: 3-Mar-94 BobDay Created
  2484. //
  2485. //----------------------------------------------------------------------------
  2486. typedef struct tagCallbackControl
  2487. {
  2488. DWORD dwContinue;
  2489. LPVOID lpfn32;
  2490. } CALLBACKCONTROL;
  2491. STDAPI_(BOOL) CallbackProcessing_3216( DWORD dwContinue, DWORD dw1, DWORD dw2 )
  2492. {
  2493. BOOL fResult;
  2494. CALLBACKCONTROL *lpcbc;
  2495. BOOL (*lpfn32)(DWORD);
  2496. lpcbc = (CALLBACKCONTROL *)dwContinue;
  2497. lpfn32 = (BOOL (*)(DWORD))lpcbc->lpfn32;
  2498. fResult = (*lpfn32)(lpcbc->dwContinue);
  2499. if ( fResult ) // This maps DWORD sized BOOLs into WORD sized BOOLs
  2500. {
  2501. return TRUE;
  2502. }
  2503. else
  2504. {
  2505. return FALSE;
  2506. }
  2507. }
  2508. //+---------------------------------------------------------------------------
  2509. //
  2510. // Function: Thop_CALLBACK_3216, public
  2511. //
  2512. // Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
  2513. //
  2514. // Arguments: [pti] - Thunk state information
  2515. //
  2516. // Returns: Appropriate status code
  2517. //
  2518. // History: 3-Mar-94 BobDay Created
  2519. //
  2520. //----------------------------------------------------------------------------
  2521. DWORD Thop_CALLBACK_3216(THUNKINFO *pti)
  2522. {
  2523. LPVOID lpfn32;
  2524. DWORD dwContinue;
  2525. CALLBACKCONTROL cbc;
  2526. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
  2527. thkAssert((*pti->pThop & THOP_IOMASK) == 0);
  2528. GET_STACK32(pti, lpfn32, LPVOID);
  2529. GET_STACK32(pti, dwContinue, DWORD);
  2530. if ( lpfn32 == 0 )
  2531. {
  2532. TO_STACK16(pti, NULL, VPVOID);
  2533. TO_STACK16(pti, dwContinue, DWORD);
  2534. }
  2535. else
  2536. {
  2537. cbc.lpfn32 = lpfn32;
  2538. cbc.dwContinue = dwContinue;
  2539. TO_STACK16(pti, gdata16Data.fnCallbackHandler, DWORD);
  2540. TO_STACK16(pti, (DWORD)&cbc, DWORD);
  2541. }
  2542. pti->pThop++;
  2543. return EXECUTE_THOP3216(pti);
  2544. }
  2545. //+---------------------------------------------------------------------------
  2546. //
  2547. // Function: Thop_CLSCONTEXT_3216, public
  2548. //
  2549. // Synopsis: Converts a class context flags DWORD
  2550. //
  2551. // Arguments: [pti] - Thunk state information
  2552. //
  2553. // Returns: Appropriate status code
  2554. //
  2555. // History: 29-Jun-94 DrewB Created
  2556. //
  2557. //----------------------------------------------------------------------------
  2558. DWORD Thop_CLSCONTEXT_3216(THUNKINFO *pti)
  2559. {
  2560. DWORD dwClsContext;
  2561. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
  2562. thkAssert((*pti->pThop & THOP_IOMASK) == 0);
  2563. // When passing a 32-bit class context to 16-bits nothing
  2564. // nothing special needs to be done
  2565. GET_STACK32(pti, dwClsContext, DWORD);
  2566. TO_STACK16(pti, dwClsContext, DWORD);
  2567. pti->pThop++;
  2568. return EXECUTE_THOP3216(pti);
  2569. }
  2570. //+---------------------------------------------------------------------------
  2571. //
  2572. // Function: Thop_FILENAME_3216, public
  2573. //
  2574. // Synopsis: Converts a filename string
  2575. //
  2576. // Arguments: [pti] - Thunk state information
  2577. //
  2578. // Returns: Appropriate status code
  2579. //
  2580. // History: 24-Aug-94 DrewB Created
  2581. //
  2582. //----------------------------------------------------------------------------
  2583. DWORD Thop_FILENAME_3216(THUNKINFO *pti)
  2584. {
  2585. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
  2586. // Can be in or out only
  2587. thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
  2588. (*pti->pThop & THOP_IOMASK) == THOP_OUT);
  2589. if ((*pti->pThop & THOP_IN) != 0)
  2590. {
  2591. // Convert filenames going from 32->16 to short filenames
  2592. // to avoid any possible problems with non-8.3 names.
  2593. return ThunkInString3216(pti, TRUE, 0);
  2594. }
  2595. else
  2596. {
  2597. thkAssert((*pti->pThop & THOP_OUT) != 0);
  2598. // No special processing is necessary for filenames going
  2599. // from 16->32 since it isn't possible for 16-bit code to
  2600. // generate a filename which can't be handled in 32-bits
  2601. return ThunkOutString3216(pti);
  2602. }
  2603. }
  2604. //+---------------------------------------------------------------------------
  2605. //
  2606. // Function: Thop_SIZEDSTRING_3216, public
  2607. //
  2608. // Synopsis: Converts strings which cannot exceed a given length
  2609. //
  2610. // Arguments: [pti] - Thunk state information
  2611. //
  2612. // Returns: Appropriate status code
  2613. //
  2614. // History: 02-Sep-94 DrewB Created
  2615. //
  2616. //----------------------------------------------------------------------------
  2617. DWORD Thop_SIZEDSTRING_3216(THUNKINFO *pti)
  2618. {
  2619. thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
  2620. thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
  2621. // Advance once to account for the length byte
  2622. // ThunkInString will advance again
  2623. pti->pThop++;
  2624. return ThunkInString3216(pti, FALSE, *pti->pThop);
  2625. }
  2626. #define THOP_FN(x) Thop_ ## x ## _3216
  2627. DWORD (* CONST aThopFunctions3216[])(THUNKINFO *) =
  2628. {
  2629. // x = Implemented
  2630. // ? = Mysteriously not needed
  2631. // = Left to do
  2632. //
  2633. // ^
  2634. // |
  2635. // +===+
  2636. // |
  2637. // v
  2638. //
  2639. ThunkCall3216, // x Terminating THOP
  2640. Thop_ShortToLong_3216, // x SHORTLONG
  2641. Thop_WordToDword_3216, // x WORDDWORD
  2642. Thop_Copy_3216, // x COPY
  2643. THOP_FN(LPSTR), // x LPSTR
  2644. THOP_FN(LPLPSTR), // x LPLPSTR
  2645. THOP_FN(BUFFER), // x BUFFER
  2646. Thop_UserHandle_3216, // x HUSER
  2647. Thop_GdiHandle_3216, // x HGDI
  2648. THOP_FN(SIZE), // x SIZE
  2649. THOP_FN(RECT), // x RECT
  2650. THOP_FN(MSG), // x MSG
  2651. THOP_FN(HRESULT), // x HRESULT
  2652. THOP_FN(STATSTG), // x STATSTG
  2653. THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
  2654. THOP_FN(STGMEDIUM), // x STGMEDIUM
  2655. THOP_FN(FORMATETC), // x FORMATETC
  2656. THOP_FN(HACCEL), // x HACCEL
  2657. THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
  2658. THOP_FN(BINDOPTS), // x BIND_OPTS
  2659. THOP_FN(LOGPALETTE), // x LOGPALETTE
  2660. THOP_FN(SNB), // x SNB
  2661. THOP_FN(CRGIID), // x CRGIID
  2662. Thop_ERROR_3216, // x OLESTREAM (only 16-bit)
  2663. THOP_FN(HTASK), // x HTASK
  2664. THOP_FN(INTERFACEINFO), // x INTERFACEINFO
  2665. THOP_FN(IFACE), // x IFACE
  2666. THOP_FN(IFACE), // x IFACEOWNER
  2667. THOP_FN(IFACE), // x IFACENOADDREF
  2668. THOP_FN(IFACE), // x IFACECLEAN
  2669. THOP_FN(IFACEGEN), // x IFACEGEN
  2670. THOP_FN(IFACEGEN), // x IFACEGENOWNER
  2671. THOP_FN(IFACE), // x UNKOUTER
  2672. Thop_ERROR_3216, // x UNKINNER
  2673. Thop_ERROR_3216, // x ROUTINE_INDEX
  2674. THOP_FN(RETURNTYPE), // x RETURN_TYPE
  2675. THOP_FN(NULL), // x NULL
  2676. Thop_ERROR_3216, // x ERROR
  2677. THOP_FN(ENUM), // x ENUM
  2678. THOP_FN(CALLBACK), // x CALLBACK
  2679. THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
  2680. THOP_FN(ALIAS32), // x ALIAS32
  2681. THOP_FN(CLSCONTEXT), // x CLSCONTEXT
  2682. THOP_FN(FILENAME), // x FILENAME
  2683. THOP_FN(SIZEDSTRING), // x SIZEDSTRING
  2684. };
  2685. //+---------------------------------------------------------------------------
  2686. //
  2687. // Function: General_Enum_3216, private
  2688. //
  2689. // Synopsis: Thunking for standard OLE enumerator interface ::Next member
  2690. // function.
  2691. //
  2692. // Arguments: [pti] - Thunk state information
  2693. // [uiSize32] - 32-bit information size
  2694. // [uiSize16] - 16-bit information size
  2695. // [pfnCallback] - Data thunking callback
  2696. // [pfnCleanup] - Thunking cleanup
  2697. //
  2698. // Returns: Appropriate status code
  2699. //
  2700. // History: 1-Mar-94 BobDay Created
  2701. //
  2702. // Notes: This handler is called from many IXXXEnum::Next handlers thop
  2703. // thunks to do the standard sorts of "buffer of structures"
  2704. // processing.
  2705. //
  2706. //----------------------------------------------------------------------------
  2707. #define MAX_ALLOCA_STRUCT 5 // 16-bit stacks are precious
  2708. DWORD General_Enum_3216(
  2709. THUNKINFO *pti,
  2710. UINT uiSize32,
  2711. UINT uiSize16,
  2712. SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
  2713. void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
  2714. {
  2715. DWORD dwResult;
  2716. ULONG ulCount;
  2717. VPVOID vpstruct16;
  2718. VPVOID vpfetched16;
  2719. LPVOID lpstruct32;
  2720. LPVOID lpstruct32Iterate;
  2721. VPVOID vpstruct16Iterate;
  2722. ULONG *lpfetched32;
  2723. ULONG UNALIGNED *lpfetched16;
  2724. ULONG ulFetched16 = 0;
  2725. ULONG ulIterate;
  2726. BOOL fError;
  2727. SCODE sc;
  2728. LPVOID pvArg32;
  2729. dwResult = (DWORD)S_OK;
  2730. GET_STACK32(pti, ulCount, ULONG );
  2731. GET_STACK32(pti, lpstruct32, LPVOID );
  2732. GET_STACK32(pti, lpfetched32, ULONG FAR *);
  2733. vpfetched16 = STACKALLOC16(sizeof(ULONG));
  2734. if (vpfetched16 == 0)
  2735. {
  2736. dwResult = (DWORD)E_OUTOFMEMORY;
  2737. }
  2738. else
  2739. {
  2740. // Zero this out so that we don't have a random value sitting
  2741. // underneath
  2742. // when bad apps like 16-bit MsWorks don't return the number of items
  2743. // in the returned enumeration.
  2744. lpfetched16 = FIXVDMPTR(vpfetched16, ULONG);
  2745. *lpfetched16 = 0;
  2746. RELVDMPTR(vpfetched16);
  2747. }
  2748. pvArg32 = NULL;
  2749. vpstruct16 = 0;
  2750. if ( lpstruct32 != NULL )
  2751. {
  2752. if ( ulCount == 0 )
  2753. {
  2754. dwResult = (DWORD)E_INVALIDARG;
  2755. }
  2756. else
  2757. {
  2758. if (IsBadWritePtr(lpstruct32, ulCount*uiSize32))
  2759. {
  2760. dwResult = (DWORD)E_INVALIDARG;
  2761. }
  2762. else
  2763. {
  2764. pvArg32 = lpstruct32;
  2765. if ( ulCount > MAX_ALLOCA_STRUCT )
  2766. {
  2767. vpstruct16 = WgtAllocLock( GMEM_MOVEABLE,
  2768. ulCount * uiSize16,
  2769. NULL );
  2770. }
  2771. else
  2772. {
  2773. vpstruct16 = STACKALLOC16( ulCount * uiSize16 );
  2774. }
  2775. if (vpstruct16 == 0)
  2776. {
  2777. dwResult = (DWORD)E_OUTOFMEMORY;
  2778. }
  2779. }
  2780. }
  2781. }
  2782. if (SUCCEEDED(dwResult))
  2783. {
  2784. TO_STACK16(pti, ulCount, ULONG);
  2785. TO_STACK16(pti, vpstruct16, VPVOID);
  2786. TO_STACK16(pti, vpfetched16, VPVOID);
  2787. pti->pThop++;
  2788. dwResult = EXECUTE_THOP3216(pti);
  2789. }
  2790. if ( SUCCEEDED(dwResult) )
  2791. {
  2792. lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
  2793. ulFetched16 = *lpfetched16;
  2794. RELVDMPTR(vpfetched16);
  2795. if ( lpstruct32 != NULL )
  2796. {
  2797. // Some apps (MsWorks3 is one) return S_FALSE and do not return
  2798. // the number of elements retrieved. The only thing we can
  2799. // do is ignore the enumeration since we don't know how many
  2800. // were actually set. Of course, we can't ignore all enumerations
  2801. // when the return is S_FALSE so we only handle the case
  2802. // where S_FALSE was returned on a enumeration of one element,
  2803. // in which we can be sure there isn't any valid data
  2804. if (dwResult == (DWORD)S_FALSE && ulCount == 1)
  2805. {
  2806. ulFetched16 = 0;
  2807. }
  2808. //
  2809. // Iterate through all of the structures, converting them
  2810. // into 16-bit
  2811. //
  2812. fError = FALSE;
  2813. ulIterate = 0;
  2814. vpstruct16Iterate = vpstruct16;
  2815. lpstruct32Iterate = lpstruct32;
  2816. while ( ulIterate < ulFetched16 )
  2817. {
  2818. //
  2819. // Callback to the callback function to do any specific
  2820. // processing
  2821. //
  2822. sc = (*pfnCallback)( pti, lpstruct32Iterate,
  2823. vpstruct16Iterate );
  2824. if ( FAILED(sc) )
  2825. {
  2826. fError = TRUE;
  2827. dwResult = sc;
  2828. }
  2829. vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
  2830. uiSize16);
  2831. lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
  2832. uiSize32);
  2833. ulIterate++;
  2834. }
  2835. if ( fError )
  2836. {
  2837. //
  2838. // Cleanup all these guys
  2839. //
  2840. ulIterate = 0;
  2841. vpstruct16Iterate = vpstruct16;
  2842. lpstruct32Iterate = lpstruct32;
  2843. while ( ulIterate <= ulFetched16 )
  2844. {
  2845. (*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
  2846. vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
  2847. uiSize16);
  2848. lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
  2849. uiSize32);
  2850. ulIterate++;
  2851. }
  2852. }
  2853. }
  2854. }
  2855. if (FAILED(dwResult) && pvArg32 != NULL)
  2856. {
  2857. memset(pvArg32, 0, ulCount*uiSize32);
  2858. }
  2859. if ( lpfetched32 != NULL )
  2860. {
  2861. *lpfetched32 = ulFetched16;
  2862. }
  2863. //
  2864. // Free up any space we've allocated
  2865. //
  2866. if (vpstruct16 != 0)
  2867. {
  2868. if ( ulCount > MAX_ALLOCA_STRUCT )
  2869. {
  2870. WgtUnlockFree( vpstruct16 );
  2871. }
  2872. else
  2873. {
  2874. STACKFREE16( vpstruct16, ulCount * uiSize16 );
  2875. }
  2876. }
  2877. if (vpfetched16 != 0)
  2878. {
  2879. STACKFREE16(vpfetched16, sizeof(ULONG));
  2880. }
  2881. return dwResult;
  2882. }
  2883. //+---------------------------------------------------------------------------
  2884. //
  2885. // Function: Callback_STRING_3216, public
  2886. //
  2887. // Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
  2888. // space.
  2889. //
  2890. // Arguments: [pti] - Thunking state information
  2891. // [lp32] - Pointer to 32-bit output structure
  2892. // [lp16] - Pointer to 16-bit returned structure
  2893. //
  2894. // Returns: SCODE indicating success/failure
  2895. //
  2896. // History: 1-Mar-94 BobDay Created
  2897. //
  2898. //----------------------------------------------------------------------------
  2899. SCODE Callback_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  2900. {
  2901. VPSTR vpstr;
  2902. *(LPOLESTR *)lp32 = NULL;
  2903. vpstr = *FIXVDMPTR(vp16, VPSTR);
  2904. RELVDMPTR(vp16);
  2905. return ConvertTaskString1632(pti, vpstr, NULL, 0, (LPOLESTR *)lp32);
  2906. }
  2907. //+---------------------------------------------------------------------------
  2908. //
  2909. // Function: Cleanup_STRING_3216, public
  2910. //
  2911. // Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
  2912. //
  2913. // Arguments: [pti] - Thunking state information
  2914. // [lp32] - Pointer to 32-bit output structure
  2915. // [lp16] - Pointer to 16-bit returned structure
  2916. //
  2917. // Returns: nothing, should NEVER fail
  2918. //
  2919. // History: 1-Mar-94 BobDay Created
  2920. //
  2921. //----------------------------------------------------------------------------
  2922. void Cleanup_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  2923. {
  2924. LPOLESTR lpstr32;
  2925. lpstr32 = *(LPOLESTR *)lp32;
  2926. if ( lpstr32 != NULL )
  2927. {
  2928. TaskFree32( lpstr32 );
  2929. }
  2930. }
  2931. //+---------------------------------------------------------------------------
  2932. //
  2933. // Function: Thop_Enum_STRING_3216, public
  2934. //
  2935. // Synopsis: Thunks IEnumSTRING::Next parameters
  2936. //
  2937. // Arguments: [pti] - Thunk state information
  2938. //
  2939. // Returns: Appropriate status code
  2940. //
  2941. // History: 1-Mar-94 BobDay Created
  2942. //
  2943. // Notes: This thunk is 2nd part of a 2-byte thop.
  2944. //
  2945. //----------------------------------------------------------------------------
  2946. DWORD Thop_Enum_STRING_3216(THUNKINFO *pti)
  2947. {
  2948. return General_Enum_3216(pti,
  2949. sizeof(LPOLESTR),
  2950. sizeof(VPSTR),
  2951. Callback_STRING_3216,
  2952. Cleanup_STRING_3216 );
  2953. }
  2954. //+---------------------------------------------------------------------------
  2955. //
  2956. // Function: Callback_UNKNOWN_3216, public
  2957. //
  2958. // Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
  2959. // address space.
  2960. //
  2961. // Arguments: [pti] - Thunking state information
  2962. // [lp32] - Pointer to 32-bit output structure
  2963. // [lp16] - Pointer to 16-bit returned structure
  2964. //
  2965. // Returns: SCODE indicating success/failure
  2966. //
  2967. // History: 1-Mar-94 BobDay Created
  2968. //
  2969. //----------------------------------------------------------------------------
  2970. SCODE Callback_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  2971. {
  2972. SCODE sc = S_OK;
  2973. VPVOID vpunknown16;
  2974. IUnknown *punkThis32;
  2975. vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
  2976. RELVDMPTR(vp16);
  2977. punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpunknown16, NULL,
  2978. INDEX_IIDIDX(THI_IUnknown),
  2979. FALSE, NULL);
  2980. // Release the actual 16-bit IUnknown as it is an OUT parameter
  2981. // This could be the last release on the interface if the
  2982. // above call failed;
  2983. ReleaseOnObj16(vpunknown16);
  2984. if(!punkThis32) {
  2985. sc = E_OUTOFMEMORY;
  2986. }
  2987. *(LPUNKNOWN *)lp32 = (LPUNKNOWN)punkThis32;
  2988. return sc;
  2989. }
  2990. //+---------------------------------------------------------------------------
  2991. //
  2992. // Function: Cleanup_UNKNOWN_3216, public
  2993. //
  2994. // Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
  2995. // or 32-bit)
  2996. //
  2997. // Arguments: [pti] - Thunking state information
  2998. // [lp32] - Pointer to 32-bit output structure
  2999. // [lp16] - Pointer to 16-bit returned structure
  3000. //
  3001. // Returns: nothing, should NEVER fail
  3002. //
  3003. // History: 1-Mar-94 BobDay Created
  3004. //
  3005. //----------------------------------------------------------------------------
  3006. void Cleanup_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3007. {
  3008. LPUNKNOWN lpunknown32;
  3009. VPVOID vpv;
  3010. lpunknown32 = *(LPUNKNOWN *)lp32;
  3011. if(lpunknown32) {
  3012. // Release the proxy to 16-bit interface
  3013. ReleaseProxy3216((THUNK3216OBJ *) lpunknown32);
  3014. }
  3015. }
  3016. //+---------------------------------------------------------------------------
  3017. //
  3018. // Function: Thop_Enum_UNKNOWN_3216, public
  3019. //
  3020. // Synopsis: Thunks IEnumUNKNOWN::Next parameters
  3021. //
  3022. // Arguments: [pti] - Thunk state information
  3023. //
  3024. // Returns: Appropriate status code
  3025. //
  3026. // History: 1-Mar-94 BobDay Created
  3027. //
  3028. // Notes: This thunk is 2nd part of a 2-byte thop.
  3029. //
  3030. //----------------------------------------------------------------------------
  3031. DWORD Thop_Enum_UNKNOWN_3216(THUNKINFO *pti)
  3032. {
  3033. return General_Enum_3216(pti,
  3034. sizeof(LPUNKNOWN),
  3035. sizeof(LPUNKNOWN),
  3036. Callback_UNKNOWN_3216,
  3037. Cleanup_UNKNOWN_3216 );
  3038. }
  3039. //+---------------------------------------------------------------------------
  3040. //
  3041. // Function: Callback_STATSTG_3216, public
  3042. //
  3043. // Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
  3044. // address space.
  3045. //
  3046. // Arguments: [pti] - Thunking state information
  3047. // [lp32] - Pointer to 32-bit output structure
  3048. // [lp16] - Pointer to 16-bit returned structure
  3049. //
  3050. // Returns: SCODE indicating success/failure
  3051. //
  3052. // History: 1-Mar-94 BobDay Created
  3053. //
  3054. //----------------------------------------------------------------------------
  3055. SCODE Callback_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3056. {
  3057. ((STATSTG *)lp32)->pwcsName = NULL;
  3058. return ConvertStatStg1632(pti, vp16, (STATSTG *)lp32,
  3059. NULL, 0);
  3060. }
  3061. //+---------------------------------------------------------------------------
  3062. //
  3063. // Function: Cleanup_STATSTG_3216, public
  3064. //
  3065. // Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
  3066. // or 32-bit)
  3067. //
  3068. // Arguments: [pti] - Thunking state information
  3069. // [lp32] - Pointer to 32-bit output structure
  3070. // [lp16] - Pointer to 16-bit returned structure
  3071. //
  3072. // Returns: nothing, should NEVER fail
  3073. //
  3074. // History: 1-Mar-94 BobDay Created
  3075. //
  3076. //----------------------------------------------------------------------------
  3077. void Cleanup_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3078. {
  3079. STATSTG FAR *lpstatstg32;
  3080. lpstatstg32 = (STATSTG FAR *)lp32;
  3081. if ( lpstatstg32->pwcsName != NULL )
  3082. {
  3083. TaskFree32( lpstatstg32->pwcsName );
  3084. }
  3085. }
  3086. //+---------------------------------------------------------------------------
  3087. //
  3088. // Function: Thop_Enum_STATSTG_3216, public
  3089. //
  3090. // Synopsis: Thunks IEnumSTATSTG::Next parameters
  3091. //
  3092. // Arguments: [pti] - Thunk state information
  3093. //
  3094. // Returns: Appropriate status code
  3095. //
  3096. // History: 1-Mar-94 BobDay Created
  3097. //
  3098. // Notes: This thunk is 2nd part of a 2-byte thop.
  3099. //
  3100. //----------------------------------------------------------------------------
  3101. DWORD Thop_Enum_STATSTG_3216(THUNKINFO *pti)
  3102. {
  3103. return General_Enum_3216(pti,
  3104. sizeof(STATSTG),
  3105. sizeof(STATSTG),
  3106. Callback_STATSTG_3216,
  3107. Cleanup_STATSTG_3216 );
  3108. }
  3109. //+---------------------------------------------------------------------------
  3110. //
  3111. // Function: Callback_FORMATETC_3216, public
  3112. //
  3113. // Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
  3114. // address space.
  3115. //
  3116. // Arguments: [pti] - Thunking state information
  3117. // [lp32] - Pointer to 32-bit output structure
  3118. // [lp16] - Pointer to 16-bit returned structure
  3119. //
  3120. // Returns: SCODE indicating success/failure
  3121. //
  3122. // History: 1-Mar-94 BobDay Created
  3123. //
  3124. //----------------------------------------------------------------------------
  3125. SCODE Callback_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3126. {
  3127. ((FORMATETC *)lp32)->ptd = NULL;
  3128. return ConvertFetc1632(pti, vp16, (FORMATETC *)lp32, TRUE);
  3129. }
  3130. //+---------------------------------------------------------------------------
  3131. //
  3132. // Function: Cleanup_FORMATETC_3216, public
  3133. //
  3134. // Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
  3135. // or 32-bit)
  3136. //
  3137. // Arguments: [pti] - Thunking state information
  3138. // [lp32] - Pointer to 32-bit output structure
  3139. // [lp16] - Pointer to 16-bit returned structure
  3140. //
  3141. // Returns: nothing, should NEVER fail
  3142. //
  3143. // History: 1-Mar-94 BobDay Created
  3144. //
  3145. //----------------------------------------------------------------------------
  3146. void Cleanup_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3147. {
  3148. FORMATETC FAR *lpformatetc32;
  3149. lpformatetc32 = (FORMATETC FAR *)lp32;
  3150. if ( lpformatetc32->ptd != NULL )
  3151. {
  3152. TaskFree32( lpformatetc32->ptd );
  3153. }
  3154. }
  3155. //+---------------------------------------------------------------------------
  3156. //
  3157. // Function: Thop_Enum_FORMATETC_3216, public
  3158. //
  3159. // Synopsis: Thunks IEnumFORMATETC::Next parameters
  3160. //
  3161. // Arguments: [pti] - Thunk state information
  3162. //
  3163. // Returns: Appropriate status code
  3164. //
  3165. // History: 1-Mar-94 BobDay Created
  3166. //
  3167. // Notes: This thunk is 2nd part of a 2-byte thop.
  3168. //
  3169. //----------------------------------------------------------------------------
  3170. DWORD Thop_Enum_FORMATETC_3216(THUNKINFO *pti)
  3171. {
  3172. return General_Enum_3216(pti,
  3173. sizeof(FORMATETC),
  3174. sizeof(FORMATETC16),
  3175. Callback_FORMATETC_3216,
  3176. Cleanup_FORMATETC_3216 );
  3177. }
  3178. //+---------------------------------------------------------------------------
  3179. //
  3180. // Function: Callback_STATDATA_3216, public
  3181. //
  3182. // Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
  3183. // address space.
  3184. //
  3185. // Arguments: [pti] - Thunking state information
  3186. // [lp32] - Pointer to 32-bit output structure
  3187. // [lp16] - Pointer to 16-bit returned structure
  3188. //
  3189. // Returns: SCODE indicating success/failure
  3190. //
  3191. // History: 1-Mar-94 BobDay Created
  3192. //
  3193. //----------------------------------------------------------------------------
  3194. SCODE Callback_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3195. {
  3196. SCODE sc;
  3197. LPSTATDATA lpstatdata32;
  3198. STATDATA16 UNALIGNED *lpstatdata16;
  3199. LPADVISESINK lpadv32;
  3200. VPVOID vpadv16;
  3201. IUnknown *punkThis32;
  3202. sc = S_OK;
  3203. lpstatdata32 = (LPSTATDATA)lp32;
  3204. lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
  3205. vpadv16 = lpstatdata16->pAdvSink;
  3206. RELVDMPTR(vp16);
  3207. if ( vpadv16 != 0)
  3208. {
  3209. // We don't know whether it's an AdviseSink or
  3210. // an AdviseSink2, so pass AdviseSink2 since it's
  3211. // a superset of AdviseSink and will work for both
  3212. punkThis32 =
  3213. pti->pThkMgr->FindProxy3216(NULL, vpadv16, NULL,
  3214. INDEX_IIDIDX(THI_IAdviseSink2),
  3215. FALSE, NULL);
  3216. // Release the actual 16-bit IAdviseSink as it is an OUT parameter
  3217. // This could be the last release on the interface if the
  3218. // above call failed;
  3219. ReleaseOnObj16(vpadv16);
  3220. if(!punkThis32) {
  3221. sc = E_OUTOFMEMORY;
  3222. }
  3223. lpadv32 = (LPADVISESINK)punkThis32;
  3224. }
  3225. else
  3226. {
  3227. lpadv32 = NULL;
  3228. }
  3229. lpstatdata32->formatetc.ptd = NULL;
  3230. if (SUCCEEDED(sc))
  3231. {
  3232. // If this fails the AdviseSink proxy will be cleaned up in
  3233. // the cleanup function later
  3234. sc = ConvertFetc1632(pti,
  3235. vp16+FIELD_OFFSET(STATDATA16, formatetc),
  3236. &lpstatdata32->formatetc, TRUE);
  3237. }
  3238. if (SUCCEEDED(sc))
  3239. {
  3240. lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
  3241. lpstatdata32->advf = lpstatdata16->advf;
  3242. lpstatdata32->pAdvSink = lpadv32;
  3243. lpstatdata32->dwConnection = lpstatdata16->dwConnection;
  3244. RELVDMPTR(vp16);
  3245. }
  3246. return sc;
  3247. }
  3248. //+---------------------------------------------------------------------------
  3249. //
  3250. // Function: Cleanup_STATDATA_3216, public
  3251. //
  3252. // Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
  3253. // or 32-bit)
  3254. //
  3255. // Arguments: [pti] - Thunking state information
  3256. // [lp32] - Pointer to 32-bit output structure
  3257. // [lp16] - Pointer to 16-bit returned structure
  3258. //
  3259. // Returns: nothing, should NEVER fail
  3260. //
  3261. // History: 1-Mar-94 BobDay Created
  3262. //
  3263. //----------------------------------------------------------------------------
  3264. void Cleanup_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3265. {
  3266. STATDATA FAR *lpstatdata32;
  3267. VPVOID vpvSink;
  3268. lpstatdata32 = (STATDATA FAR *)lp32;
  3269. if ( lpstatdata32->formatetc.ptd != NULL )
  3270. {
  3271. TaskFree32( lpstatdata32->formatetc.ptd );
  3272. }
  3273. if(lpstatdata32->pAdvSink) {
  3274. // Release the proxy to 16-bit interface
  3275. ReleaseProxy3216((THUNK3216OBJ *) (lpstatdata32->pAdvSink));
  3276. }
  3277. }
  3278. //+---------------------------------------------------------------------------
  3279. //
  3280. // Function: Thop_Enum_STATDATA_3216, public
  3281. //
  3282. // Synopsis: Thunks IEnumSTATDATA::Next parameters
  3283. //
  3284. // Arguments: [pti] - Thunk state information
  3285. //
  3286. // Returns: Appropriate status code
  3287. //
  3288. // History: 1-Mar-94 BobDay Created
  3289. //
  3290. // Notes: This thunk is 2nd part of a 2-byte thop.
  3291. //
  3292. //----------------------------------------------------------------------------
  3293. DWORD Thop_Enum_STATDATA_3216(THUNKINFO *pti)
  3294. {
  3295. return General_Enum_3216(pti,
  3296. sizeof(STATDATA),
  3297. sizeof(STATDATA16),
  3298. Callback_STATDATA_3216,
  3299. Cleanup_STATDATA_3216 );
  3300. }
  3301. //+---------------------------------------------------------------------------
  3302. //
  3303. // Function: Callback_MONIKER_3216, public
  3304. //
  3305. // Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
  3306. // address space.
  3307. //
  3308. // Arguments: [pti] - Thunking state information
  3309. // [lp32] - Pointer to 32-bit output structure
  3310. // [lp16] - Pointer to 16-bit returned structure
  3311. //
  3312. // Returns: SCODE indicating success/failure
  3313. //
  3314. // History: 1-Mar-94 BobDay Created
  3315. //
  3316. //----------------------------------------------------------------------------
  3317. SCODE Callback_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3318. {
  3319. VPVOID vpmoniker16;
  3320. IUnknown *punkThis32;
  3321. SCODE sc = S_OK;
  3322. vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
  3323. RELVDMPTR(vp16);
  3324. punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpmoniker16, NULL,
  3325. INDEX_IIDIDX(THI_IMoniker),
  3326. FALSE, NULL);
  3327. // Release the actual 16-bit IMoniker as it is an OUT parameter
  3328. // This could be the last release on the interface if the
  3329. // above call failed;
  3330. ReleaseOnObj16(vpmoniker16);
  3331. if(!punkThis32) {
  3332. sc = E_OUTOFMEMORY;
  3333. }
  3334. *(LPMONIKER *)lp32 = (LPMONIKER)punkThis32;
  3335. return sc;
  3336. }
  3337. //+---------------------------------------------------------------------------
  3338. //
  3339. // Function: Cleanup_MONIKER_3216, public
  3340. //
  3341. // Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
  3342. // or 32-bit)
  3343. //
  3344. // Arguments: [pti] - Thunking state information
  3345. // [lp32] - Pointer to 32-bit output structure
  3346. // [lp16] - Pointer to 16-bit returned structure
  3347. //
  3348. // Returns: nothing, should NEVER fail
  3349. //
  3350. // History: 1-Mar-94 BobDay Created
  3351. //
  3352. //----------------------------------------------------------------------------
  3353. void Cleanup_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3354. {
  3355. LPMONIKER lpmoniker32;
  3356. VPVOID vpv;
  3357. lpmoniker32 = *(LPMONIKER *)lp32;
  3358. if(lpmoniker32) {
  3359. // Release the proxy to 16-bit interface
  3360. ReleaseProxy3216((THUNK3216OBJ *) lpmoniker32);
  3361. }
  3362. }
  3363. //+---------------------------------------------------------------------------
  3364. //
  3365. // Function: Thop_Enum_MONIKER_3216, public
  3366. //
  3367. // Synopsis: Thunks IEnumMONIKER::Next parameters
  3368. //
  3369. // Arguments: [pti] - Thunk state information
  3370. //
  3371. // Returns: Appropriate status code
  3372. //
  3373. // History: 1-Mar-94 BobDay Created
  3374. //
  3375. // Notes: This thunk is 2nd part of a 2-byte thop.
  3376. //
  3377. //----------------------------------------------------------------------------
  3378. DWORD Thop_Enum_MONIKER_3216(THUNKINFO *pti)
  3379. {
  3380. return General_Enum_3216(pti,
  3381. sizeof(LPMONIKER),
  3382. sizeof(LPMONIKER),
  3383. Callback_MONIKER_3216,
  3384. Cleanup_MONIKER_3216 );
  3385. }
  3386. //+---------------------------------------------------------------------------
  3387. //
  3388. // Function: Callback_OLEVERB_3216, public
  3389. //
  3390. // Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
  3391. // address space.
  3392. //
  3393. // Arguments: [pti] - Thunking state information
  3394. // [lp32] - Pointer to 32-bit output structure
  3395. // [lp16] - Pointer to 16-bit returned structure
  3396. //
  3397. // Returns: SCODE indicating success/failure
  3398. //
  3399. // History: 1-Mar-94 BobDay Created
  3400. //
  3401. //----------------------------------------------------------------------------
  3402. SCODE Callback_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3403. {
  3404. SCODE sc;
  3405. OLEVERB *lpoleverb32;
  3406. OLEVERB UNALIGNED *lpoleverb16;
  3407. VPSTR vpstr;
  3408. lpoleverb32 = (LPOLEVERB)lp32;
  3409. lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
  3410. vpstr = (VPSTR)lpoleverb16->lpszVerbName;
  3411. RELVDMPTR(vp16);
  3412. lpoleverb32->lpszVerbName = NULL;
  3413. sc = ConvertTaskString1632(pti, vpstr, NULL, 0,
  3414. &lpoleverb32->lpszVerbName);
  3415. if (SUCCEEDED(sc))
  3416. {
  3417. lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
  3418. lpoleverb32->lVerb = lpoleverb16->lVerb;
  3419. lpoleverb32->fuFlags = lpoleverb16->fuFlags;
  3420. lpoleverb32->grfAttribs = lpoleverb16->grfAttribs;
  3421. RELVDMPTR(vp16);
  3422. }
  3423. return sc;
  3424. }
  3425. //+---------------------------------------------------------------------------
  3426. //
  3427. // Function: Cleanup_OLEVERB_3216, public
  3428. //
  3429. // Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
  3430. // or 32-bit)
  3431. //
  3432. // Arguments: [pti] - Thunking state information
  3433. // [lp32] - Pointer to 32-bit output structure
  3434. // [lp16] - Pointer to 16-bit returned structure
  3435. //
  3436. // Returns: nothing, should NEVER fail
  3437. //
  3438. // History: 1-Mar-94 BobDay Created
  3439. //
  3440. //----------------------------------------------------------------------------
  3441. void Cleanup_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
  3442. {
  3443. OLEVERB FAR *lpoleverb32;
  3444. lpoleverb32 = (LPOLEVERB)lp32;
  3445. if ( lpoleverb32->lpszVerbName != NULL )
  3446. {
  3447. TaskFree32( lpoleverb32->lpszVerbName );
  3448. }
  3449. }
  3450. //+---------------------------------------------------------------------------
  3451. //
  3452. // Function: Thop_Enum_OLEVERB_3216, public
  3453. //
  3454. // Synopsis: Thunks IEnumOLEVERB::Next parameters
  3455. //
  3456. // Arguments: [pti] - Thunk state information
  3457. //
  3458. // Returns: Appropriate status code
  3459. //
  3460. // History: 1-Mar-94 BobDay Created
  3461. //
  3462. // Notes: This thunk is 2nd part of a 2-byte thop.
  3463. //
  3464. //----------------------------------------------------------------------------
  3465. DWORD Thop_Enum_OLEVERB_3216(THUNKINFO *pti)
  3466. {
  3467. return General_Enum_3216(pti,
  3468. sizeof(OLEVERB),
  3469. sizeof(OLEVERB),
  3470. Callback_OLEVERB_3216,
  3471. Cleanup_OLEVERB_3216 );
  3472. }
  3473. #define THOP_EFN(x) Thop_Enum_ ## x ## _3216
  3474. DWORD (*CONST aThopEnumFunctions3216[])(THUNKINFO *) =
  3475. {
  3476. THOP_EFN(STRING), // STRING
  3477. THOP_EFN(UNKNOWN), // UNKNOWN
  3478. THOP_EFN(STATSTG), // STATSTG
  3479. THOP_EFN(FORMATETC), // FORMATETC
  3480. THOP_EFN(STATDATA), // STATDATA
  3481. THOP_EFN(MONIKER), // MONIKER
  3482. THOP_EFN(OLEVERB), // OLEVERB
  3483. };