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.

4317 lines
125 KiB

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