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.

4557 lines
115 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: thoputil.cxx
  7. //
  8. // Contents: Utility routines for thunking
  9. //
  10. // History: 01-Mar-94 DrewB Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. #include <stdio.h>
  16. #include <limits.h>
  17. #include <vdmdbg.h>
  18. #include <valid.h>
  19. //
  20. // Chicago doesn't support the NT ExpLdr API, use the new Chicago
  21. // WOWGetDescriptor that copies the LDT info to a provided buffer.
  22. //
  23. #if defined(_CHICAGO_)
  24. extern "C" WOWGetDescriptor(VPVOID, VDMLDT_ENTRY *);
  25. #else
  26. extern "C" DECLSPEC_IMPORT VDMLDT_ENTRY *ExpLdt;
  27. #endif
  28. #include "struct16.hxx"
  29. #define CF_INVALID ((CLIPFORMAT)0)
  30. #define OBJDESC_CF(cf) \
  31. ((cf) == g_cfObjectDescriptor || (cf) == g_cfLinkSourceDescriptor)
  32. // Alias manager for THOP_ALIAS32
  33. CAliases gAliases32;
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Function: IidToIidIdx, public
  37. //
  38. // Synopsis: Looks up an interface index by IID
  39. // If it's not found, it returns the IID pointer
  40. //
  41. // Arguments: [riid] - IID
  42. //
  43. // Returns: Index or IID
  44. //
  45. // History: 23-Feb-94 DrewB Created
  46. //
  47. //----------------------------------------------------------------------------
  48. IIDIDX IidToIidIdx(REFIID riid)
  49. {
  50. int idx;
  51. for (idx = 0; idx < THI_COUNT; idx++)
  52. {
  53. if (IsEqualIID(riid, *aittIidToThi[idx].piid))
  54. {
  55. return INDEX_IIDIDX(aittIidToThi[idx].iThi);
  56. }
  57. }
  58. return IID_IIDIDX(&riid);
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: TaskMalloc32, public
  63. //
  64. // Synopsis: Task allocation for 32-bits
  65. //
  66. // History: 01-Mar-94 DrewB Created
  67. //
  68. // Notes: Temporary until CoTaskMemAlloc is hooked up
  69. //
  70. //----------------------------------------------------------------------------
  71. #ifndef COTASK_DEFINED
  72. LPVOID TaskMalloc32(SIZE_T cb)
  73. {
  74. IMalloc *pm;
  75. LPVOID pv;
  76. if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
  77. {
  78. return NULL;
  79. }
  80. else
  81. {
  82. pv = pm->Alloc(cb);
  83. pm->Release();
  84. }
  85. return pv;
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Function: TaskFree32, public
  90. //
  91. // Synopsis: Task free for 32-bits
  92. //
  93. // History: 01-Mar-94 DrewB Created
  94. //
  95. // Notes: Temporary until CoTaskMemAlloc is hooked up
  96. //
  97. //----------------------------------------------------------------------------
  98. void TaskFree32(LPVOID pv)
  99. {
  100. IMalloc *pm;
  101. if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
  102. {
  103. thkAssert(!"CoGetMalloc failed");
  104. }
  105. else
  106. {
  107. pm->Free(pv);
  108. pm->Release();
  109. }
  110. }
  111. #endif
  112. //+---------------------------------------------------------------------------
  113. //
  114. // Function: TaskMalloc16, public
  115. //
  116. // Synopsis: Allocates 16-bit task memory
  117. //
  118. // Arguments: [uiSize] - Amount of memory to allocate
  119. //
  120. // Returns: VPVOID for memory allocated
  121. //
  122. // History: 01-Mar-94 DrewB Created
  123. //
  124. //----------------------------------------------------------------------------
  125. DWORD TaskMalloc16( UINT uiSize )
  126. {
  127. return CallbackTo16(gdata16Data.fnTaskAlloc, uiSize);
  128. }
  129. //+---------------------------------------------------------------------------
  130. //
  131. // Function: TaskFree16, public
  132. //
  133. // Synopsis: Frees 16-bit task memory
  134. //
  135. // Arguments: [vpvoid] - VPVOID of allocated memory
  136. //
  137. // History: 01-Mar-94 DrewB Created
  138. //
  139. //----------------------------------------------------------------------------
  140. void TaskFree16( DWORD vpvoid )
  141. {
  142. CallbackTo16(gdata16Data.fnTaskFree, vpvoid);
  143. }
  144. // List of 16/32 HRESULT mappings for mapping functions
  145. struct SHrMapping
  146. {
  147. HRESULT hr16;
  148. HRESULT hr32;
  149. };
  150. // Since we're including 32-bit headers in this code we can use
  151. // the defines for the 32-bit values but we must specify the
  152. // 16-bit values explicitly
  153. static SHrMapping hmMappings[] =
  154. {
  155. 0x80000001, E_NOTIMPL,
  156. 0x80000002, E_OUTOFMEMORY,
  157. 0x80000003, E_INVALIDARG,
  158. 0x80000004, E_NOINTERFACE,
  159. 0x80000005, E_POINTER,
  160. 0x80000006, E_HANDLE,
  161. 0x80000007, E_ABORT,
  162. 0x80000008, E_FAIL,
  163. 0x80000009, E_ACCESSDENIED
  164. };
  165. #define NMAPPINGS (sizeof(hmMappings)/sizeof(hmMappings[0]))
  166. #define HR16_ERROR 0x80000000
  167. #define HR16_MAP_FIRST 1
  168. #define HR16_MAP_LAST 9
  169. //+---------------------------------------------------------------------------
  170. //
  171. // Function: TransformHRESULT_1632, public
  172. //
  173. // Synopsis: Translates a 16-bit hresult into a 32-bit hresult
  174. //
  175. // Arguments: [hresult] - 16-bit hresult to transform
  176. //
  177. // History: 15-Mar-94 BobDay Created
  178. //
  179. //----------------------------------------------------------------------------
  180. STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult )
  181. {
  182. ULONG ulIndex;
  183. // We only map error codes
  184. if (hresult & HR16_ERROR)
  185. {
  186. // The 16-bit HRESULTs to be mapped are known quantities
  187. // whose values are sequential, so we can map directly from
  188. // the value to an array index
  189. ulIndex = hresult & ~HR16_ERROR;
  190. if (ulIndex >= HR16_MAP_FIRST && ulIndex <= HR16_MAP_LAST)
  191. {
  192. // Known value, index array to find 32-bit HRESULT
  193. return hmMappings[ulIndex-HR16_MAP_FIRST].hr32;
  194. }
  195. }
  196. // No mapping found, so return the original
  197. return hresult;
  198. }
  199. //+---------------------------------------------------------------------------
  200. //
  201. // Function: TransformHRESULT_3216, public
  202. //
  203. // Synopsis: Translates a 32-bit hresult into a 16-bit hresult
  204. //
  205. // Arguments: [hresult] - 32-bit hresult to transform
  206. //
  207. // History: 15-Mar-94 BobDay Created
  208. //
  209. //----------------------------------------------------------------------------
  210. STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult )
  211. {
  212. int i;
  213. SHrMapping *phm;
  214. // We don't know the true values of 32-bit HRESULTs since we're
  215. // using the defines and they may change, so we have to look up
  216. // the hard way
  217. phm = hmMappings;
  218. for (i = 0; i < NMAPPINGS; i++)
  219. {
  220. if (phm->hr32 == (HRESULT)hresult)
  221. {
  222. return phm->hr16;
  223. }
  224. phm++;
  225. }
  226. // No mapping found, so return the original
  227. return hresult;
  228. }
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Function: RecordStackState, public debug
  232. //
  233. // Synopsis: Records the current state of the stack
  234. //
  235. // Arguments: [psr] - Storage space for information
  236. //
  237. // Modifies: [psr]
  238. //
  239. // History: 28-Apr-94 DrewB Created
  240. //
  241. //----------------------------------------------------------------------------
  242. #if DBG == 1
  243. void RecordStackState16(SStackRecord *psr)
  244. {
  245. CStackAllocator *psa;
  246. psa = TlsThkGetStack16();
  247. psa->RecordState(psr);
  248. }
  249. void RecordStackState32(SStackRecord *psr)
  250. {
  251. CStackAllocator *psa;
  252. psa = TlsThkGetStack32();
  253. psa->RecordState(psr);
  254. }
  255. #endif
  256. //+---------------------------------------------------------------------------
  257. //
  258. // Function: CheckStackState, public debug
  259. //
  260. // Synopsis: Checks recorded information about the stack against its
  261. // current state
  262. //
  263. // Arguments: [psr] - Recorded information
  264. //
  265. // History: 28-Apr-94 DrewB Created
  266. //
  267. //----------------------------------------------------------------------------
  268. #if DBG == 1
  269. void CheckStackState16(SStackRecord *psr)
  270. {
  271. CStackAllocator *psa;
  272. psa = TlsThkGetStack16();
  273. psa->CheckState(psr);
  274. }
  275. void CheckStackState32(SStackRecord *psr)
  276. {
  277. CStackAllocator *psa;
  278. psa = TlsThkGetStack32();
  279. psa->CheckState(psr);
  280. }
  281. #endif
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Function: Convert_VPSTR_to_LPOLESTR
  285. //
  286. // Synopsis: Converts 16-bit VPSTR to 32-bit LPOLESTR pointer
  287. //
  288. // Arguments: [vpstr] - VPSTR
  289. // [lpOleStr] - OLESTR
  290. // [uiSizeInPlace] - Amount of data available in [lpOleStr]
  291. // for in-place conversion (in characters, not bytes)
  292. // including nul
  293. //
  294. // Returns: Pointer to LPOLESTR with data
  295. //
  296. // History: 24-Feb-94 BobDay Created
  297. //
  298. //----------------------------------------------------------------------------
  299. LPOLESTR Convert_VPSTR_to_LPOLESTR(
  300. THUNKINFO *pti,
  301. VPSTR vpstr,
  302. LPOLESTR lpOleStr,
  303. UINT uiSizeInPlace
  304. )
  305. {
  306. LPSTR lpstr;
  307. UINT uiSize;
  308. LPOLESTR lpOleStrResult;
  309. UINT cChars;
  310. // We shouldn't be calling here for null strings
  311. thkAssert( vpstr != NULL );
  312. lpstr = GetStringPtr16(pti, vpstr, CCHMAXSTRING, &uiSize);
  313. if ( lpstr == NULL )
  314. {
  315. //
  316. // GetStringPtr will have filled in the pti->scResult
  317. //
  318. return( NULL );
  319. }
  320. // The string has to have at least one character in it
  321. // because it must be null-terminated to be valid
  322. thkAssert(uiSize > 0);
  323. lpOleStrResult = lpOleStr;
  324. if ( uiSize > uiSizeInPlace )
  325. {
  326. lpOleStrResult = (LPOLESTR)TaskMalloc32(uiSize*sizeof(OLECHAR));
  327. if (lpOleStrResult == NULL)
  328. {
  329. pti->scResult = E_OUTOFMEMORY;
  330. return NULL;
  331. }
  332. }
  333. cChars = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  334. 0,
  335. lpstr,
  336. uiSize,
  337. lpOleStrResult,
  338. uiSize );
  339. WOWRELVDMPTR(vpstr);
  340. if ( cChars == 0 )
  341. {
  342. if (lpOleStrResult != lpOleStr)
  343. {
  344. TaskFree32(lpOleStrResult);
  345. }
  346. pti->scResult = E_UNEXPECTED;
  347. return( NULL );
  348. }
  349. else
  350. {
  351. return( lpOleStrResult );
  352. }
  353. }
  354. //+---------------------------------------------------------------------------
  355. //
  356. // Function: Convert_LPOLESTR_to_VPSTR
  357. //
  358. // Synopsis: Converts 32-bit LPOLESTR to 16-bit VPSTR pointer
  359. //
  360. // Arguments: [lpOleStr] - OLESTR
  361. // [vpstr] - VPSTR
  362. // [uiSize32] - Length of OLESTR in characters (not bytes)
  363. // including nul
  364. // [uiSize16] - Byte length of buffer referred to by VPSTR
  365. //
  366. // Returns: Appropriate status code
  367. //
  368. // History: 24-Feb-94 BobDay Created
  369. //
  370. // Notes: Always converts in place
  371. //
  372. //----------------------------------------------------------------------------
  373. SCODE Convert_LPOLESTR_to_VPSTR(
  374. LPCOLESTR lpOleStr,
  375. VPSTR vpstr,
  376. UINT uiSize32,
  377. UINT uiSize16
  378. )
  379. {
  380. LPSTR lpstr;
  381. UINT cChars;
  382. SCODE sc;
  383. sc = S_OK;
  384. lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
  385. cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  386. 0,
  387. lpOleStr,
  388. uiSize32,
  389. lpstr,
  390. uiSize16,
  391. NULL,
  392. NULL );
  393. if ( cChars == 0 && uiSize32 != 0 )
  394. {
  395. sc = E_UNEXPECTED;
  396. }
  397. WOWRELVDMPTR(vpstr);
  398. return sc;
  399. }
  400. #ifdef _CHICAGO_
  401. //+---------------------------------------------------------------------------
  402. //
  403. // Function: Convert_LPSTR_to_VPSTR
  404. //
  405. // Synopsis: Converts 32-bit LPSTR to 16-bit VPSTR pointer
  406. //
  407. // Arguments: [lpOleStr] - LPSTR
  408. // [vpstr] - VPSTR
  409. // [uiSize32] - Length of LPSTR in bytes including nul
  410. // [uiSize16] - Byte length of buffer referred to by VPSTR
  411. //
  412. // Returns: Appropriate status code
  413. //
  414. // History: 10-21-95 KevinRo Created
  415. //
  416. // Notes:
  417. //
  418. //----------------------------------------------------------------------------
  419. SCODE Convert_LPSTR_to_VPSTR(
  420. LPCSTR lpOleStr,
  421. VPSTR vpstr,
  422. UINT uiSize32,
  423. UINT uiSize16
  424. )
  425. {
  426. LPSTR lpstr;
  427. lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
  428. memcpy(lpstr,lpOleStr,uiSize32);
  429. WOWRELVDMPTR(vpstr);
  430. return S_OK;
  431. }
  432. #endif // _CHICAGO_
  433. // Selector bit constants
  434. #define SEL_TI 0x0004
  435. #define SEL_RPL 0x0003
  436. #define SEL_INDEX 0xfff8
  437. #define IS_LDT_SELECTOR(sel) (((sel) & SEL_TI) == SEL_TI)
  438. // LDT bit constants
  439. #define LTYPE_APP 0x0010
  440. #define LTYPE_CODE 0x0008
  441. #define LTYPE_CREAD 0x0002
  442. #define LTYPE_DDOWN 0x0004
  443. #define LTYPE_DWRITE 0x0002
  444. // Pointer access types, or'able
  445. // Defined to be the same as thop in/out so that no translation
  446. // is necessary for checks on thop memory access
  447. #define PACC_READ THOP_IN
  448. #define PACC_WRITE THOP_OUT
  449. #define PACC_CODE 1 // Special for CODE PTRs
  450. // Information about a VDM pointer
  451. typedef struct _VPTRDESC
  452. {
  453. BYTE *pbFlat;
  454. DWORD dwLengthLeft;
  455. } VPTRDESC;
  456. // VDM memory is always zero-based on Win95
  457. #ifndef _CHICAGO_
  458. DWORD dwBaseVDMMemory = 0xFFFFFFFF;
  459. #else
  460. #define dwBaseVDMMemory 0
  461. #endif
  462. // Extended success returns from GetPtr16Description
  463. #define S_GDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
  464. #define S_SYSLDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 2)
  465. //+---------------------------------------------------------------------------
  466. //
  467. // Function: GetPtr16Description, public
  468. //
  469. // Synopsis: Validates access for a VDM pointer and returns
  470. // information about it
  471. // Also forces not-present segments into memory by
  472. // touching them
  473. //
  474. // Arguments: [vp] - VDM pointer
  475. // [grfAccess] - Desired access
  476. // [dwSize] - Desired size of access, must be >= 1
  477. // [pvpd] - VPTRDESC out
  478. //
  479. // Returns: Appropriate status code
  480. //
  481. // Modifies: [pvpd]
  482. //
  483. // History: 26-Apr-94 DrewB Created
  484. //
  485. // Notes: Returns fixed memory
  486. //
  487. //----------------------------------------------------------------------------
  488. SCODE GetPtr16Description(VPVOID vp,
  489. WORD grfAccess,
  490. DWORD dwSize,
  491. VPTRDESC *pvpd)
  492. {
  493. VDMLDT_ENTRY *vle;
  494. #if defined(_CHICAGO_)
  495. VDMLDT_ENTRY LdtEntry;
  496. #endif
  497. WORD wSel;
  498. WORD wOff;
  499. DWORD dwLength;
  500. thkAssert(vp != 0);
  501. thkAssert(dwSize > 0);
  502. thkAssert(grfAccess != 0);
  503. wSel = (WORD)(vp >> 16);
  504. wOff = (WORD)(vp & 0xffff);
  505. pvpd->dwLengthLeft = 0xffff-wOff+1; // Default length remaining
  506. if (!IS_LDT_SELECTOR(wSel))
  507. {
  508. // According to the WOW developers, the only GDT selector
  509. // is for the BIOS data area so we should never see one
  510. thkDebugOut((DEB_ERROR, "GDT selector: 0x%04X\n", wSel));
  511. // Handle it just in case
  512. pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
  513. return S_GDTENTRY;
  514. }
  515. #if defined(_CHICAGO_)
  516. vle = &LdtEntry;
  517. if (!WOWGetDescriptor(vp, vle))
  518. {
  519. return E_INVALIDARG;
  520. }
  521. #else
  522. vle = (VDMLDT_ENTRY *)((BYTE *)(ExpLdt)+(wSel & SEL_INDEX));
  523. #endif
  524. if ((vle->HighWord.Bits.Type & LTYPE_APP) == 0)
  525. {
  526. // According to the WOW developers, they don't use
  527. // system segments so we should never see one
  528. thkDebugOut((DEB_ERROR, "System descriptor: 0x%04X\n", wSel));
  529. // Handle it just in case
  530. pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
  531. return S_SYSLDTENTRY;
  532. }
  533. // Do as much up-front validation as possible
  534. // Since the segment may not be present, we are restricted to
  535. // only checking the access permissions
  536. if (vle->HighWord.Bits.Type & LTYPE_CODE)
  537. {
  538. // Validate access for code segments
  539. // Code segments are never writable
  540. if (((grfAccess & PACC_READ) &&
  541. (vle->HighWord.Bits.Type & LTYPE_CREAD) == 0) ||
  542. (grfAccess & PACC_WRITE))
  543. {
  544. return E_INVALIDARG;
  545. }
  546. }
  547. else
  548. {
  549. // Validate access for data segments
  550. // Data segments are always readable never executable
  551. if (((grfAccess & PACC_WRITE) &&
  552. (vle->HighWord.Bits.Type & LTYPE_DWRITE) == 0) ||
  553. (grfAccess & PACC_CODE))
  554. {
  555. return E_INVALIDARG;
  556. }
  557. }
  558. // Bring in segment if it's not present
  559. if (!vle->HighWord.Bits.Pres)
  560. {
  561. // We've validated access permissions and segments must
  562. // always be at least one byte long so it's safe to
  563. // touch the first byte to bring it in
  564. // On Win95, this will call GlobalFix on the pointer
  565. // to ensure that it stays in memory
  566. WOWCallback16(gdata16Data.fnTouchPointer16, vp);
  567. #if defined(_CHICAGO_)
  568. // Since we only copy the descriptor, recopy it now.
  569. WOWGetDescriptor(vp, vle);
  570. #endif
  571. thkAssert(vle->HighWord.Bits.Pres);
  572. }
  573. #ifdef _CHICAGO_
  574. else
  575. {
  576. // Lock the LDT entry (as best as we can) by fixing it
  577. // This prevents global blocks from being relocated during
  578. // heap compaction
  579. WOWGetVDMPointerFix(vp, dwSize, TRUE);
  580. }
  581. #endif
  582. dwLength = ((DWORD)vle->LimitLow |
  583. ((DWORD)vle->HighWord.Bits.LimitHi << 16))+1;
  584. if (vle->HighWord.Bits.Granularity)
  585. {
  586. // 4K granularity
  587. dwLength <<= 12;
  588. }
  589. if ((vle->HighWord.Bits.Type & LTYPE_CODE) ||
  590. (vle->HighWord.Bits.Type & LTYPE_DDOWN) == 0)
  591. {
  592. // Validate length for code and normal data segments
  593. if (wOff+dwSize > dwLength)
  594. {
  595. WOWRELVDMPTR(vp);
  596. return E_INVALIDARG;
  597. }
  598. pvpd->dwLengthLeft = dwLength-wOff;
  599. }
  600. else
  601. {
  602. // Expand-down segment
  603. if (wOff < dwLength)
  604. {
  605. WOWRELVDMPTR(vp);
  606. return E_INVALIDARG;
  607. }
  608. // Check for wraparound
  609. if (vle->HighWord.Bits.Granularity)
  610. {
  611. // Compiler - This should be +1, but
  612. // the compiler generates a warning about an overflow
  613. // in constant arithmetic
  614. pvpd->dwLengthLeft = 0xffffffff-wOff;
  615. }
  616. if (dwSize > pvpd->dwLengthLeft)
  617. {
  618. WOWRELVDMPTR(vp);
  619. return E_INVALIDARG;
  620. }
  621. }
  622. // VDM memory is always zero-based on Win95
  623. #ifndef _CHICAGO_
  624. if ( dwBaseVDMMemory == 0xFFFFFFFF )
  625. {
  626. dwBaseVDMMemory = (DWORD)WOWGetVDMPointer(0, 0, FALSE);
  627. }
  628. #endif
  629. // Translate the pointer even on Win95 because forcing the segment
  630. // present may have changed its address
  631. pvpd->pbFlat = (BYTE *)(dwBaseVDMMemory +
  632. wOff +
  633. ( (DWORD)vle->BaseLow |
  634. ( (DWORD)vle->HighWord.Bytes.BaseMid << 16) |
  635. ( (DWORD)vle->HighWord.Bytes.BaseHi << 24) ) );
  636. #if DBG == 1
  637. if (pvpd->pbFlat != WOWGetVDMPointer(vp, dwSize, TRUE))
  638. {
  639. thkDebugOut((DEB_ERROR, "GetPtr16Description: "
  640. "%p computed, %p system\n",
  641. pvpd->pbFlat, WOWGetVDMPointer(vp, dwSize, TRUE)));
  642. }
  643. #endif
  644. return S_OK;
  645. }
  646. //+---------------------------------------------------------------------------
  647. //
  648. // Function: GetReadPtr16
  649. //
  650. // Synopsis: Validates a 16-bit pointer for reading and converts it into
  651. // a flat 32 pointer.
  652. //
  653. // Arguments: [pti] - THUNKINFO * for updating error code
  654. // [vp] - 16-bit pointer to validate/convert
  655. // [dwSize] - Length to validate
  656. //
  657. // Returns: Appropriate status code
  658. //
  659. // History: 22-Mar-94 BobDay Created
  660. //
  661. //----------------------------------------------------------------------------
  662. VOID *
  663. GetReadPtr16(
  664. THUNKINFO *pti,
  665. VPVOID vp,
  666. DWORD dwSize )
  667. {
  668. VPTRDESC vpd;
  669. SCODE sc;
  670. sc = GetPtr16Description(vp, PACC_READ, dwSize, &vpd);
  671. if (FAILED(sc))
  672. {
  673. pti->scResult = sc;
  674. return NULL;
  675. }
  676. else
  677. {
  678. return vpd.pbFlat;
  679. }
  680. }
  681. //+---------------------------------------------------------------------------
  682. //
  683. // Function: GetWritePtr16
  684. //
  685. // Synopsis: Validates a 16-bit pointer for writing and converts it into
  686. // a flat 32 pointer.
  687. //
  688. // Arguments: [pti] - THUNKINFO * for updating error code
  689. // [vp] - 16-bit pointer to validate/convert
  690. // [dwSize] - Length to validate
  691. //
  692. // Returns: Appropriate status code
  693. //
  694. // History: 22-Mar-94 BobDay Created
  695. //
  696. //----------------------------------------------------------------------------
  697. VOID *
  698. GetWritePtr16(
  699. THUNKINFO *pti,
  700. VPVOID vp,
  701. DWORD dwSize )
  702. {
  703. VPTRDESC vpd;
  704. SCODE sc;
  705. sc = GetPtr16Description(vp, PACC_WRITE, dwSize, &vpd);
  706. if (FAILED(sc))
  707. {
  708. pti->scResult = sc;
  709. return NULL;
  710. }
  711. else
  712. {
  713. return vpd.pbFlat;
  714. }
  715. }
  716. //+---------------------------------------------------------------------------
  717. //
  718. // Function: GetCodePtr16
  719. //
  720. // Synopsis: Validates a 16-bit pointer for execution and converts it
  721. // into a flat 32 pointer.
  722. //
  723. // Arguments: [pti] - THUNKINFO * for updating error code
  724. // [vp] - 16-bit pointer to validate/convert
  725. // [dwSize] - Length to validate
  726. //
  727. // Returns: Appropriate status code
  728. //
  729. // History: 22-Jul-94 BobDay Created
  730. //
  731. //----------------------------------------------------------------------------
  732. VOID *
  733. GetCodePtr16(
  734. THUNKINFO *pti,
  735. VPVOID vp,
  736. DWORD dwSize )
  737. {
  738. VPTRDESC vpd;
  739. SCODE sc;
  740. sc = GetPtr16Description(vp, PACC_CODE, dwSize, &vpd);
  741. if (FAILED(sc))
  742. {
  743. pti->scResult = sc;
  744. return NULL;
  745. }
  746. else
  747. {
  748. return vpd.pbFlat;
  749. }
  750. }
  751. //+---------------------------------------------------------------------------
  752. //
  753. // Function: GetReadWritePtr16
  754. //
  755. // Synopsis: Validates a 16-bit pointer for reading and writing and
  756. // converts it into a flat 32 pointer.
  757. //
  758. // Arguments: [pti] - THUNKINFO * for updating error code
  759. // [vp] - 16-bit pointer to validate/convert
  760. // [dwSize] - Length to validate
  761. //
  762. // Returns: Appropriate status code
  763. //
  764. // History: 22-Mar-94 BobDay Created
  765. //
  766. //----------------------------------------------------------------------------
  767. VOID *
  768. GetReadWritePtr16(
  769. THUNKINFO *pti,
  770. VPVOID vp,
  771. DWORD dwSize )
  772. {
  773. VPTRDESC vpd;
  774. SCODE sc;
  775. sc = GetPtr16Description(vp, PACC_READ | PACC_WRITE, dwSize, &vpd);
  776. if (FAILED(sc))
  777. {
  778. pti->scResult = sc;
  779. return NULL;
  780. }
  781. else
  782. {
  783. return vpd.pbFlat;
  784. }
  785. }
  786. //+---------------------------------------------------------------------------
  787. //
  788. // Function: GetStringPtr16
  789. //
  790. // Synopsis: Validates a 16-bit pointer to a string for reading and
  791. // converts it (the pointer) into a flat 32 pointer. It also
  792. // returns the length, since it has to compute it anyway.
  793. //
  794. // Arguments: [pti] - THUNKINFO * for updating error code
  795. // [vp] - 16-bit pointer to validate/convert
  796. // [cchMax] - Maximum legal length
  797. // [lpSize] - Place to return length
  798. //
  799. // Returns: Appropriate status code
  800. //
  801. // History: 22-Mar-94 BobDay Created
  802. //
  803. //----------------------------------------------------------------------------
  804. CHAR *
  805. GetStringPtr16(
  806. THUNKINFO *pti,
  807. VPSTR vp,
  808. UINT cchMax,
  809. PUINT lpSize )
  810. {
  811. VPTRDESC vpd;
  812. SCODE sc;
  813. // Check the first byte to ensure read access to the segment
  814. sc = GetPtr16Description(vp, PACC_READ, 1, &vpd);
  815. if (FAILED(sc))
  816. {
  817. pti->scResult = sc;
  818. return NULL;
  819. }
  820. else
  821. {
  822. UINT cchLen;
  823. BYTE *pb;
  824. BOOL fMbLead;
  825. pb = vpd.pbFlat;
  826. if (pb == NULL)
  827. {
  828. goto Exit;
  829. }
  830. // Restrict zero-termination search to cchMax characters
  831. // or valid remaining memory
  832. // Since we specified one in GetPtr16Description, dwLengthLeft
  833. // is one off here
  834. cchMax = min(cchMax, vpd.dwLengthLeft+1);
  835. cchLen = 0;
  836. fMbLead = FALSE;
  837. while (cchMax > 0)
  838. {
  839. cchLen++;
  840. if (*pb == 0 && !fMbLead)
  841. {
  842. break;
  843. }
  844. else
  845. {
  846. fMbLead = (BOOL)g_abLeadTable[*pb++];
  847. cchMax--;
  848. }
  849. }
  850. if (cchMax > 0)
  851. {
  852. *lpSize = cchLen;
  853. return (LPSTR)vpd.pbFlat;
  854. }
  855. Exit:
  856. {
  857. pti->scResult = E_INVALIDARG;
  858. WOWRELVDMPTR(vp);
  859. return NULL;
  860. }
  861. }
  862. }
  863. //+---------------------------------------------------------------------------
  864. //
  865. // Function: ValidatePtr16, public
  866. //
  867. // Synopsis: Calls an appropriate validation routine for 16-bit
  868. // memory based on in/out status
  869. //
  870. // Arguments: [pti] - Thunk info, can be NULL for no validation
  871. // [vp16] - 16-bit pointer
  872. // [dwSize] - Size
  873. // [thopInOut] - In/out type
  874. //
  875. // Returns: Pointer or NULL
  876. //
  877. // Modifies: [pti]->scResult for errors
  878. //
  879. // History: 24-Apr-94 DrewB Created
  880. //
  881. // Notes: 0 - No validation
  882. // THOP_IN - Read validation
  883. // THOP_OUT - Write validation
  884. // THOP_INOUT - Read/write validation
  885. //
  886. //----------------------------------------------------------------------------
  887. VOID *
  888. ValidatePtr16(THUNKINFO *pti,
  889. VPVOID vp16,
  890. DWORD dwSize,
  891. THOP thopInOut)
  892. {
  893. VPTRDESC vpd;
  894. SCODE sc;
  895. thopInOut &= THOP_INOUT;
  896. if (thopInOut != 0)
  897. {
  898. sc = GetPtr16Description(vp16, thopInOut, dwSize, &vpd);
  899. if (FAILED(sc))
  900. {
  901. pti->scResult = sc;
  902. return NULL;
  903. }
  904. else
  905. {
  906. return vpd.pbFlat;
  907. }
  908. }
  909. else
  910. {
  911. return WOWFIXVDMPTR(vp16, dwSize);
  912. }
  913. }
  914. //+---------------------------------------------------------------------------
  915. //
  916. // Function: IsValidInterface16, public
  917. //
  918. // Synopsis: Validates that a provided 16-bit interface is really valid
  919. // (uses the same validation technique as 16-bit OLE 2.01)
  920. //
  921. // Arguments: [pti] - Thunk info, can be NULL for no validation
  922. // [vp16] - 16-bit pointer
  923. //
  924. // Returns: BOOL - true for valid, false for invalid
  925. //
  926. // Modifies: [pti]->scResult for errors
  927. //
  928. // History: 22-Jul-92 BobDay Created
  929. //
  930. //----------------------------------------------------------------------------
  931. BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp )
  932. {
  933. VPVOID UNALIGNED *pvpv;
  934. VPVOID vpvtbl;
  935. VPVOID vpfn;
  936. LPVOID lpfn;
  937. //
  938. // Make sure we can read the vtbl pointer from the object.
  939. //
  940. pvpv = (VPVOID FAR *)GetReadPtr16(pti, vp, sizeof(VPVOID));
  941. if ( pvpv == NULL )
  942. {
  943. thkDebugOut((DEB_WARN, "IsValidInterface16: "
  944. "Interface ptr invalid %p\n", vp));
  945. return FALSE;
  946. }
  947. vpvtbl = *pvpv; // Read the vtbl ptr
  948. WOWRELVDMPTR(vp);
  949. // Make sure we can read the first entry from the vtbl (QI)
  950. pvpv = (VPVOID FAR *)GetReadPtr16(pti, vpvtbl, sizeof(VPVOID));
  951. if ( pvpv == NULL )
  952. {
  953. thkDebugOut((DEB_WARN, "Vtbl ptr invalid %p:%p\n", vp, vpvtbl));
  954. return FALSE;
  955. }
  956. vpfn = *pvpv; // Get the QI Function
  957. WOWRELVDMPTR(vpvtbl);
  958. if ( vpfn == 0 )
  959. {
  960. thkDebugOut((DEB_WARN, "QI function NULL %p:%p\n", vp, vpvtbl));
  961. pti->scResult = E_INVALIDARG;
  962. return FALSE;
  963. }
  964. // Why it has to be 9 bytes long, I have no idea.
  965. // This check was taken from valid.cpp in
  966. // \src\ole2\dll\src\debug the 16-bit ole2.01
  967. // sources...
  968. lpfn = (LPVOID)GetCodePtr16(pti, vpfn, 9);
  969. WOWRELVDMPTR(vpfn);
  970. if ( lpfn == NULL )
  971. {
  972. thkDebugOut((DEB_WARN, "QI function ptr invalid %p:%p:%p\n",
  973. vp,vpvtbl,vpfn));
  974. return FALSE;
  975. }
  976. return TRUE;
  977. }
  978. //+---------------------------------------------------------------------------
  979. //
  980. // Function: GuidString, debug public
  981. //
  982. // Synopsis: Converts a guid to a string
  983. //
  984. // Arguments: [pguid] - GUID
  985. //
  986. // Returns: Pointer to string
  987. //
  988. // History: 08-Mar-94 DrewB Created
  989. //
  990. // Notes: Uses a static buffer
  991. //
  992. //----------------------------------------------------------------------------
  993. #if DBG == 1
  994. #pragma pack(1)
  995. struct SplitGuid
  996. {
  997. DWORD dw1;
  998. WORD w1;
  999. WORD w2;
  1000. BYTE b[8];
  1001. };
  1002. #pragma pack()
  1003. char *GuidString(GUID const *pguid)
  1004. {
  1005. static char ach[39];
  1006. SplitGuid *psg = (SplitGuid *)pguid;
  1007. wsprintfA(ach, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  1008. psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
  1009. psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
  1010. return ach;
  1011. }
  1012. #endif
  1013. #if DBG == 1
  1014. char *apszThopNames[] =
  1015. {
  1016. "THOP_END",
  1017. "THOP_SHORTLONG",
  1018. "THOP_WORDDWORD",
  1019. "THOP_COPY",
  1020. "THOP_LPSTR",
  1021. "THOP_LPLPSTR",
  1022. "THOP_BUFFER",
  1023. "THOP_HUSER",
  1024. "THOP_HGDI",
  1025. "THOP_SIZE",
  1026. "THOP_RECT",
  1027. "THOP_MSG",
  1028. "THOP_HRESULT",
  1029. "THOP_STATSTG",
  1030. "THOP_DVTARGETDEVICE",
  1031. "THOP_STGMEDIUM",
  1032. "THOP_FORMATETC",
  1033. "THOP_HACCEL",
  1034. "THOP_OIFI",
  1035. "THOP_BINDOPTS",
  1036. "THOP_LOGPALETTE",
  1037. "THOP_SNB",
  1038. "THOP_CRGIID",
  1039. "THOP_OLESTREAM",
  1040. "THOP_HTASK",
  1041. "THOP_INTERFACEINFO",
  1042. "THOP_IFACE",
  1043. "THOP_IFACEOWNER",
  1044. "THOP_IFACENOADDREF",
  1045. "THOP_IFACECLEAN",
  1046. "THOP_IFACEGEN",
  1047. "THOP_IFACEGENOWNER",
  1048. "THOP_UNKOUTER",
  1049. "THOP_UNKINNER",
  1050. "THOP_ROUTINEINDEX",
  1051. "THOP_RETURNTYPE",
  1052. "THOP_NULL",
  1053. "THOP_ERROR",
  1054. "THOP_ENUM",
  1055. "THOP_CALLBACK",
  1056. "THOP_RPCOLEMESSAGE",
  1057. "THOP_ALIAS32",
  1058. "THOP_CLSCONTEXT",
  1059. "THOP_FILENAME",
  1060. "THOP_SIZEDSTRING"
  1061. };
  1062. #endif
  1063. //+---------------------------------------------------------------------------
  1064. //
  1065. // Function: ThopName, debug public
  1066. //
  1067. // Synopsis: Returns the string name of a thop
  1068. //
  1069. // Arguments: [thop] - Thop
  1070. //
  1071. // Returns: Pointer to string
  1072. //
  1073. // History: 11-Mar-94 DrewB Created
  1074. //
  1075. // Notes: Uses a static buffer
  1076. //
  1077. //----------------------------------------------------------------------------
  1078. #if DBG == 1
  1079. char *ThopName(THOP thop)
  1080. {
  1081. static char achString[80];
  1082. char *psz;
  1083. thkAssert((thop & THOP_OPMASK) < THOP_LASTOP);
  1084. thkAssert(THOP_LASTOP ==
  1085. (sizeof(apszThopNames)/sizeof(apszThopNames[0])));
  1086. strcpy(achString, apszThopNames[thop & THOP_OPMASK]);
  1087. psz = achString+strlen(achString);
  1088. if (thop & THOP_IN)
  1089. {
  1090. strcpy(psz, " | THOP_IN");
  1091. psz += strlen(psz);
  1092. }
  1093. if (thop & THOP_OUT)
  1094. {
  1095. strcpy(psz, " | THOP_OUT");
  1096. }
  1097. return achString;
  1098. }
  1099. #endif
  1100. #if DBG == 1
  1101. char *apszEnumThopNames[] =
  1102. {
  1103. "STRING",
  1104. "UNKNOWN",
  1105. "STATSTG",
  1106. "FORMATETC",
  1107. "STATDATA",
  1108. "MONIKER",
  1109. "OLEVERB"
  1110. };
  1111. #endif
  1112. //+---------------------------------------------------------------------------
  1113. //
  1114. // Function: EnumThopName, debug public
  1115. //
  1116. // Synopsis: Returns the string name of an enum thop
  1117. //
  1118. // Arguments: [thopEnum] - Thop
  1119. //
  1120. // Returns: Pointer to string
  1121. //
  1122. // History: 11-Mar-94 DrewB Created
  1123. //
  1124. //----------------------------------------------------------------------------
  1125. #if DBG == 1
  1126. char *EnumThopName(THOP thopEnum)
  1127. {
  1128. thkAssert(thopEnum <
  1129. (sizeof(apszEnumThopNames)/sizeof(apszEnumThopNames[0])));
  1130. return apszEnumThopNames[thopEnum];
  1131. }
  1132. #endif
  1133. #if DBG == 1
  1134. // Maintain current thunking invocation nesting level
  1135. int _iThunkNestingLevel = 1;
  1136. #endif
  1137. //+---------------------------------------------------------------------------
  1138. //
  1139. // Function: NestingSpaces, debug public
  1140. //
  1141. // Synopsis: Spaces for each nesting level
  1142. //
  1143. // History: 22-Mar-94 DrewB Created
  1144. //
  1145. //----------------------------------------------------------------------------
  1146. #if DBG == 1
  1147. #define NESTING_SPACES 32
  1148. #define SPACES_PER_LEVEL 2
  1149. static char achSpaces[NESTING_SPACES+1] = " ";
  1150. void NestingSpaces(char *psz)
  1151. {
  1152. int iSpaces, i;
  1153. iSpaces = _iThunkNestingLevel*SPACES_PER_LEVEL;
  1154. while (iSpaces > 0)
  1155. {
  1156. i = min(iSpaces, NESTING_SPACES);
  1157. memcpy(psz, achSpaces, i);
  1158. psz += i;
  1159. *psz = 0;
  1160. iSpaces -= i;
  1161. }
  1162. }
  1163. #endif
  1164. //+---------------------------------------------------------------------------
  1165. //
  1166. // Function: NestingLevelString, debug public
  1167. //
  1168. // Synopsis: Provides a string describing the nesting level
  1169. //
  1170. // History: 22-Mar-94 DrewB Created
  1171. //
  1172. // Notes: Uses a static buffer
  1173. //
  1174. //----------------------------------------------------------------------------
  1175. #if DBG == 1
  1176. char *NestingLevelString(void)
  1177. {
  1178. static char ach[256];
  1179. char *psz;
  1180. if ((thkInfoLevel & DEB_NESTING) == 0)
  1181. {
  1182. return "";
  1183. }
  1184. wsprintfA(ach, "%2d:", _iThunkNestingLevel);
  1185. psz = ach+strlen(ach);
  1186. if (sizeof(ach)/SPACES_PER_LEVEL <= _iThunkNestingLevel)
  1187. {
  1188. strcpy(psz, "...");
  1189. }
  1190. else
  1191. {
  1192. NestingSpaces(psz);
  1193. }
  1194. return ach;
  1195. }
  1196. #endif
  1197. //+---------------------------------------------------------------------------
  1198. //
  1199. // Function: IidOrInterfaceString, debug public
  1200. //
  1201. // Synopsis: Returns the interface name for known interfaces or
  1202. // the IID string itself
  1203. //
  1204. // Arguments: [piid] - IID
  1205. //
  1206. // Returns: char *
  1207. //
  1208. // History: 18-Jun-94 DrewB Created
  1209. //
  1210. //----------------------------------------------------------------------------
  1211. #if DBG == 1
  1212. char *IidOrInterfaceString(IID const *piid)
  1213. {
  1214. return IidIdxString(IidToIidIdx(*piid));
  1215. }
  1216. #endif
  1217. //+---------------------------------------------------------------------------
  1218. //
  1219. // Function: IidIdxString, debug public
  1220. //
  1221. // Synopsis: Returns the interface name for known interfaces or
  1222. // the IID string itself
  1223. //
  1224. // Arguments: [iidx] - IID or index
  1225. //
  1226. // Returns: char *
  1227. //
  1228. // History: 07-Jul-94 DrewB Created
  1229. //
  1230. //----------------------------------------------------------------------------
  1231. #if DBG == 1
  1232. char *IidIdxString(IIDIDX iidx)
  1233. {
  1234. if (IIDIDX_IS_IID(iidx))
  1235. {
  1236. return GuidString(IIDIDX_IID(iidx));
  1237. }
  1238. else if (IIDIDX_INDEX(iidx) == THI_COUNT)
  1239. {
  1240. // Special case here because of IMalloc's unusual unthunked-
  1241. // but-indexed existence
  1242. return "IMalloc";
  1243. }
  1244. else
  1245. {
  1246. return inInterfaceNames[IIDIDX_INDEX(iidx)].pszInterface;
  1247. }
  1248. }
  1249. #endif
  1250. //+---------------------------------------------------------------------------
  1251. //
  1252. // Function: Handler routines, public
  1253. //
  1254. // Synopsis: Generic conversion routines for the generic thop handler
  1255. //
  1256. // Arguments: [pbFrom] - Data to convert from
  1257. // [pbTo] - Buffer to convert into
  1258. // [cbFrom] - Size of source data
  1259. // [cbTo] - Size of destination data
  1260. //
  1261. // History: 05-Apr-94 DrewB Created
  1262. //
  1263. //----------------------------------------------------------------------------
  1264. //+---------------------------------------------------------------------------
  1265. //
  1266. // Function: FhCopyMemory, public
  1267. //
  1268. // Synopsis: Handler routine for memory copies
  1269. //
  1270. // History: 05-Apr-94 DrewB Created
  1271. //
  1272. //----------------------------------------------------------------------------
  1273. void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1274. {
  1275. thkAssert(cbFrom == cbTo);
  1276. memcpy(pbTo, pbFrom, cbFrom);
  1277. #if DBG == 1
  1278. if (cbFrom == sizeof(DWORD))
  1279. {
  1280. thkDebugOut((DEB_ARGS, "Arg DWORD: 0x%08lX\n",
  1281. *(DWORD UNALIGNED *)pbFrom));
  1282. }
  1283. else if (cbFrom == sizeof(LARGE_INTEGER))
  1284. {
  1285. thkDebugOut((DEB_ARGS, "Arg 8 byte: 0x%08lX:%08lX\n",
  1286. *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
  1287. *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
  1288. }
  1289. else if (cbFrom == sizeof(GUID))
  1290. {
  1291. thkDebugOut((DEB_ARGS, "Arg 16 byte: 0x%08lX:%08lX:%08lX:%08lX\n",
  1292. *(DWORD UNALIGNED *)(pbFrom+3*sizeof(DWORD)),
  1293. *(DWORD UNALIGNED *)(pbFrom+2*sizeof(DWORD)),
  1294. *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
  1295. *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
  1296. }
  1297. else
  1298. {
  1299. thkDebugOut((DEB_ARGS, "Arg %d byte copy\n", cbFrom));
  1300. }
  1301. #endif
  1302. }
  1303. //+---------------------------------------------------------------------------
  1304. //
  1305. // Function: FhShortToLong, FhLongToShort, public
  1306. //
  1307. // Synopsis: Signed int conversion
  1308. //
  1309. // History: 05-Apr-94 DrewB Created
  1310. //
  1311. //----------------------------------------------------------------------------
  1312. void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1313. {
  1314. thkAssert(cbFrom == sizeof(SHORT));
  1315. thkAssert(cbTo == sizeof(LONG));
  1316. *(LONG UNALIGNED *)pbTo = (LONG)*(SHORT UNALIGNED *)pbFrom;
  1317. thkDebugOut((DEB_ARGS, "ShToLo %d -> %d\n",
  1318. *(SHORT UNALIGNED *)pbFrom, *(LONG UNALIGNED *)pbTo));
  1319. }
  1320. void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1321. {
  1322. thkAssert(cbFrom == sizeof(LONG));
  1323. thkAssert(cbTo == sizeof(SHORT));
  1324. // Not used in situations where clamping is meaningful
  1325. *(SHORT UNALIGNED *)pbTo = (SHORT)*(LONG UNALIGNED *)pbFrom;
  1326. thkDebugOut((DEB_ARGS, "LoToSh %d -> %d\n",
  1327. *(LONG UNALIGNED *)pbFrom, *(SHORT UNALIGNED *)pbTo));
  1328. }
  1329. //+---------------------------------------------------------------------------
  1330. //
  1331. // Function: FhWordToDword, FhDwordToWord, public
  1332. //
  1333. // Synopsis: Handler routine for memory copies
  1334. //
  1335. // History: 05-Apr-94 DrewB Created
  1336. //
  1337. //----------------------------------------------------------------------------
  1338. void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1339. {
  1340. thkAssert(cbFrom == sizeof(WORD));
  1341. thkAssert(cbTo == sizeof(DWORD));
  1342. *(DWORD UNALIGNED *)pbTo = (DWORD)*(WORD UNALIGNED *)pbFrom;
  1343. thkDebugOut((DEB_ARGS, "WoToDw 0x%04lX -> 0x%08lX\n",
  1344. *(WORD UNALIGNED *)pbFrom, *(DWORD UNALIGNED *)pbTo));
  1345. }
  1346. void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1347. {
  1348. thkAssert(cbFrom == sizeof(DWORD));
  1349. thkAssert(cbTo == sizeof(WORD));
  1350. // Not used in situations where clamping is meaningful
  1351. *(WORD UNALIGNED *)pbTo = (WORD)*(DWORD UNALIGNED *)pbFrom;
  1352. thkDebugOut((DEB_ARGS, "DwToWo 0x%08lX -> 0x%04lX\n",
  1353. *(DWORD UNALIGNED *)pbFrom, *(WORD UNALIGNED *)pbTo));
  1354. }
  1355. //+---------------------------------------------------------------------------
  1356. //
  1357. // Function: Handle routines, public
  1358. //
  1359. // Synopsis: Handler routine for Windows handles
  1360. //
  1361. // History: 05-Apr-94 DrewB Created
  1362. //
  1363. //----------------------------------------------------------------------------
  1364. void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1365. {
  1366. thkAssert(cbFrom == sizeof(HAND16));
  1367. thkAssert(cbTo == sizeof(HANDLE));
  1368. *(HBITMAP *)pbTo = HBITMAP_32(*(HBITMAP16 UNALIGNED *)pbFrom);
  1369. thkDebugOut((DEB_ARGS, "1632 HGdi: 0x%04lX -> 0x%p\n",
  1370. *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
  1371. }
  1372. void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1373. {
  1374. thkAssert(cbFrom == sizeof(HANDLE));
  1375. thkAssert(cbTo == sizeof(HAND16));
  1376. *(HAND16 UNALIGNED *)pbTo = HBITMAP_16(*(HANDLE *)pbFrom);
  1377. thkDebugOut((DEB_ARGS, "3216 HGdi: 0x%p -> 0x%04lX\n",
  1378. *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
  1379. }
  1380. void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1381. {
  1382. thkAssert(cbFrom == sizeof(HAND16));
  1383. thkAssert(cbTo == sizeof(HANDLE));
  1384. // Even though the constant is WOW_TYPE_FULLHWND, it
  1385. // works for any user handle
  1386. *(HANDLE *)pbTo = WOWHandle32(*(HAND16 UNALIGNED *)pbFrom,
  1387. WOW_TYPE_FULLHWND);
  1388. thkDebugOut((DEB_ARGS, "1632 HUser: 0x%04lX -> 0x%p\n",
  1389. *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
  1390. }
  1391. void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1392. {
  1393. thkAssert(cbFrom == sizeof(HANDLE));
  1394. thkAssert(cbTo == sizeof(HAND16));
  1395. *(HAND16 UNALIGNED *)pbTo = HWND_16(*(HANDLE *)pbFrom);
  1396. thkDebugOut((DEB_ARGS, "3216 HUser: 0x%p -> 0x%04lX\n",
  1397. *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
  1398. }
  1399. void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1400. {
  1401. thkAssert(cbFrom == sizeof(HAND16));
  1402. thkAssert(cbTo == sizeof(HANDLE));
  1403. *(HANDLE *)pbTo = HACCEL_32(*(HAND16 UNALIGNED *)pbFrom);
  1404. thkDebugOut((DEB_ARGS, "1632 HACCEL: 0x%04lX -> 0x%p\n",
  1405. *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
  1406. }
  1407. void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1408. {
  1409. thkAssert(cbFrom == sizeof(HANDLE));
  1410. thkAssert(cbTo == sizeof(HAND16));
  1411. *(HAND16 UNALIGNED *)pbTo = HACCEL_16(*(HANDLE *)pbFrom);
  1412. thkDebugOut((DEB_ARGS, "3216 HACCEL: 0x%p -> 0x%04lX\n",
  1413. *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
  1414. }
  1415. void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1416. {
  1417. HAND16 h16;
  1418. DWORD h32;
  1419. thkAssert(cbFrom == sizeof(HAND16));
  1420. thkAssert(cbTo == sizeof(HANDLE));
  1421. h16 = *(HAND16 UNALIGNED *)pbFrom;
  1422. if ( h16 == 0 )
  1423. {
  1424. h32 = 0;
  1425. }
  1426. else
  1427. {
  1428. h32 = HTASK_32(h16);
  1429. }
  1430. *(DWORD *)pbTo = h32;
  1431. thkDebugOut((DEB_ARGS, "1632 HTASK: 0x%04lX -> 0x%p\n", h16, h32));
  1432. }
  1433. void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1434. {
  1435. HAND16 h16;
  1436. HANDLE h32;
  1437. thkAssert(cbFrom == sizeof(HANDLE));
  1438. thkAssert(cbTo == sizeof(HAND16));
  1439. h32 = *(HANDLE *)pbFrom;
  1440. if ( h32 == NULL )
  1441. {
  1442. h16 = 0;
  1443. }
  1444. else
  1445. {
  1446. h16 = HTASK_16(h32);
  1447. }
  1448. *(HAND16 UNALIGNED *)pbTo = h16;
  1449. thkDebugOut((DEB_ARGS, "3216 HTASK: 0x%p -> 0x%04lX\n",h32, h16));
  1450. }
  1451. //+---------------------------------------------------------------------------
  1452. //
  1453. // Function: HRESULT routines, public
  1454. //
  1455. // Synopsis: Handler routine for HRESULTs
  1456. //
  1457. // History: 05-Apr-94 DrewB Created
  1458. //
  1459. //----------------------------------------------------------------------------
  1460. void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1461. {
  1462. thkAssert(cbFrom == sizeof(HRESULT));
  1463. thkAssert(cbTo == sizeof(HRESULT));
  1464. *(HRESULT *)pbTo = TransformHRESULT_1632(*(HRESULT UNALIGNED *)pbFrom);
  1465. thkDebugOut((DEB_ARGS, "1632 HRESULT: 0x%08lX -> 0x%08lX\n",
  1466. *(HRESULT UNALIGNED *)pbFrom, *(HRESULT *)pbTo));
  1467. }
  1468. void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1469. {
  1470. thkAssert(cbFrom == sizeof(HRESULT));
  1471. thkAssert(cbTo == sizeof(HRESULT));
  1472. *(HRESULT UNALIGNED *)pbTo = TransformHRESULT_3216(*(HRESULT *)pbFrom);
  1473. thkDebugOut((DEB_ARGS, "3216 HRESULT: 0x%08lX -> 0x%08lX\n",
  1474. *(HRESULT *)pbFrom, *(HRESULT UNALIGNED *)pbTo));
  1475. }
  1476. //+---------------------------------------------------------------------------
  1477. //
  1478. // Function: NULL routines, public
  1479. //
  1480. // Synopsis: Handler routine for NULL
  1481. //
  1482. // History: 05-Apr-94 DrewB Created
  1483. //
  1484. //----------------------------------------------------------------------------
  1485. void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1486. {
  1487. thkAssert(cbFrom == sizeof(void *));
  1488. thkAssert(cbTo == sizeof(void *));
  1489. thkDebugOut((DEB_WARN, "FhNull: %p NULL value not NULL\n", pbFrom));
  1490. *(void UNALIGNED **)pbTo = NULL;
  1491. thkDebugOut((DEB_ARGS, "Arg NULL\n"));
  1492. }
  1493. //+---------------------------------------------------------------------------
  1494. //
  1495. // Function: Rect routines, public
  1496. //
  1497. // Synopsis: Handler routines for RECT
  1498. //
  1499. // History: 05-Apr-94 DrewB Created
  1500. //
  1501. //----------------------------------------------------------------------------
  1502. void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1503. {
  1504. RECT *pr32;
  1505. RECT16 UNALIGNED * pr16;
  1506. thkAssert(cbFrom == sizeof(RECT16));
  1507. thkAssert(cbTo == sizeof(RECT));
  1508. pr16 = (RECT16 UNALIGNED *)pbFrom;
  1509. pr32 = (RECT *)pbTo;
  1510. pr32->left = (LONG)pr16->left; // Sign extend
  1511. pr32->top = (LONG)pr16->top; // Sign extend
  1512. pr32->right = (LONG)pr16->right; // Sign extend
  1513. pr32->bottom = (LONG)pr16->bottom; // Sign extend
  1514. thkDebugOut((DEB_ARGS, "1632 RECT: {%d, %d, %d, %d}\n",
  1515. pr32->left, pr32->top, pr32->right, pr32->bottom));
  1516. }
  1517. void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1518. {
  1519. RECT *pr32;
  1520. RECT16 UNALIGNED *pr16;
  1521. thkAssert(cbFrom == sizeof(RECT));
  1522. thkAssert(cbTo == sizeof(RECT16));
  1523. pr32 = (RECT *)pbFrom;
  1524. pr16 = (RECT16 UNALIGNED *)pbTo;
  1525. pr16->left = ClampLongToShort(pr32->left);
  1526. pr16->top = ClampLongToShort(pr32->top);
  1527. pr16->right = ClampLongToShort(pr32->right);
  1528. pr16->bottom = ClampLongToShort(pr32->bottom);
  1529. thkDebugOut((DEB_ARGS, "3216 RECT: {%d, %d, %d, %d}\n",
  1530. pr32->left, pr32->top, pr32->right, pr32->bottom));
  1531. }
  1532. //+---------------------------------------------------------------------------
  1533. //
  1534. // Function: Size routines, public
  1535. //
  1536. // Synopsis: Handler routines for SIZE
  1537. //
  1538. // History: 05-Apr-94 DrewB Created
  1539. //
  1540. //----------------------------------------------------------------------------
  1541. void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1542. {
  1543. SIZE16 UNALIGNED *psize16;
  1544. SIZE *psize32;
  1545. thkAssert(cbFrom == sizeof(SIZE16));
  1546. thkAssert(cbTo == sizeof(SIZE));
  1547. psize16 = (SIZE16 UNALIGNED *)pbFrom;
  1548. psize32 = (SIZE *)pbTo;
  1549. psize32->cx = (LONG)psize16->cx;
  1550. psize32->cy = (LONG)psize16->cy;
  1551. thkDebugOut((DEB_ARGS, "1632 SIZE: {%d, %d}\n",
  1552. psize32->cx, psize32->cy));
  1553. }
  1554. void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1555. {
  1556. SIZE16 UNALIGNED *psize16;
  1557. SIZE *psize32;
  1558. thkAssert(cbFrom == sizeof(SIZE));
  1559. thkAssert(cbTo == sizeof(SIZE16));
  1560. psize32 = (SIZE *)pbFrom;
  1561. psize16 = (SIZE16 UNALIGNED *)pbTo;
  1562. psize16->cx = ClampLongToShort(psize32->cx);
  1563. psize16->cy = ClampLongToShort(psize32->cy);
  1564. thkDebugOut((DEB_ARGS, "3216 SIZE: {%d, %d}\n",
  1565. psize32->cx, psize32->cy));
  1566. }
  1567. //+---------------------------------------------------------------------------
  1568. //
  1569. // Function: Message routines, public
  1570. //
  1571. // Synopsis: Handler routines for MSG
  1572. //
  1573. // History: 05-Apr-94 DrewB Created
  1574. //
  1575. //----------------------------------------------------------------------------
  1576. void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1577. {
  1578. MSG16 UNALIGNED *pmsg16;
  1579. MSG *pmsg32;
  1580. thkAssert(cbFrom == sizeof(MSG16));
  1581. thkAssert(cbTo == sizeof(MSG));
  1582. pmsg16 = (MSG16 UNALIGNED *)pbFrom;
  1583. pmsg32 = (MSG *)pbTo;
  1584. pmsg32->hwnd = HWND_32(pmsg16->hwnd);
  1585. pmsg32->message = (UINT)pmsg16->message;
  1586. pmsg32->wParam = (WPARAM)pmsg16->wParam; // Should we sign extend?
  1587. pmsg32->lParam = (LPARAM)pmsg16->lParam;
  1588. pmsg32->time = pmsg16->time;
  1589. pmsg32->pt.x = (LONG)(SHORT)LOWORD(pmsg16->pt); // Sign extend
  1590. pmsg32->pt.y = (LONG)(SHORT)HIWORD(pmsg16->pt); // Sign extend
  1591. thkDebugOut((DEB_ARGS, "1632 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
  1592. "0x%08lX, {%d, %d}}\n",
  1593. pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
  1594. pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
  1595. pmsg32->pt.y));
  1596. }
  1597. void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
  1598. {
  1599. MSG16 UNALIGNED *pmsg16;
  1600. MSG *pmsg32;
  1601. thkAssert(cbFrom == sizeof(MSG));
  1602. thkAssert(cbTo == sizeof(MSG16));
  1603. pmsg32 = (MSG *)pbFrom;
  1604. pmsg16 = (MSG16 UNALIGNED *)pbTo;
  1605. pmsg16->hwnd = HWND_16(pmsg32->hwnd);
  1606. pmsg16->message = (WORD)pmsg32->message;
  1607. pmsg16->wParam = (WORD)pmsg32->wParam; // Sign truncate
  1608. pmsg16->lParam = (LONG)pmsg32->lParam;
  1609. pmsg16->time = pmsg32->time;
  1610. pmsg16->pt = MAKELONG(ClampLongToShort(pmsg32->pt.x),
  1611. ClampLongToShort(pmsg32->pt.y));
  1612. thkDebugOut((DEB_ARGS, "3216 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
  1613. "0x%08lX, {%d, %d}}\n",
  1614. pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
  1615. pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
  1616. pmsg32->pt.y));
  1617. }
  1618. //+---------------------------------------------------------------------------
  1619. //
  1620. // Function: ALLOCROUTINE, public
  1621. //
  1622. // Synopsis: A routine which allocates memory
  1623. //
  1624. // Arguments: [cb] - Amount to allocate
  1625. //
  1626. // Returns: Pointer to memory
  1627. //
  1628. // History: 19-Apr-94 DrewB Created
  1629. //
  1630. //----------------------------------------------------------------------------
  1631. //+---------------------------------------------------------------------------
  1632. //
  1633. // Function: FREEROUTINE, public
  1634. //
  1635. // Synopsis: A routine which frees memory
  1636. //
  1637. // Arguments: [pv] - Memory to free
  1638. // [cb] - Size of memory to free
  1639. //
  1640. // History: 19-Apr-94 DrewB Created
  1641. //
  1642. //----------------------------------------------------------------------------
  1643. void *ArTask16(UINT cb)
  1644. {
  1645. return (void *)TaskMalloc16(cb);
  1646. }
  1647. void FrTask16(void *pv, UINT cb)
  1648. {
  1649. TaskFree16((VPVOID)pv);
  1650. }
  1651. void *ArTask32(UINT cb)
  1652. {
  1653. return TaskMalloc32(cb);
  1654. }
  1655. void FrTask32(void *pv, UINT cb)
  1656. {
  1657. TaskFree32(pv);
  1658. }
  1659. void *ArStack16(UINT cb)
  1660. {
  1661. return (void *)STACKALLOC16(cb);
  1662. }
  1663. void FrStack16(void *pv, UINT cb)
  1664. {
  1665. STACKFREE16((VPVOID)pv, cb);
  1666. }
  1667. void *ArStack32(UINT cb)
  1668. {
  1669. // Can't use STACKALLOC32 on NT since it may be _alloca which wouldn't
  1670. // live beyond this routine
  1671. #ifdef _CHICAGO_
  1672. return STACKALLOC32(cb);
  1673. #else
  1674. return (void *)LocalAlloc(LMEM_FIXED, cb);
  1675. #endif
  1676. }
  1677. void FrStack32(void *pv, UINT cb)
  1678. {
  1679. #ifdef _CHICAGO_
  1680. STACKFREE32(pv, cb);
  1681. #else
  1682. LocalFree(pv);
  1683. #endif
  1684. }
  1685. //+---------------------------------------------------------------------------
  1686. //
  1687. // Function: ConvertDvtd1632, private
  1688. //
  1689. // Synopsis: Converts a DVTARGETDEVICE from 16 to 32-bits
  1690. //
  1691. // Arguments: [pti] - Thunking state information
  1692. // [vpdvtd16] - Source
  1693. // [pfnAlloc] - ALLOCROUTINE
  1694. // [pfnFree] - FREEROUTINE
  1695. // [ppdvtd32] - Destination
  1696. // [pcbSize] - Size return
  1697. //
  1698. // Returns: Appropriate status code
  1699. //
  1700. // Modifies: [ppdvtd32]
  1701. // [pcbSize]
  1702. //
  1703. // History: 18-Apr-94 DrewB Created
  1704. //
  1705. // Notes: [pfnAlloc/Free] must deal with 32-bit memory
  1706. //
  1707. //----------------------------------------------------------------------------
  1708. SCODE ConvertDvtd1632(THUNKINFO *pti,
  1709. VPVOID vpdvtd16,
  1710. ALLOCROUTINE pfnAlloc,
  1711. FREEROUTINE pfnFree,
  1712. DVTARGETDEVICE **ppdvtd32,
  1713. UINT *pcbSize)
  1714. {
  1715. DVTARGETDEVICE UNALIGNED *pdvtd16;
  1716. DVTARGETDEVICE *pdvtd32;
  1717. DVTDINFO dvtdi;
  1718. pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
  1719. sizeof(DVTARGETDEVICE));
  1720. if (pdvtd16 == NULL)
  1721. {
  1722. return pti->scResult;
  1723. }
  1724. pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
  1725. pdvtd16->tdSize);
  1726. WOWRELVDMPTR(vpdvtd16);
  1727. if (pdvtd16 == NULL)
  1728. {
  1729. return pti->scResult;
  1730. }
  1731. pti->scResult = UtGetDvtd16Info( pdvtd16, &dvtdi );
  1732. if ( FAILED(pti->scResult) )
  1733. {
  1734. WOWRELVDMPTR(vpdvtd16);
  1735. return pti->scResult;
  1736. }
  1737. pdvtd32 = (DVTARGETDEVICE *)pfnAlloc(dvtdi.cbConvertSize);
  1738. if (pdvtd32 == NULL)
  1739. {
  1740. WOWRELVDMPTR(vpdvtd16);
  1741. return E_OUTOFMEMORY;
  1742. }
  1743. pti->scResult = UtConvertDvtd16toDvtd32( pdvtd16, &dvtdi, pdvtd32 );
  1744. WOWRELVDMPTR(vpdvtd16);
  1745. if ( FAILED(pti->scResult) )
  1746. {
  1747. pfnFree(pdvtd32, dvtdi.cbConvertSize);
  1748. return pti->scResult;
  1749. }
  1750. *ppdvtd32 = pdvtd32;
  1751. *pcbSize = dvtdi.cbConvertSize;
  1752. return S_OK;
  1753. }
  1754. //+---------------------------------------------------------------------------
  1755. //
  1756. // Function: ConvertDvtd3216, private
  1757. //
  1758. // Synopsis: Converts a DVTARGETDEVICE from 32 to 16-bits
  1759. //
  1760. // Arguments: [pti] - Thunking state information
  1761. // [pdvtd32] - Source
  1762. // [pfnAlloc] - Allocator
  1763. // [pfnFree] - Freer
  1764. // [ppvdvtd16] - Destination
  1765. // [pcbSize] - Size return
  1766. //
  1767. // Returns: Appropriate status code
  1768. //
  1769. // Modifies: [ppvdvtd16]
  1770. // [pcbSize]
  1771. //
  1772. // History: 18-Apr-94 DrewB Created
  1773. //
  1774. // Notes: [pfnAlloc/Free] must deal with 16-bit memory
  1775. //
  1776. //----------------------------------------------------------------------------
  1777. SCODE ConvertDvtd3216(THUNKINFO *pti,
  1778. DVTARGETDEVICE *pdvtd32,
  1779. ALLOCROUTINE pfnAlloc,
  1780. FREEROUTINE pfnFree,
  1781. VPVOID *ppvdvtd16,
  1782. UINT *pcbSize)
  1783. {
  1784. DVTARGETDEVICE UNALIGNED *pdvtd16;
  1785. VPVOID vpdvtd16;
  1786. DVTDINFO dvtdi;
  1787. if (IsBadReadPtr(pdvtd32, sizeof(DVTARGETDEVICE)) ||
  1788. IsBadReadPtr(pdvtd32, pdvtd32->tdSize))
  1789. {
  1790. return E_INVALIDARG;
  1791. }
  1792. pti->scResult = UtGetDvtd32Info( pdvtd32, &dvtdi );
  1793. if ( FAILED(pti->scResult) )
  1794. {
  1795. return pti->scResult;
  1796. }
  1797. vpdvtd16 = (VPVOID)pfnAlloc(dvtdi.cbConvertSize);
  1798. if (vpdvtd16 == 0)
  1799. {
  1800. return E_OUTOFMEMORY;
  1801. }
  1802. pdvtd16 = (DVTARGETDEVICE UNALIGNED *)WOWFIXVDMPTR(vpdvtd16,
  1803. dvtdi.cbConvertSize);
  1804. pti->scResult = UtConvertDvtd32toDvtd16( pdvtd32, &dvtdi, pdvtd16 );
  1805. WOWRELVDMPTR(vpdvtd16);
  1806. if ( FAILED(pti->scResult) )
  1807. {
  1808. pfnFree((void *)vpdvtd16, dvtdi.cbConvertSize);
  1809. return pti->scResult;
  1810. }
  1811. *ppvdvtd16 = vpdvtd16;
  1812. *pcbSize = dvtdi.cbConvertSize;
  1813. return S_OK;
  1814. }
  1815. #if !defined(_CHICAGO_)
  1816. SCODE ConvertHDrop1632(HMEM16 hg16, HGLOBAL* phg32)
  1817. {
  1818. SCODE sc = S_OK;
  1819. *phg32 = CopyDropFilesFrom16(hg16);
  1820. if (!*phg32)
  1821. sc = E_INVALIDARG;
  1822. return sc;
  1823. }
  1824. SCODE ConvertHDrop3216(HGLOBAL hg32, HMEM16* phg16)
  1825. {
  1826. SCODE sc = S_OK;
  1827. *phg16 = CopyDropFilesFrom32(hg32);
  1828. if (!*phg16)
  1829. sc = E_INVALIDARG;
  1830. return sc;
  1831. }
  1832. #endif
  1833. //+---------------------------------------------------------------------------
  1834. //
  1835. // Function: ConvertHGlobal1632, public
  1836. //
  1837. // Synopsis: Creates a 32-bit HGLOBAL for a 16-bit HGLOBAL
  1838. //
  1839. // Arguments: [pti] - Thunk info, can be NULL for no validation
  1840. // [hg16] - 16-bit HGLOBAL
  1841. // [thopInOut] - Validation type
  1842. // [phg32] - 32-bit HGLOBAL in/out
  1843. // [pdwSize] - Size in/out
  1844. //
  1845. // Returns: Appropriate status code
  1846. //
  1847. // Modifies: [phg32]
  1848. // [pdwSize]
  1849. //
  1850. // History: 24-Apr-94 DrewB Created
  1851. //
  1852. // Notes: If [phg32] is non-NULL on entry, [pdwSize] must be set
  1853. // appropriately also
  1854. //
  1855. //----------------------------------------------------------------------------
  1856. SCODE ConvertHGlobal1632(THUNKINFO *pti,
  1857. HMEM16 hg16,
  1858. THOP thopInOut,
  1859. HGLOBAL *phg32,
  1860. DWORD *pdwSize)
  1861. {
  1862. SCODE sc;
  1863. VPVOID vpdata16;
  1864. LPVOID lpdata16;
  1865. LPVOID lpdata32;
  1866. HGLOBAL hg32;
  1867. DWORD dwSize;
  1868. BOOL fOwn;
  1869. sc = S_OK;
  1870. vpdata16 = WOWGlobalLockSize16( hg16, &dwSize );
  1871. if ( vpdata16 == 0 )
  1872. {
  1873. sc = E_INVALIDARG;
  1874. }
  1875. else
  1876. {
  1877. if (*phg32 != 0 && *pdwSize == dwSize)
  1878. {
  1879. hg32 = *phg32;
  1880. fOwn = FALSE;
  1881. }
  1882. else
  1883. {
  1884. hg32 = GlobalAlloc( GMEM_MOVEABLE, dwSize );
  1885. fOwn = TRUE;
  1886. }
  1887. if ( hg32 == 0 )
  1888. {
  1889. sc = E_OUTOFMEMORY;
  1890. }
  1891. else
  1892. {
  1893. lpdata32 = GlobalLock( hg32 );
  1894. lpdata16 = (LPVOID)ValidatePtr16(pti, vpdata16, dwSize, thopInOut);
  1895. if ( lpdata16 != NULL )
  1896. {
  1897. memcpy( lpdata32, lpdata16, dwSize );
  1898. WOWRELVDMPTR(vpdata16);
  1899. }
  1900. else
  1901. {
  1902. sc = pti->scResult;
  1903. }
  1904. GlobalUnlock(hg32);
  1905. if (FAILED(sc) && fOwn)
  1906. {
  1907. GlobalFree(hg32);
  1908. }
  1909. }
  1910. WOWGlobalUnlock16( hg16 );
  1911. }
  1912. if (SUCCEEDED(sc))
  1913. {
  1914. if (*phg32 != 0 && hg32 != *phg32)
  1915. {
  1916. GlobalFree(*phg32);
  1917. }
  1918. *phg32 = hg32;
  1919. *pdwSize = dwSize;
  1920. thkDebugOut((DEB_ARGS, "1632 HGLOBAL: 0x%04X -> 0x%p, %u\n",
  1921. hg16, hg32, dwSize));
  1922. }
  1923. return sc;
  1924. }
  1925. //+---------------------------------------------------------------------------
  1926. //
  1927. // Function: ConvertHGlobal3216, public
  1928. //
  1929. // Synopsis: Creates a 16-bit HGLOBAL for a 32-bit HGLOBAL
  1930. //
  1931. // Arguments: [pti] - Thunk info, can be NULL for no validation
  1932. // [hg32] - 32-bit HGLOBAL
  1933. // [thopInOut] - Validation type
  1934. // [phg16] - 16-bit HGLOBAL in/out
  1935. // [pdwSize] - Size in/out
  1936. //
  1937. // Returns: Appropriate status code
  1938. //
  1939. // Modifies: [phg16]
  1940. // [pdwSize]
  1941. //
  1942. // History: 24-Apr-94 DrewB Created
  1943. //
  1944. // Notes: If [phg16] is non-NULL on entry, [pdwSize] must be set
  1945. // appropriately also
  1946. //
  1947. //----------------------------------------------------------------------------
  1948. SCODE ConvertHGlobal3216(THUNKINFO *pti,
  1949. HGLOBAL hg32,
  1950. THOP thopInOut,
  1951. HMEM16 *phg16,
  1952. DWORD *pdwSize)
  1953. {
  1954. SCODE sc;
  1955. VPVOID vpdata16;
  1956. LPVOID lpdata16;
  1957. LPVOID lpdata32;
  1958. HMEM16 hg16;
  1959. DWORD dwSize;
  1960. BOOL fOwn;
  1961. sc = S_OK;
  1962. dwSize = (DWORD) GlobalSize(hg32);
  1963. if (dwSize == 0)
  1964. {
  1965. sc = E_INVALIDARG;
  1966. }
  1967. else
  1968. {
  1969. lpdata32 = GlobalLock(hg32);
  1970. if (*phg16 != 0 && *pdwSize == dwSize)
  1971. {
  1972. hg16 = *phg16;
  1973. vpdata16 = WOWGlobalLock16(hg16);
  1974. fOwn = FALSE;
  1975. }
  1976. else
  1977. {
  1978. vpdata16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
  1979. dwSize, &hg16);
  1980. fOwn = TRUE;
  1981. }
  1982. if (vpdata16 == 0)
  1983. {
  1984. sc = E_OUTOFMEMORY;
  1985. }
  1986. else
  1987. {
  1988. lpdata16 = (LPVOID)WOWFIXVDMPTR( vpdata16, dwSize );
  1989. if ( lpdata16 == NULL )
  1990. {
  1991. sc = E_UNEXPECTED;
  1992. }
  1993. else
  1994. {
  1995. memcpy( lpdata16, lpdata32, dwSize );
  1996. WOWRELVDMPTR(vpdata16);
  1997. }
  1998. WOWGlobalUnlock16( hg16 );
  1999. if (FAILED(sc) && fOwn)
  2000. {
  2001. WOWGlobalFree16(hg16);
  2002. }
  2003. }
  2004. GlobalUnlock(hg32);
  2005. }
  2006. if (SUCCEEDED(sc))
  2007. {
  2008. if (*phg16 != 0 && hg16 != *phg16)
  2009. {
  2010. WOWGlobalFree16(*phg16);
  2011. }
  2012. *phg16 = hg16;
  2013. *pdwSize = dwSize;
  2014. thkDebugOut((DEB_ARGS, "3216 HGLOBAL: 0x%p -> 0x%04X, %u\n",
  2015. hg32, hg16, dwSize));
  2016. }
  2017. return sc;
  2018. }
  2019. //+---------------------------------------------------------------------------
  2020. //
  2021. // Function: ConvertMfPict1632, public
  2022. //
  2023. // Synopsis: Converts a 16-bit METAFILEPICT to 32-bit
  2024. //
  2025. // Arguments: [pti] - Thunk info
  2026. // [hg16] - 16-bit HGLOBAL containing METAFILEPICT
  2027. // [phg32] - 32-bit HGLOBAL return
  2028. //
  2029. // Returns: Appropriate status code
  2030. //
  2031. // Modifies: [phg32]
  2032. //
  2033. // History: 24-Apr-94 DrewB Created
  2034. //
  2035. //----------------------------------------------------------------------------
  2036. SCODE ConvertMfPict1632(THUNKINFO *pti,
  2037. HMEM16 hg16,
  2038. HGLOBAL *phg32)
  2039. {
  2040. SCODE sc;
  2041. VPVOID vpmfp16;
  2042. METAFILEPICT16 UNALIGNED *pmfp16;
  2043. METAFILEPICT *pmfp32;
  2044. HGLOBAL hg32;
  2045. DWORD dwSize;
  2046. #if DBG == 1
  2047. BOOL fSaveToFile = FALSE;
  2048. #endif
  2049. thkDebugOut((DEB_ITRACE, "In ConvertMfPict1632(%p, 0x%04X, %p)\n",
  2050. pti, hg16, phg32));
  2051. *phg32 = 0;
  2052. sc = S_OK;
  2053. vpmfp16 = WOWGlobalLockSize16( hg16, &dwSize );
  2054. if ( vpmfp16 == 0 || dwSize < sizeof(METAFILEPICT16))
  2055. {
  2056. sc = E_INVALIDARG;
  2057. }
  2058. else
  2059. {
  2060. hg32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
  2061. if ( hg32 == 0 )
  2062. {
  2063. sc = E_OUTOFMEMORY;
  2064. }
  2065. else
  2066. {
  2067. pmfp32 = (METAFILEPICT *)GlobalLock( hg32 );
  2068. pmfp16 = (METAFILEPICT16 UNALIGNED *)GetReadPtr16(pti, vpmfp16,
  2069. dwSize);
  2070. if ( pmfp16 != NULL )
  2071. {
  2072. pmfp32->mm = (LONG)pmfp16->mm;
  2073. pmfp32->xExt = (LONG)pmfp16->xExt;
  2074. pmfp32->yExt = (LONG)pmfp16->yExt;
  2075. pmfp32->hMF = HMETAFILE_32(pmfp16->hMF);
  2076. thkDebugOut((DEB_ARGS, "1632 METAFILEPICT: "
  2077. "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
  2078. pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF,
  2079. pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF));
  2080. WOWRELVDMPTR(vpmfp16);
  2081. #if DBG == 1
  2082. if (fSaveToFile)
  2083. {
  2084. HMETAFILE hmf;
  2085. hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
  2086. if (hmf != NULL)
  2087. {
  2088. DeleteMetaFile(hmf);
  2089. }
  2090. }
  2091. #endif
  2092. }
  2093. else
  2094. {
  2095. sc = pti->scResult;
  2096. }
  2097. GlobalUnlock(hg32);
  2098. if (FAILED(sc))
  2099. {
  2100. GlobalFree(hg32);
  2101. }
  2102. }
  2103. WOWGlobalUnlock16( hg16 );
  2104. }
  2105. if (SUCCEEDED(sc))
  2106. {
  2107. *phg32 = hg32;
  2108. }
  2109. thkDebugOut((DEB_ITRACE, "Out ConvertMfPict1632 => 0x%08lX, 0x%p\n",
  2110. sc, *phg32));
  2111. return sc;
  2112. }
  2113. //+---------------------------------------------------------------------------
  2114. //
  2115. // Function: ConvertMfPict3216, public
  2116. //
  2117. // Synopsis: Converts a 32-bit METAFILEPICT to 16-bit
  2118. //
  2119. // Arguments: [pti] - Thunk info
  2120. // [hg32] - 32-bit HGLOBAL containing METAFILEPICT
  2121. // [phg16] - 16-bit HGLOBAL return
  2122. //
  2123. // Returns: Appropriate status code
  2124. //
  2125. // Modifies: [phg16]
  2126. //
  2127. // History: 24-Apr-94 DrewB Created
  2128. //
  2129. //----------------------------------------------------------------------------
  2130. SCODE ConvertMfPict3216(THUNKINFO *pti,
  2131. HGLOBAL hg32,
  2132. HMEM16 *phg16)
  2133. {
  2134. SCODE sc;
  2135. VPVOID vpmfp16;
  2136. METAFILEPICT16 UNALIGNED *pmfp16;
  2137. METAFILEPICT *pmfp32;
  2138. DWORD dwSize;
  2139. HMEM16 hg16;
  2140. #if DBG == 1
  2141. BOOL fSaveToFile = FALSE;
  2142. #endif
  2143. thkDebugOut((DEB_ITRACE, "In ConvertMfPict3216(%p, 0x%p, %p)\n",
  2144. pti, hg32, phg16));
  2145. *phg16 = 0;
  2146. sc = S_OK;
  2147. dwSize = (DWORD) GlobalSize(hg32);
  2148. pmfp32 = (METAFILEPICT *)GlobalLock(hg32);
  2149. if (dwSize == 0 || dwSize < sizeof(METAFILEPICT) || pmfp32 == NULL)
  2150. {
  2151. sc = E_INVALIDARG;
  2152. }
  2153. else
  2154. {
  2155. vpmfp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
  2156. sizeof(METAFILEPICT16), &hg16);
  2157. if (vpmfp16 == 0)
  2158. {
  2159. sc = E_OUTOFMEMORY;
  2160. }
  2161. else
  2162. {
  2163. pmfp16 = FIXVDMPTR(vpmfp16, METAFILEPICT16);
  2164. if ( pmfp16 != NULL )
  2165. {
  2166. pmfp16->mm = (SHORT)pmfp32->mm;
  2167. pmfp16->xExt = ClampLongToShort(pmfp32->xExt);
  2168. pmfp16->yExt = ClampLongToShort(pmfp32->yExt);
  2169. pmfp16->hMF = HMETAFILE_16(pmfp32->hMF);
  2170. thkDebugOut((DEB_ARGS, "3216 METAFILEPICT: "
  2171. "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
  2172. pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF,
  2173. pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF));
  2174. RELVDMPTR(vpmfp16);
  2175. #if DBG == 1
  2176. if (fSaveToFile)
  2177. {
  2178. HMETAFILE hmf;
  2179. hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
  2180. if (hmf != NULL)
  2181. {
  2182. DeleteMetaFile(hmf);
  2183. }
  2184. }
  2185. #endif
  2186. }
  2187. else
  2188. {
  2189. sc = E_UNEXPECTED;
  2190. }
  2191. WOWGlobalUnlock16(hg16);
  2192. if (FAILED(sc))
  2193. {
  2194. WOWGlobalFree16(hg16);
  2195. }
  2196. }
  2197. GlobalUnlock(hg32);
  2198. }
  2199. if (SUCCEEDED(sc))
  2200. {
  2201. *phg16 = hg16;
  2202. }
  2203. thkDebugOut((DEB_ITRACE, "Out ConvertMfPict3216 => 0x%08lX, 0x%04X\n",
  2204. sc, *phg16));
  2205. return sc;
  2206. }
  2207. //+---------------------------------------------------------------------------
  2208. //
  2209. // Function: ConvertObjDesc1632, public
  2210. //
  2211. // Synopsis: Converts an OBJECTDESCRIPTOR structure
  2212. //
  2213. // Arguments: [pti] - THUNKINFO
  2214. // [hg16] - HGLOBAL containing structure
  2215. // [phg32] - Output HGLOBAL
  2216. //
  2217. // Returns: Appropriate status code
  2218. //
  2219. // Modifies: [phg32]
  2220. //
  2221. // History: 04-May-94 DrewB Created
  2222. //
  2223. //----------------------------------------------------------------------------
  2224. SCODE ConvertObjDesc1632(THUNKINFO *pti,
  2225. HMEM16 hg16,
  2226. HGLOBAL *phg32)
  2227. {
  2228. SCODE sc;
  2229. VPVOID vp16;
  2230. HGLOBAL hg32;
  2231. DWORD dwSize;
  2232. OBJECTDESCRIPTOR UNALIGNED *pod16;
  2233. OBJECTDESCRIPTOR *pod32;
  2234. char *pszFutn, *pszSoc;
  2235. UINT cchFutn, cchSoc;
  2236. UINT cbOffset;
  2237. sc = S_OK;
  2238. *phg32 = NULL;
  2239. vp16 = WOWGlobalLock16(hg16);
  2240. if ( vp16 == 0 )
  2241. {
  2242. return E_INVALIDARG;
  2243. }
  2244. pszFutn = NULL;
  2245. pszSoc = NULL;
  2246. pod16 = (OBJECTDESCRIPTOR UNALIGNED *)
  2247. GetReadPtr16(pti, vp16, sizeof(OBJECTDESCRIPTOR));
  2248. if (pod16 == NULL)
  2249. {
  2250. sc = pti->scResult;
  2251. goto EH_Unlock;
  2252. }
  2253. dwSize = sizeof(OBJECTDESCRIPTOR);
  2254. if (pod16->dwFullUserTypeName > 0)
  2255. {
  2256. pszFutn = (char *)GetStringPtr16(pti, vp16+pod16->dwFullUserTypeName,
  2257. CCHMAXSTRING, &cchFutn);
  2258. if (pszFutn == NULL)
  2259. {
  2260. sc = pti->scResult;
  2261. goto EH_Unlock;
  2262. }
  2263. dwSize += cchFutn*sizeof(WCHAR);
  2264. }
  2265. if (pod16->dwSrcOfCopy > 0)
  2266. {
  2267. pszSoc = (char *)GetStringPtr16(pti, vp16+pod16->dwSrcOfCopy,
  2268. CCHMAXSTRING, &cchSoc);
  2269. if (pszSoc == NULL)
  2270. {
  2271. sc = pti->scResult;
  2272. goto EH_Unlock;
  2273. }
  2274. dwSize += cchSoc*sizeof(WCHAR);
  2275. }
  2276. hg32 = GlobalAlloc(GMEM_MOVEABLE, dwSize);
  2277. if ( hg32 == 0 )
  2278. {
  2279. sc = E_OUTOFMEMORY;
  2280. goto EH_Unlock;
  2281. }
  2282. pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
  2283. memcpy(pod32, pod16, sizeof(OBJECTDESCRIPTOR));
  2284. pod32->cbSize = dwSize;
  2285. cbOffset = sizeof(OBJECTDESCRIPTOR);
  2286. if (pod16->dwFullUserTypeName > 0)
  2287. {
  2288. if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  2289. 0, pszFutn, cchFutn,
  2290. (WCHAR *)((BYTE *)pod32+cbOffset),
  2291. cchFutn) == 0)
  2292. {
  2293. sc = E_UNEXPECTED;
  2294. goto EH_Free;
  2295. }
  2296. pod32->dwFullUserTypeName = cbOffset;
  2297. cbOffset += cchFutn*sizeof(WCHAR);
  2298. }
  2299. if (pod16->dwSrcOfCopy > 0)
  2300. {
  2301. if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  2302. 0, pszSoc, cchSoc,
  2303. (WCHAR *)((BYTE *)pod32+cbOffset),
  2304. cchSoc) == 0)
  2305. {
  2306. sc = E_UNEXPECTED;
  2307. goto EH_Free;
  2308. }
  2309. pod32->dwSrcOfCopy = cbOffset;
  2310. cbOffset += cchFutn*sizeof(WCHAR);
  2311. }
  2312. #if DBG == 1
  2313. WCHAR *pwcsFutn, *pwcsSoc;
  2314. if (pod32->dwFullUserTypeName > 0)
  2315. {
  2316. pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
  2317. }
  2318. else
  2319. {
  2320. pwcsFutn = NULL;
  2321. }
  2322. if (pod32->dwSrcOfCopy > 0)
  2323. {
  2324. pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
  2325. }
  2326. else
  2327. {
  2328. pwcsSoc = NULL;
  2329. }
  2330. thkDebugOut((DEB_ARGS, "1632 OBJECTDESCRIPTOR: "
  2331. "{%d, ..., \"%ws\" (%s), \"%ws\" (%s)} %p -> %p\n",
  2332. pod32->cbSize, pwcsFutn, pszFutn, pwcsSoc, pszSoc,
  2333. vp16, pod32));
  2334. #endif
  2335. GlobalUnlock(hg32);
  2336. *phg32 = hg32;
  2337. EH_Unlock:
  2338. if (pszFutn != NULL)
  2339. {
  2340. WOWRELVDMPTR(vp16+pod16->dwFullUserTypeName);
  2341. }
  2342. if (pszSoc != NULL)
  2343. {
  2344. WOWRELVDMPTR(vp16+pod16->dwSrcOfCopy);
  2345. }
  2346. if (pod16 != NULL)
  2347. {
  2348. WOWRELVDMPTR(vp16);
  2349. }
  2350. WOWGlobalUnlock16(hg16);
  2351. return sc;
  2352. EH_Free:
  2353. GlobalUnlock(hg32);
  2354. GlobalFree(hg32);
  2355. goto EH_Unlock;
  2356. }
  2357. //+---------------------------------------------------------------------------
  2358. //
  2359. // Function: ConvertObjDesc3216, public
  2360. //
  2361. // Synopsis: Converts an OBJECTDESCRIPTOR structure
  2362. //
  2363. // Arguments: [pti] - THUNKINFO
  2364. // [hg32] - HGLOBAL containing structure
  2365. // [phg16] - Output HGLOBAL
  2366. //
  2367. // Returns: Appropriate status code
  2368. //
  2369. // Modifies: [phg16]
  2370. //
  2371. // History: 04-May-94 DrewB Created
  2372. //
  2373. //----------------------------------------------------------------------------
  2374. SCODE ConvertObjDesc3216(THUNKINFO *pti,
  2375. HGLOBAL hg32,
  2376. HMEM16 *phg16)
  2377. {
  2378. SCODE sc;
  2379. VPVOID vp16;
  2380. HMEM16 hg16;
  2381. DWORD dwSize;
  2382. OBJECTDESCRIPTOR UNALIGNED *pod16;
  2383. OBJECTDESCRIPTOR *pod32;
  2384. WCHAR *pwcsFutn, *pwcsSoc;
  2385. UINT cchFutn, cchSoc;
  2386. UINT cbOffset;
  2387. sc = S_OK;
  2388. pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
  2389. if ( pod32 == 0 )
  2390. {
  2391. return E_INVALIDARG;
  2392. }
  2393. if (IsBadReadPtr(pod32, sizeof(OBJECTDESCRIPTOR)))
  2394. {
  2395. sc = E_INVALIDARG;
  2396. goto EH_Unlock;
  2397. }
  2398. dwSize = sizeof(OBJECTDESCRIPTOR);
  2399. pwcsFutn = NULL;
  2400. if (pod32->dwFullUserTypeName > 0)
  2401. {
  2402. pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
  2403. if (IsBadStringPtrW(pwcsFutn, CCHMAXSTRING))
  2404. {
  2405. sc = E_INVALIDARG;
  2406. goto EH_Unlock;
  2407. }
  2408. cchFutn = lstrlenW(pwcsFutn)+1;
  2409. dwSize += cchFutn*2;
  2410. }
  2411. pwcsSoc = NULL;
  2412. if (pod32->dwSrcOfCopy > 0)
  2413. {
  2414. pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
  2415. if (IsBadStringPtrW(pwcsSoc, CCHMAXSTRING))
  2416. {
  2417. sc = E_INVALIDARG;
  2418. goto EH_Unlock;
  2419. }
  2420. cchSoc = lstrlenW(pwcsSoc)+1;
  2421. dwSize += cchSoc*2;
  2422. }
  2423. vp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE, dwSize, &hg16);
  2424. if ( vp16 == 0 )
  2425. {
  2426. sc = E_OUTOFMEMORY;
  2427. goto EH_Unlock;
  2428. }
  2429. pod16 = FIXVDMPTR(vp16, OBJECTDESCRIPTOR);
  2430. memcpy(pod16, pod32, sizeof(OBJECTDESCRIPTOR));
  2431. pod16->cbSize = dwSize;
  2432. cbOffset = sizeof(OBJECTDESCRIPTOR);
  2433. if (pod32->dwFullUserTypeName > 0)
  2434. {
  2435. if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  2436. 0, pwcsFutn, cchFutn,
  2437. (char *)pod16+cbOffset, 2 * cchFutn,
  2438. NULL, NULL) == 0)
  2439. {
  2440. sc = E_UNEXPECTED;
  2441. goto EH_Free;
  2442. }
  2443. pod16->dwFullUserTypeName = cbOffset;
  2444. cbOffset += cchFutn*2;
  2445. }
  2446. if (pod32->dwSrcOfCopy > 0)
  2447. {
  2448. if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  2449. 0, pwcsSoc, cchSoc,
  2450. (char *)pod16+cbOffset, 2 * cchSoc,
  2451. NULL, NULL) == 0)
  2452. {
  2453. sc = E_UNEXPECTED;
  2454. goto EH_Free;
  2455. }
  2456. pod16->dwSrcOfCopy = cbOffset;
  2457. cbOffset += cchFutn*2;
  2458. }
  2459. #if DBG == 1
  2460. char *pszFutn, *pszSoc;
  2461. if (pod16->dwFullUserTypeName > 0)
  2462. {
  2463. pszFutn = (char *)((BYTE *)pod16+pod16->dwFullUserTypeName);
  2464. }
  2465. else
  2466. {
  2467. pszFutn = NULL;
  2468. }
  2469. if (pod16->dwSrcOfCopy > 0)
  2470. {
  2471. pszSoc = (char *)((BYTE *)pod16+pod16->dwSrcOfCopy);
  2472. }
  2473. else
  2474. {
  2475. pszSoc = NULL;
  2476. }
  2477. thkDebugOut((DEB_ARGS, "3216 OBJECTDESCRIPTOR: "
  2478. "{%d, ..., \"%s\" (%ws), \"%s\" (%ws)} %p -> %p\n",
  2479. pod16->cbSize, pszFutn, pwcsFutn, pszSoc, pwcsSoc,
  2480. pod32, vp16));
  2481. #endif
  2482. RELVDMPTR(vp16);
  2483. WOWGlobalUnlock16(hg16);
  2484. *phg16 = hg16;
  2485. EH_Unlock:
  2486. GlobalUnlock(hg32);
  2487. return sc;
  2488. EH_Free:
  2489. WOWGlobalUnlockFree16(vp16);
  2490. goto EH_Unlock;
  2491. }
  2492. //+---------------------------------------------------------------------------
  2493. //
  2494. // Class: CSm32ReleaseHandler (srh)
  2495. //
  2496. // Purpose: Provides punkForRelease for 16->32 STGMEDIUM conversion
  2497. //
  2498. // Interface: IUnknown
  2499. //
  2500. // History: 24-Apr-94 DrewB Created
  2501. //
  2502. //----------------------------------------------------------------------------
  2503. class CSm32ReleaseHandler : public IUnknown
  2504. {
  2505. public:
  2506. CSm32ReleaseHandler(void)
  2507. {
  2508. _vpvForRelease = NULL;
  2509. }
  2510. ~CSm32ReleaseHandler(void)
  2511. {
  2512. }
  2513. void Init(CThkMgr *pThkMgr,
  2514. STGMEDIUM UNALIGNED *psm16,
  2515. STGMEDIUM *psm32,
  2516. VPVOID vpvForRelease,
  2517. CLIPFORMAT cfFormat)
  2518. {
  2519. // Unfortunately, the MIPS compiler is not smart enough
  2520. // to do the right thing if we just declare psm16 as UNALIGNED -- it
  2521. // doesn't recognize that each member of the structure is also
  2522. // unaligned when it does the structure copy. So...to make
  2523. // sure we don't generate an alignment fault, we just copy each
  2524. // member of the structure directly.
  2525. _sm16.tymed = psm16->tymed;
  2526. switch(_sm16.tymed) {
  2527. case TYMED_HGLOBAL:
  2528. _sm16.hGlobal = psm16->hGlobal;
  2529. case TYMED_FILE:
  2530. _sm16.lpszFileName = psm16->lpszFileName;
  2531. case TYMED_ISTREAM:
  2532. _sm16.pstm = psm16->pstm;
  2533. case TYMED_ISTORAGE:
  2534. _sm16.pstg = psm16->pstg;
  2535. }
  2536. _sm16.pUnkForRelease = psm16->pUnkForRelease;
  2537. _sm32 = *psm32;
  2538. _vpvForRelease = vpvForRelease;
  2539. _cReferences = 1;
  2540. _cfFormat = cfFormat;
  2541. _pThkMgr = pThkMgr;
  2542. }
  2543. STDMETHOD(QueryInterface)(REFIID riid, void **ppv)
  2544. {
  2545. if ( IsEqualIID(riid,IID_IUnknown) )
  2546. {
  2547. *ppv = this;
  2548. AddRef();
  2549. return NOERROR;
  2550. }
  2551. else
  2552. {
  2553. thkDebugOut((DEB_WARN, "Not a QI for IUnknown\n"));
  2554. *ppv = NULL;
  2555. return E_NOINTERFACE;
  2556. }
  2557. }
  2558. STDMETHOD_(ULONG, AddRef)(void)
  2559. {
  2560. return InterlockedIncrement(&_cReferences);
  2561. }
  2562. STDMETHOD_(ULONG, Release)(void);
  2563. void CallFailed() {
  2564. _vpvForRelease = NULL;
  2565. }
  2566. private:
  2567. STGMEDIUM _sm16;
  2568. STGMEDIUM _sm32;
  2569. VPVOID _vpvForRelease;
  2570. CLIPFORMAT _cfFormat;
  2571. CThkMgr *_pThkMgr;
  2572. LONG _cReferences;
  2573. };
  2574. //+---------------------------------------------------------------------------
  2575. //
  2576. // Member: CSm32ReleaseHandler::Release, public
  2577. //
  2578. // Synopsis: Frees resources for the 32-bit copy and then
  2579. // passes the ReleaseStgMedium on to 16-bits
  2580. //
  2581. // Returns: Ref count
  2582. //
  2583. // History: 24-Apr-94 DrewB Created
  2584. //
  2585. //----------------------------------------------------------------------------
  2586. STDMETHODIMP_(ULONG) CSm32ReleaseHandler::Release(void)
  2587. {
  2588. STGMEDIUM UNALIGNED *psm16;
  2589. VPVOID vpvunk;
  2590. STGMEDIUM *psm32;
  2591. LONG lRet;
  2592. SCODE sc;
  2593. BOOL fCopy;
  2594. DWORD dwSize;
  2595. lRet = InterlockedDecrement(&_cReferences);
  2596. if (lRet != 0) {
  2597. return lRet;
  2598. }
  2599. if(_vpvForRelease) {
  2600. // This is the last release on ReleaseHandler
  2601. // Cleanup 32-bit STGMEDIUM after copying it to
  2602. // 16-bit STGMEDIUM.
  2603. fCopy = TRUE;
  2604. }
  2605. else {
  2606. // The current call failed.
  2607. // As the fields in the 16-bit STGMEDIUM are not longer valid,
  2608. // cleanup the 32-bit STGMEDIUM without copying it to
  2609. // 16-bit STGMEDIUM
  2610. fCopy = FALSE;
  2611. }
  2612. psm16 = &_sm16;
  2613. psm32 = &_sm32;
  2614. switch(psm32->tymed)
  2615. {
  2616. case TYMED_HGLOBAL:
  2617. // Assumption that OBJECTDESCRIPTOR does not need copyback
  2618. if (fCopy && !OBJDESC_CF(_cfFormat))
  2619. {
  2620. // Do we ever need to do this?
  2621. // Is it valid to rely on the contents of the HGLOBAL
  2622. // at release time?
  2623. // Is this the right time to copy back?
  2624. Assert(NULL != psm32->hGlobal);
  2625. WOWGlobalLockSize16((HMEM16)psm16->hGlobal, &dwSize);
  2626. WOWGlobalUnlock16((HMEM16)psm16->hGlobal);
  2627. sc = ConvertHGlobal3216(NULL, psm32->hGlobal, 0,
  2628. (HMEM16 *)&psm16->hGlobal, &dwSize);
  2629. // What happens on errors?
  2630. thkAssert(SUCCEEDED(sc));
  2631. }
  2632. GlobalFree(psm32->hGlobal);
  2633. psm32->hGlobal = NULL;
  2634. break;
  2635. case TYMED_MFPICT:
  2636. // Chicago uses the same GDI handles for both 32bit and 16bit worlds.
  2637. // Don't delete the handle after a copy since Chicago doesn't actually
  2638. // copy the handle.
  2639. #if !defined(_CHICAGO_)
  2640. METAFILEPICT *pmfp32;
  2641. pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
  2642. DeleteMetaFile(pmfp32->hMF);
  2643. GlobalUnlock(psm32->hGlobal);
  2644. #endif
  2645. GlobalFree(psm32->hGlobal);
  2646. break;
  2647. case TYMED_FILE:
  2648. // 32-bit handled by ReleaseStgMedium
  2649. // Clean up 16-bit ourselves
  2650. #ifdef SM_FREE_16BIT_FILENAME
  2651. if(fCopy) {
  2652. // 16-bit OLE did not free the filename, so we can't
  2653. // either. This may lead to memory leaks, but there's not
  2654. // really anything we can do about it
  2655. TaskFree16((VPVOID)psm16->lpszFileName);
  2656. }
  2657. #endif
  2658. break;
  2659. case TYMED_ISTREAM:
  2660. if(fCopy) {
  2661. // The proxy to the 16-bit stream interface was released by
  2662. // ReleaseStgMedium
  2663. // Release the reference kept on the 16-bit stream interface
  2664. ReleaseOnObj16((VPVOID) psm16->pstm);
  2665. }
  2666. break;
  2667. case TYMED_ISTORAGE:
  2668. if(fCopy) {
  2669. // The proxy to the 16-bit storage interface was released by
  2670. // ReleaseStgMedium
  2671. // Release the reference kept on the 16-bit storage interface
  2672. ReleaseOnObj16((VPVOID) psm16->pstg);
  2673. }
  2674. break;
  2675. case TYMED_GDI:
  2676. case TYMED_NULL:
  2677. // Nothing to release
  2678. break;
  2679. default:
  2680. thkAssert(!"Unknown tymed in CSm32ReleaseHandler::Release");
  2681. break;
  2682. }
  2683. // Call Release on the 16-bit vpvForRelease
  2684. if(_vpvForRelease) {
  2685. ReleaseOnObj16(_vpvForRelease);
  2686. _vpvForRelease = NULL;
  2687. }
  2688. // Clean up this
  2689. delete this;
  2690. return 0;
  2691. }
  2692. //+---------------------------------------------------------------------------
  2693. //
  2694. // Member: CSm16ReleaseHandler::Init, public
  2695. //
  2696. // Synopsis: Initialize class
  2697. //
  2698. // Arguments: [psm32] - 32-bit STGMEDIUM
  2699. // [psm16] - 16-bit STGMEDIUM
  2700. // [vpvUnkForRelease] - Object for punkForRelease
  2701. // [cfFormat] - Clipboard format associated with STGMEDIUM
  2702. //
  2703. // History: 24-Apr-94 DrewB Created
  2704. //
  2705. //----------------------------------------------------------------------------
  2706. void CSm16ReleaseHandler::Init(IUnknown *pThkMgr,
  2707. STGMEDIUM *psm32,
  2708. STGMEDIUM UNALIGNED *psm16,
  2709. IUnknown *punkForRelease,
  2710. CLIPFORMAT cfFormat)
  2711. {
  2712. _avpfnVtbl = gdata16Data.avpfnSm16ReleaseHandlerVtbl;
  2713. _sm32 = *psm32;
  2714. // Unfortunately, the MIPS compiler is not smart enough
  2715. // to do the right thing if we just (ony) declare psm16 as UNALIGNED,
  2716. // it doesn't recognize that each member of the structure is also
  2717. // unaligned when it does the structure copy. So...to make
  2718. // sure we don't generate an alignment fault, we just copy each
  2719. // member of the structure directly.
  2720. _sm16.tymed = psm16->tymed;
  2721. _sm16.hGlobal = psm16->hGlobal;
  2722. _sm16.pstm = psm16->pstm;
  2723. _sm16.pstg = psm16->pstg;
  2724. _sm16.pUnkForRelease = psm16->pUnkForRelease;
  2725. _punkForRelease = punkForRelease;
  2726. _cReferences = 1;
  2727. _cfFormat = cfFormat;
  2728. _pUnkThkMgr = pThkMgr;
  2729. }
  2730. //+---------------------------------------------------------------------------
  2731. //
  2732. // Function: CSm16ReleaseHandler_Release32, public
  2733. //
  2734. // Synopsis: Handles 32-bit portion of cleaning up STGMEDIUMs for
  2735. // punkForRelease
  2736. //
  2737. // Arguments: [psrh] - this
  2738. // [dw1]
  2739. // [dw2]
  2740. //
  2741. // Returns: punkForRelease->Release()
  2742. //
  2743. // History: 24-Apr-94 DrewB Created
  2744. //
  2745. //----------------------------------------------------------------------------
  2746. STDAPI_(DWORD) CSm16ReleaseHandler_Release32(CSm16ReleaseHandler *psrh,
  2747. DWORD dw1,
  2748. DWORD dw2)
  2749. {
  2750. STGMEDIUM UNALIGNED *psm16;
  2751. STGMEDIUM *psm32;
  2752. DWORD dwSize;
  2753. SCODE sc;
  2754. BOOL fCopy;
  2755. if(psrh->_punkForRelease) {
  2756. // This is the last release on ReleaseHandler
  2757. // Cleanup 16-bit STGMEDIUM after copying it to
  2758. // 32-bit STGMEDIUM.
  2759. fCopy = TRUE;
  2760. }
  2761. else {
  2762. // The current call failed.
  2763. // As the fields in the 32-bit STGMEDIUM are not longer valid,
  2764. // cleanup the 16-bit STGMEDIUM without copying it to
  2765. // 32-bit STGMEDIUM
  2766. fCopy = FALSE;
  2767. }
  2768. psm16 = &psrh->_sm16;
  2769. psm32 = &psrh->_sm32;
  2770. switch(psm32->tymed)
  2771. {
  2772. case TYMED_FILE:
  2773. // 16-bit code cleaned up the 16-bit name,
  2774. // now clean up the 32-bit name
  2775. if (fCopy) {
  2776. TaskFree32(psm32->lpszFileName);
  2777. }
  2778. break;
  2779. case TYMED_HGLOBAL:
  2780. // Assumption that OBJECTDESCRIPTOR does not need copyback
  2781. if(fCopy && !OBJDESC_CF(psrh->_cfFormat))
  2782. {
  2783. // Do we ever need to do this?
  2784. // Copy data back and free global memory
  2785. dwSize = (DWORD) GlobalSize(psm32->hGlobal);
  2786. sc = ConvertHGlobal1632(NULL, (HMEM16)psm16->hGlobal, 0,
  2787. &psm32->hGlobal, &dwSize);
  2788. // What happens on errors?
  2789. thkAssert(SUCCEEDED(sc));
  2790. }
  2791. WOWGlobalFree16((HMEM16)psm16->hGlobal);
  2792. break;
  2793. case TYMED_MFPICT:
  2794. // Untouched in this case
  2795. break;
  2796. case TYMED_ISTREAM:
  2797. if(fCopy) {
  2798. // The proxy to the 32-bit stream interface was released by
  2799. // ReleaseStgMedium
  2800. // Release the reference kept on the 32-bit stream interface
  2801. psm32->pstm->Release();
  2802. }
  2803. break;
  2804. case TYMED_ISTORAGE:
  2805. if(fCopy) {
  2806. // The proxy to the 32-bit stream interface was released by
  2807. // ReleaseStgMedium
  2808. // Release the reference kept on the 32-bit stream interface
  2809. psm32->pstg->Release();
  2810. }
  2811. break;
  2812. case TYMED_GDI:
  2813. case TYMED_NULL:
  2814. // Nothing to release
  2815. break;
  2816. default:
  2817. thkAssert(!"Unknown tymed in ReleaseStgMedium32");
  2818. break;
  2819. }
  2820. // Call Release on the 32-bit punkForRelease
  2821. if(fCopy) {
  2822. psrh->_punkForRelease->Release();
  2823. psrh->_punkForRelease = NULL;
  2824. }
  2825. return 0;
  2826. }
  2827. //+---------------------------------------------------------------------------
  2828. //
  2829. // Function: ConvertStgMed1632, public
  2830. //
  2831. // Synopsis: Converts a 16-bit STGMEDIUM to 32-bits
  2832. //
  2833. // Arguments: [pti] - Thunk info
  2834. // [vpsm16] - VDM pointer to 16-bit STGMEDIUM
  2835. // [psm32] - 32-bit STGMEDIUM to fill in
  2836. // [pfe] - FORMATETC paired with STGMEDIUM or NULL
  2837. // [pdwSize] - Size return
  2838. //
  2839. // Returns: Appropriate status code
  2840. //
  2841. // Modifies: [pdwSize]
  2842. //
  2843. // History: 24-Apr-94 DrewB Created
  2844. //
  2845. // Notes: [pdwSize] is only set for TYMED_HGLOBAL
  2846. //
  2847. //----------------------------------------------------------------------------
  2848. SCODE ConvertStgMed1632(THUNKINFO *pti,
  2849. VPVOID vpsm16,
  2850. STGMEDIUM *psm32,
  2851. FORMATETC *pfe,
  2852. BOOL fPassingOwnershipIn,
  2853. DWORD *pdwSize)
  2854. {
  2855. SCODE sc;
  2856. STGMEDIUM UNALIGNED *psm16;
  2857. CSm32ReleaseHandler *psrh;
  2858. IUnknown *punkForRelease;
  2859. VPVOID vpvUnk, vpvForRelease;
  2860. HMEM16 hmem16;
  2861. HGDIOBJ hGDI = NULL;
  2862. THKSTATE thkstateSaved;
  2863. psm16 = (STGMEDIUM UNALIGNED *)
  2864. GetReadPtr16(pti, vpsm16, sizeof(STGMEDIUM));
  2865. if (psm16 == NULL)
  2866. {
  2867. return pti->scResult;
  2868. }
  2869. sc = S_OK;
  2870. psm32->tymed = psm16->tymed;
  2871. vpvForRelease = (VPVOID)psm16->pUnkForRelease;
  2872. WOWRELVDMPTR(vpsm16);
  2873. if(vpvForRelease) {
  2874. // Create the 32-bit punkForRelease
  2875. thkDebugOut((DEB_WARN, "pUnkForRelease present in StgMedium1632\n"));
  2876. psrh = new CSm32ReleaseHandler;
  2877. if(psrh == NULL)
  2878. return E_OUTOFMEMORY;
  2879. }
  2880. else {
  2881. psrh = NULL;
  2882. }
  2883. psm32->pUnkForRelease = psrh;
  2884. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  2885. // Word 6 insists on treating BITMAPs as HGLOBALS, which is bogus.
  2886. // If this is the case, just patch the tymed to the correct value
  2887. if (pfe != NULL)
  2888. {
  2889. if( (pfe->cfFormat == CF_BITMAP || pfe->cfFormat == CF_PALETTE ) &&
  2890. psm16->tymed == TYMED_HGLOBAL )
  2891. {
  2892. DWORD dw = TlsThkGetAppCompatFlags();
  2893. // if we are in Word 6, then hack the tymed so we thunk the
  2894. // bitmaps as GDI objects
  2895. if( (dw & OACF_USEGDI ) )
  2896. {
  2897. DWORD dwType;
  2898. hGDI = HBITMAP_32((HBITMAP16)psm16->hBitmap);
  2899. // make sure HGDI is either a bitmap or palette
  2900. dwType = GetObjectType(hGDI);
  2901. if( (pfe->cfFormat == CF_BITMAP && dwType == OBJ_BITMAP) ||
  2902. (pfe->cfFormat == CF_PALETTE && dwType == OBJ_PAL) )
  2903. {
  2904. psm16->tymed = TYMED_GDI;
  2905. }
  2906. else
  2907. {
  2908. thkDebugOut((DEB_WARN,
  2909. "WARNING! invalid bitmap or palette!\n"));
  2910. hGDI = NULL;
  2911. }
  2912. }
  2913. else
  2914. {
  2915. thkDebugOut((DEB_WARN, "WARNING! App trying to transfer a "
  2916. "bitmap or palette on an HGLOBAL\n"));
  2917. }
  2918. }
  2919. }
  2920. switch( psm16->tymed )
  2921. {
  2922. case TYMED_HGLOBAL:
  2923. hmem16 = (HMEM16)psm16->hGlobal;
  2924. RELVDMPTR(vpsm16);
  2925. if (pfe && OBJDESC_CF(pfe->cfFormat))
  2926. {
  2927. sc = ConvertObjDesc1632(pti, hmem16, &psm32->hGlobal);
  2928. }
  2929. #if !defined(_CHICAGO_)
  2930. else if (pfe && pfe->cfFormat == CF_HDROP)
  2931. {
  2932. // fix for mapi forms
  2933. // thunk CF_HDROP passed as HGLOBAL format
  2934. sc = ConvertHDrop1632(hmem16, &psm32->hGlobal);
  2935. }
  2936. #endif
  2937. else
  2938. {
  2939. psm32->hGlobal = 0;
  2940. sc = ConvertHGlobal1632(pti, hmem16, THOP_INOUT,
  2941. &psm32->hGlobal, pdwSize);
  2942. }
  2943. break;
  2944. case TYMED_MFPICT:
  2945. hmem16 = (HMEM16)psm16->hGlobal;
  2946. RELVDMPTR(vpsm16);
  2947. sc = ConvertMfPict1632(pti, hmem16, &psm32->hGlobal);
  2948. break;
  2949. case TYMED_FILE:
  2950. psm32->lpszFileName =
  2951. Convert_VPSTR_to_LPOLESTR( pti,
  2952. (VPVOID)psm16->lpszFileName,
  2953. NULL, 0 );
  2954. if (psm32->lpszFileName == NULL)
  2955. {
  2956. sc = pti->scResult;
  2957. }
  2958. else
  2959. {
  2960. #if DBG == 1
  2961. thkDebugOut((DEB_ARGS, "1632 TYMED_FILE: '%ws' (%s)\n",
  2962. psm32->lpszFileName,
  2963. WOWFIXVDMPTR((VPVOID)psm16->lpszFileName, 0)));
  2964. WOWRELVDMPTR((VPVOID)psm16->lpszFileName);
  2965. #endif
  2966. }
  2967. RELVDMPTR(vpsm16);
  2968. break;
  2969. case TYMED_ISTREAM:
  2970. vpvUnk = (VPVOID)psm16->pstm;
  2971. RELVDMPTR(vpsm16);
  2972. psm32->pstm =
  2973. (LPSTREAM)pti->pThkMgr->FindProxy3216(NULL, vpvUnk, NULL,
  2974. INDEX_IIDIDX(THI_IStream),
  2975. FALSE, NULL);
  2976. if(psm32->pstm) {
  2977. thkDebugOut((DEB_ARGS, "1632 TYMED_ISTREAM: %p -> %p\n",
  2978. vpvUnk, psm32->pstm));
  2979. }
  2980. else {
  2981. sc = E_OUTOFMEMORY;
  2982. }
  2983. break;
  2984. case TYMED_ISTORAGE:
  2985. vpvUnk = (VPVOID)psm16->pstg;
  2986. RELVDMPTR(vpsm16);
  2987. psm32->pstg =
  2988. (LPSTORAGE)pti->pThkMgr->FindProxy3216(NULL, vpvUnk, NULL,
  2989. INDEX_IIDIDX(THI_IStorage),
  2990. FALSE, NULL);
  2991. if(psm32->pstg) {
  2992. thkDebugOut((DEB_ARGS, "1632 TYMED_ISTORAGE: %p -> %p\n",
  2993. vpvUnk, psm32->pstg));
  2994. }
  2995. else {
  2996. sc = E_OUTOFMEMORY;
  2997. }
  2998. break;
  2999. case TYMED_GDI:
  3000. // if we're in Word6, then we may have already converted the bitmap
  3001. // or palette handle
  3002. if( hGDI == NULL )
  3003. {
  3004. psm32->hBitmap = HBITMAP_32((HBITMAP16)psm16->hBitmap);
  3005. }
  3006. else
  3007. {
  3008. psm32->hBitmap = (HBITMAP)hGDI;
  3009. }
  3010. thkDebugOut((DEB_ARGS, "1632 TYMED_GDI: 0x%04X -> 0x%p\n",
  3011. psm16->hBitmap, psm32->hBitmap));
  3012. RELVDMPTR(vpsm16);
  3013. break;
  3014. case TYMED_NULL:
  3015. RELVDMPTR(vpsm16);
  3016. break;
  3017. default:
  3018. RELVDMPTR(vpsm16);
  3019. sc = E_INVALIDARG;
  3020. break;
  3021. }
  3022. if (FAILED(sc))
  3023. {
  3024. delete psrh;
  3025. }
  3026. else
  3027. {
  3028. if (psrh)
  3029. {
  3030. CLIPFORMAT cf;
  3031. if (pfe)
  3032. {
  3033. cf = pfe->cfFormat;
  3034. }
  3035. else
  3036. {
  3037. cf = CF_INVALID;
  3038. }
  3039. thkAssert(vpvForRelease);
  3040. psrh->Init(pti->pThkMgr, FIXVDMPTR(vpsm16, STGMEDIUM), psm32,
  3041. vpvForRelease, cf);
  3042. RELVDMPTR(vpsm16);
  3043. }
  3044. #if DBG == 1
  3045. if (pfe)
  3046. {
  3047. thkDebugOut((DEB_ARGS, "1632 STGMEDIUM FORMATETC %p {%d}\n",
  3048. pfe, pfe->cfFormat));
  3049. }
  3050. thkDebugOut((DEB_ARGS, "1632 STGMEDIUM: %p {%d, %p, ...} -> "
  3051. "%p {%d, %p, ...}\n", vpsm16, psm16->tymed,
  3052. psm16->pUnkForRelease, psm32, psm32->tymed,
  3053. psm32->pUnkForRelease));
  3054. #endif
  3055. }
  3056. return sc;
  3057. }
  3058. //+---------------------------------------------------------------------------
  3059. //
  3060. // Function: CleanStgMed32, public
  3061. //
  3062. // Synopsis: Cleans up a 32-bit STGMEDIUM
  3063. //
  3064. // Arguments: [pti] - Thunk info
  3065. // [psm32] - STGMEDIUM to clean
  3066. // [vpsm16] - Source STGMEDIUM if thunk
  3067. // [dwSize] - Source size if thunk
  3068. // [fIsThunk] - STGMEDIUM was generated by thunking
  3069. // [pfe] - FORMATETC or NULL
  3070. //
  3071. // Returns: Appropriate status code
  3072. //
  3073. // History: 24-Apr-94 DrewB Created
  3074. //
  3075. //----------------------------------------------------------------------------
  3076. SCODE CleanStgMed32(THUNKINFO *pti,
  3077. STGMEDIUM *psm32,
  3078. VPVOID vpsm16,
  3079. DWORD dwSize,
  3080. BOOL fIsThunk,
  3081. FORMATETC *pfe)
  3082. {
  3083. SCODE sc;
  3084. STGMEDIUM UNALIGNED *psm16;
  3085. HMEM16 hmem16;
  3086. VPVOID vpvUnk;
  3087. BOOL fCleanup = TRUE;
  3088. thkDebugOut((DEB_ITRACE, "In CleanStgMed32(%p, %p, %p, %u, %d, %p)\n",
  3089. pti, psm32, vpsm16, dwSize, fIsThunk, pfe));
  3090. sc = S_OK;
  3091. if(fIsThunk && psm32->pUnkForRelease) {
  3092. // This means that the current call failed
  3093. // Inform the 32-bit punkForRelease created during thunking
  3094. // so that it would cleanup 32-bit STGMEDIUM
  3095. ((CSm32ReleaseHandler *) (psm32->pUnkForRelease))->CallFailed();
  3096. fCleanup = FALSE;
  3097. }
  3098. switch( psm32->tymed )
  3099. {
  3100. case TYMED_HGLOBAL:
  3101. if (fIsThunk &&
  3102. (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
  3103. {
  3104. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3105. hmem16 = (HMEM16)psm16->hGlobal;
  3106. RELVDMPTR(vpsm16);
  3107. Assert(NULL != psm32->hGlobal);
  3108. sc = ConvertHGlobal3216(pti, psm32->hGlobal, 0,
  3109. &hmem16, &dwSize);
  3110. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3111. psm16->hGlobal = (HGLOBAL)hmem16;
  3112. RELVDMPTR(vpsm16);
  3113. }
  3114. if(fCleanup) {
  3115. GlobalFree( psm32->hGlobal );
  3116. psm32->hGlobal = NULL;
  3117. }
  3118. break;
  3119. case TYMED_MFPICT:
  3120. // Chicago uses the same GDI handles for both 32bit and 16bit worlds.
  3121. // Don't delete the handle after a copy since Chicago doesn't actually
  3122. // copy the handle.
  3123. if(fCleanup) {
  3124. #if !defined(_CHICAGO_)
  3125. // Can't modify an MFPICT
  3126. METAFILEPICT *pmfp32;
  3127. pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
  3128. DeleteMetaFile(pmfp32->hMF);
  3129. GlobalUnlock(psm32->hGlobal);
  3130. #endif
  3131. GlobalFree(psm32->hGlobal);
  3132. }
  3133. break;
  3134. case TYMED_FILE:
  3135. Convert_VPSTR_to_LPOLESTR_free( NULL, psm32->lpszFileName );
  3136. #ifdef SM_FREE_16BIT_FILENAME
  3137. if(fCleanup) {
  3138. // 16-bit OLE did not free the filename, so we can't
  3139. // either. This may lead to memory leaks, but there's not
  3140. // really anything we can do about it
  3141. TaskFree16((VPVOID)psm16->lpszFileName);
  3142. }
  3143. #endif
  3144. break;
  3145. case TYMED_ISTREAM:
  3146. if(fIsThunk) {
  3147. // Release the 32-bit stream interface
  3148. psm32->pstm->Release();
  3149. }
  3150. break;
  3151. case TYMED_ISTORAGE:
  3152. if(fIsThunk) {
  3153. // Release the 32-bit storage interface
  3154. psm32->pstg->Release();
  3155. }
  3156. break;
  3157. case TYMED_GDI:
  3158. //
  3159. // No unthunking needed
  3160. //
  3161. break;
  3162. case TYMED_NULL:
  3163. break;
  3164. default:
  3165. // Ignore, this case is handled on input
  3166. thkAssert(!"STGMEDIUM with invalid tymed");
  3167. break;
  3168. }
  3169. if(fIsThunk && psm32->pUnkForRelease) {
  3170. // Release the 32-bit STGMEDIUM pUnkForRelease.
  3171. // 32-bit STGMEDIUM would be cleaned up after the last release
  3172. psm32->pUnkForRelease->Release();
  3173. }
  3174. thkDebugOut((DEB_ITRACE, "Out CleanStgMed32 => 0x%08lX\n", sc));
  3175. return sc;
  3176. }
  3177. //+---------------------------------------------------------------------------
  3178. //
  3179. // Function: ConvertStgMed3216, public
  3180. //
  3181. // Synopsis: Converts a 32-bit STGMEDIUM to 16-bits
  3182. //
  3183. // Arguments: [pti] - Thunk info
  3184. // [psm32] - 32-bit STGMEDIUM
  3185. // [vpsm16] - VDM pointer to 16-bit STGMEDIUM
  3186. // [pfe] - FORMATETC paired with STGMEDIUM or NULL
  3187. // [pdwSize] - Size return
  3188. //
  3189. // Returns: Appropriate status code
  3190. //
  3191. // Modifies: [pdwSize]
  3192. //
  3193. // History: 24-Apr-94 DrewB Created
  3194. //
  3195. // Notes: [pdwSize] is only set for TYMED_HGLOBAL
  3196. //
  3197. //----------------------------------------------------------------------------
  3198. SCODE ConvertStgMed3216(THUNKINFO *pti,
  3199. STGMEDIUM *psm32,
  3200. VPVOID vpsm16,
  3201. FORMATETC *pfe,
  3202. BOOL fPassingOwnershipIn,
  3203. DWORD *pdwSize)
  3204. {
  3205. SCODE sc;
  3206. STGMEDIUM UNALIGNED *psm16;
  3207. VPVOID vpsrh;
  3208. VPSTR vpstr;
  3209. UINT uiSize;
  3210. VPVOID vpvUnkForRelease;
  3211. VPVOID vpvUnk;
  3212. HMEM16 hmem16;
  3213. THKSTATE thkstateSaved;
  3214. sc = S_OK;
  3215. if(psm32->pUnkForRelease) {
  3216. thkDebugOut((DEB_WARN, "pUnkForRelease present in StgMedium3216\n"));
  3217. vpsrh = WOWGlobalAllocLock16(GMEM_MOVEABLE, sizeof(CSm16ReleaseHandler),
  3218. NULL);
  3219. if(vpsrh == 0)
  3220. return E_OUTOFMEMORY;
  3221. }
  3222. else {
  3223. vpsrh = 0;
  3224. }
  3225. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3226. psm16->tymed = psm32->tymed;
  3227. psm16->pUnkForRelease = (IUnknown *)vpsrh;
  3228. RELVDMPTR(vpsm16);
  3229. switch( psm32->tymed )
  3230. {
  3231. case TYMED_HGLOBAL:
  3232. if (pfe && OBJDESC_CF(pfe->cfFormat))
  3233. {
  3234. sc = ConvertObjDesc3216(pti, psm32->hGlobal, &hmem16);
  3235. }
  3236. #if !defined(_CHICAGO_)
  3237. else if (pfe && pfe->cfFormat == CF_HDROP)
  3238. {
  3239. // fix for mapi forms
  3240. sc = ConvertHDrop3216(psm32->hGlobal, &hmem16);
  3241. }
  3242. #endif
  3243. else
  3244. {
  3245. hmem16 = 0;
  3246. sc = ConvertHGlobal3216(pti, psm32->hGlobal, THOP_INOUT,
  3247. &hmem16, pdwSize);
  3248. }
  3249. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3250. psm16->hGlobal = (HGLOBAL)hmem16;
  3251. RELVDMPTR(vpsm16);
  3252. break;
  3253. case TYMED_MFPICT:
  3254. sc = ConvertMfPict3216(pti, psm32->hGlobal, &hmem16);
  3255. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3256. psm16->hGlobal = (HGLOBAL)hmem16;
  3257. RELVDMPTR(vpsm16);
  3258. break;
  3259. case TYMED_FILE:
  3260. uiSize = lstrlenW(psm32->lpszFileName) + 1;
  3261. vpstr = TaskMalloc16( uiSize*2 );
  3262. if ( vpstr == NULL )
  3263. {
  3264. sc = E_OUTOFMEMORY;
  3265. }
  3266. else
  3267. {
  3268. sc = Convert_LPOLESTR_to_VPSTR( psm32->lpszFileName,
  3269. vpstr, uiSize, uiSize*2 );
  3270. if (FAILED(sc))
  3271. {
  3272. TaskFree16(vpstr);
  3273. }
  3274. else
  3275. {
  3276. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3277. psm16->lpszFileName = (LPOLESTR)vpstr;
  3278. RELVDMPTR(vpsm16);
  3279. #if DBG == 1
  3280. thkDebugOut((DEB_ARGS, "3216 TYMED_FILE: '%s' (%ws)\n",
  3281. WOWFIXVDMPTR(vpstr, 0),
  3282. psm32->lpszFileName));
  3283. WOWRELVDMPTR(vpstr);
  3284. #endif
  3285. }
  3286. }
  3287. break;
  3288. case TYMED_ISTREAM:
  3289. vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstm, NULL,
  3290. INDEX_IIDIDX(THI_IStream),
  3291. NULL);
  3292. if (vpvUnk == 0)
  3293. {
  3294. sc = E_OUTOFMEMORY;
  3295. }
  3296. else
  3297. {
  3298. thkDebugOut((DEB_ARGS, "3216 TYMED_ISTREAM: %p -> %p\n",
  3299. psm32->pstm, vpvUnk));
  3300. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3301. psm16->pstm = (IStream *)vpvUnk;
  3302. RELVDMPTR(vpsm16);
  3303. }
  3304. break;
  3305. case TYMED_ISTORAGE:
  3306. vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstg, NULL,
  3307. INDEX_IIDIDX(THI_IStorage),
  3308. NULL);
  3309. if (vpvUnk == 0)
  3310. {
  3311. sc = E_OUTOFMEMORY;
  3312. }
  3313. else
  3314. {
  3315. thkDebugOut((DEB_ARGS, "3216 TYMED_ISTORAGE: %p -> %p\n",
  3316. psm32->pstg, vpvUnk));
  3317. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3318. psm16->pstg = (IStorage *)vpvUnk;
  3319. RELVDMPTR(vpsm16);
  3320. }
  3321. break;
  3322. case TYMED_GDI:
  3323. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3324. psm16->hBitmap = (HBITMAP)HBITMAP_16(psm32->hBitmap);
  3325. thkDebugOut((DEB_ARGS, "3216 TYMED_GDI: 0x%p -> 0x%04X\n",
  3326. psm32->hBitmap, psm16->hBitmap));
  3327. RELVDMPTR(vpsm16);
  3328. break;
  3329. case TYMED_NULL:
  3330. break;
  3331. default:
  3332. sc = E_INVALIDARG;
  3333. break;
  3334. }
  3335. if (FAILED(sc))
  3336. {
  3337. if (vpsrh != 0)
  3338. {
  3339. WOWGlobalUnlockFree16(vpsrh);
  3340. }
  3341. }
  3342. else
  3343. {
  3344. if (vpsrh != 0)
  3345. {
  3346. CSm16ReleaseHandler UNALIGNED *psrh;
  3347. CLIPFORMAT cf;
  3348. if (pfe)
  3349. {
  3350. cf = pfe->cfFormat;
  3351. }
  3352. else
  3353. {
  3354. cf = CF_INVALID;
  3355. }
  3356. thkAssert(psm32->pUnkForRelease);
  3357. psrh = FIXVDMPTR(vpsrh, CSm16ReleaseHandler);
  3358. psrh->Init(pti->pThkMgr, psm32, FIXVDMPTR(vpsm16, STGMEDIUM),
  3359. psm32->pUnkForRelease, cf);
  3360. RELVDMPTR(vpsrh);
  3361. RELVDMPTR(vpsm16);
  3362. }
  3363. #if DBG == 1
  3364. if (pfe)
  3365. {
  3366. thkDebugOut((DEB_ARGS, "3216 STGMEDIUM FORMATETC %p {%d}\n",
  3367. pfe, pfe->cfFormat));
  3368. }
  3369. thkDebugOut((DEB_ARGS, "3216 STGMEDIUM: %p {%d, %p, ...} -> "
  3370. "%p {%d, %p, ...}\n", psm32, psm32->tymed,
  3371. psm32->pUnkForRelease, vpsm16, psm16->tymed,
  3372. psm16->pUnkForRelease));
  3373. #endif
  3374. }
  3375. return sc;
  3376. }
  3377. //+---------------------------------------------------------------------------
  3378. //
  3379. // Function: CleanStgMed16, public
  3380. //
  3381. // Synopsis: Frees up resources in a 16-bit STGMEDIUM
  3382. //
  3383. // Arguments: [pti] - Thunk info
  3384. // [vpsm16] - STGMEDIUM to clean
  3385. // [psm32] - Source STGMEDIUM if thunk
  3386. // [dwSize] - Source size for thunked HGLOBAL
  3387. // [fIsThunk] - If the STGMEDIUM is a result of thunking
  3388. // [pfe] - FORMATETC or NULL
  3389. //
  3390. // Returns: Appropriate status code
  3391. //
  3392. // History: 24-Apr-94 DrewB Created
  3393. //
  3394. //----------------------------------------------------------------------------
  3395. SCODE CleanStgMed16(THUNKINFO *pti,
  3396. VPVOID vpsm16,
  3397. STGMEDIUM *psm32,
  3398. DWORD dwSize,
  3399. BOOL fIsThunk,
  3400. FORMATETC *pfe)
  3401. {
  3402. SCODE sc;
  3403. STGMEDIUM UNALIGNED *psm16;
  3404. VPVOID vpvUnk, vpv;
  3405. HMEM16 hmem16;
  3406. BOOL fCleanup = TRUE;
  3407. thkDebugOut((DEB_ITRACE, "In CleanStgMed16(%p, %p, %p, %u, %d, %p)\n",
  3408. pti, vpsm16, psm32, dwSize, fIsThunk, pfe));
  3409. sc = S_OK;
  3410. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3411. vpvUnk = (VPVOID)psm16->pUnkForRelease;
  3412. RELVDMPTR(vpsm16);
  3413. if (fIsThunk && vpvUnk)
  3414. {
  3415. // This means that the current call failed
  3416. // Inform the 32-bit punkForRelease created during thunking
  3417. // so that it would cleanup 32-bit STGMEDIUM
  3418. CSm16ReleaseHandler UNALIGNED *psrh;
  3419. psrh = FIXVDMPTR(vpvUnk, CSm16ReleaseHandler);
  3420. psrh->CallFailed();
  3421. RELVDMPTR(vpvUnk);
  3422. fCleanup = FALSE;
  3423. }
  3424. psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
  3425. switch( psm16->tymed )
  3426. {
  3427. case TYMED_HGLOBAL:
  3428. hmem16 = (HMEM16)psm16->hGlobal;
  3429. RELVDMPTR(vpsm16);
  3430. if (fIsThunk &&
  3431. (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
  3432. {
  3433. sc = ConvertHGlobal1632(pti, hmem16, 0,
  3434. &psm32->hGlobal, &dwSize);
  3435. }
  3436. if(fCleanup)
  3437. WOWGlobalFree16(hmem16);
  3438. break;
  3439. case TYMED_MFPICT:
  3440. hmem16 = (HMEM16)psm16->hGlobal;
  3441. RELVDMPTR(vpsm16);
  3442. // Chicago uses the same GDI handles for both 32bit and 16bit worlds.
  3443. // Don't delete the handle after a copy since Chicago doesn't actually
  3444. // copy the handle.
  3445. if(fCleanup) {
  3446. #if !defined(_CHICAGO_)
  3447. VPVOID vpvmfp16;
  3448. METAFILEPICT16 *pmfp16;
  3449. HMEM16 hmf16;
  3450. vpvmfp16 = WOWGlobalLock16(hmem16);
  3451. pmfp16 = FIXVDMPTR(vpvmfp16, METAFILEPICT16);
  3452. hmf16 = pmfp16->hMF;
  3453. RELVDMPTR(vpvmfp16);
  3454. // Relies on the fact that a 16-bit metafile is an HGLOBAL
  3455. WOWGlobalFree16(hmf16);
  3456. WOWGlobalUnlockFree16(vpvmfp16);
  3457. #else
  3458. WOWGlobalFree16(hmem16);
  3459. #endif
  3460. }
  3461. break;
  3462. case TYMED_FILE:
  3463. vpv = (VPVOID)psm16->lpszFileName;
  3464. RELVDMPTR(vpsm16);
  3465. if(fCleanup)
  3466. TaskFree16(vpv);
  3467. break;
  3468. case TYMED_ISTREAM:
  3469. vpv = (VPVOID) psm16->pstm;
  3470. RELVDMPTR(vpsm16);
  3471. if(fIsThunk) {
  3472. // Release the 16-bit stream interface
  3473. ReleaseOnObj16(vpv);
  3474. }
  3475. break;
  3476. case TYMED_ISTORAGE:
  3477. vpv = (VPVOID) psm16->pstg;
  3478. RELVDMPTR(vpsm16);
  3479. if(fIsThunk) {
  3480. // Release the 16-bit storage interface
  3481. ReleaseOnObj16(vpv);
  3482. }
  3483. break;
  3484. case TYMED_GDI:
  3485. RELVDMPTR(vpsm16);
  3486. //
  3487. // No unthunking needed
  3488. //
  3489. break;
  3490. case TYMED_NULL:
  3491. RELVDMPTR(vpsm16);
  3492. break;
  3493. default:
  3494. // Ignore, this case is handled on input
  3495. thkAssert(!"CleanStgMed16 with invalid tymed");
  3496. break;
  3497. }
  3498. if(fIsThunk && vpvUnk) {
  3499. // Release the 16-bit STGMEDIUM vpvForRelease.
  3500. // 16-bit STGMEDIUM would be cleaned up after the last release
  3501. ReleaseOnObj16(vpvUnk);
  3502. }
  3503. thkDebugOut((DEB_ITRACE, "Out CleanStgMed16 => 0x%08lX\n", sc));
  3504. return sc;
  3505. }
  3506. //+---------------------------------------------------------------------------
  3507. //
  3508. // Function: ConvertFetc1632, public
  3509. //
  3510. // Synopsis: Converts a FORMATETC
  3511. //
  3512. // Arguments: [pti] - Thunk info
  3513. // [vpfe16] - FORMATETC
  3514. // [pfe32] - FORMATETC
  3515. // [fFree] - Free resources as converting
  3516. //
  3517. // Returns: Appropriate status code
  3518. //
  3519. // Modifies: [pfe32]
  3520. //
  3521. // History: 14-May-94 DrewB Created
  3522. // 11-Dec-00 DickD initialize pdv32 (prefix bug 22397)
  3523. //
  3524. //----------------------------------------------------------------------------
  3525. SCODE ConvertFetc1632(THUNKINFO *pti,
  3526. VPVOID vpfe16,
  3527. FORMATETC *pfe32,
  3528. BOOL fFree)
  3529. {
  3530. FORMATETC16 UNALIGNED *pfe16;
  3531. VPVOID vpdv16;
  3532. DVTARGETDEVICE *pdv32 = NULL;
  3533. UINT cbSize;
  3534. SCODE sc;
  3535. pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
  3536. vpdv16 = (VPVOID)pfe16->ptd;
  3537. RELVDMPTR(vpfe16);
  3538. if ( vpdv16 == 0 )
  3539. {
  3540. pdv32 = NULL;
  3541. }
  3542. else
  3543. {
  3544. sc = ConvertDvtd1632(pti, vpdv16, ArTask32, FrTask32,
  3545. &pdv32, &cbSize);
  3546. if (fFree)
  3547. {
  3548. TaskFree16(vpdv16);
  3549. }
  3550. if (FAILED(sc))
  3551. {
  3552. return sc;
  3553. }
  3554. }
  3555. pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
  3556. pfe32->cfFormat = pfe16->cfFormat;
  3557. pfe32->ptd = pdv32;
  3558. pfe32->dwAspect = pfe16->dwAspect;
  3559. pfe32->lindex = pfe16->lindex;
  3560. pfe32->tymed = pfe16->tymed;
  3561. thkDebugOut((DEB_ARGS, "1632 FORMATETC: "
  3562. "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
  3563. vpfe16, pfe32,
  3564. pfe32->cfFormat,
  3565. pfe32->ptd, vpdv16,
  3566. pfe32->dwAspect,
  3567. pfe32->lindex,
  3568. pfe32->tymed));
  3569. RELVDMPTR(vpfe16);
  3570. return S_OK;
  3571. }
  3572. //+---------------------------------------------------------------------------
  3573. //
  3574. // Function: ConvertFetc3216, public
  3575. //
  3576. // Synopsis: Converts a FORMATETC
  3577. //
  3578. // Arguments: [pti] - Thunk info
  3579. // [pfe32] - FORMATETC
  3580. // [vpfe16] - FORMATETC
  3581. // [fFree] - Free resources as converting
  3582. //
  3583. // Returns: Appropriate status code
  3584. //
  3585. // Modifies: [vpfe16]
  3586. //
  3587. // History: 14-May-94 DrewB Created
  3588. //
  3589. //----------------------------------------------------------------------------
  3590. SCODE ConvertFetc3216(THUNKINFO *pti,
  3591. FORMATETC *pfe32,
  3592. VPVOID vpfe16,
  3593. BOOL fFree)
  3594. {
  3595. FORMATETC16 UNALIGNED *pfe16;
  3596. DVTARGETDEVICE *pdv32;
  3597. SCODE sc;
  3598. VPVOID vpdv16;
  3599. UINT cbSize;
  3600. pdv32 = pfe32->ptd;
  3601. if (pdv32 != NULL)
  3602. {
  3603. sc = ConvertDvtd3216(pti, pdv32, ArTask16, FrTask16,
  3604. &vpdv16, &cbSize);
  3605. if (fFree)
  3606. {
  3607. TaskFree32(pdv32);
  3608. }
  3609. if (FAILED(sc))
  3610. {
  3611. return sc;
  3612. }
  3613. }
  3614. else
  3615. {
  3616. vpdv16 = 0;
  3617. }
  3618. pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
  3619. pfe16->cfFormat = pfe32->cfFormat;
  3620. pfe16->ptd = vpdv16;
  3621. pfe16->dwAspect = pfe32->dwAspect;
  3622. pfe16->lindex = pfe32->lindex;
  3623. pfe16->tymed = pfe32->tymed;
  3624. thkDebugOut((DEB_ARGS, "3216 FORMATETC: "
  3625. "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
  3626. pfe32, vpfe16,
  3627. pfe16->cfFormat,
  3628. vpdv16, pdv32,
  3629. pfe16->dwAspect,
  3630. pfe16->lindex,
  3631. pfe16->tymed));
  3632. RELVDMPTR(vpfe16);
  3633. return S_OK;
  3634. }
  3635. //+---------------------------------------------------------------------------
  3636. //
  3637. // Function: DebugValidateProxy1632, debug public
  3638. //
  3639. // Synopsis: Validates a 16->32 proxy pointer and its memory
  3640. //
  3641. // Arguments: [vpvProxy] - Proxy
  3642. //
  3643. // History: 07-Jul-94 DrewB Created
  3644. //
  3645. //----------------------------------------------------------------------------
  3646. #if DBG == 1
  3647. void DebugValidateProxy1632(VPVOID vpvProxy)
  3648. {
  3649. THUNK1632OBJ UNALIGNED *pto;
  3650. THUNKINFO ti;
  3651. thkAssert(vpvProxy != 0 && "Invalid proxy pointer");
  3652. pto = (THUNK1632OBJ UNALIGNED *)
  3653. GetReadWritePtr16(&ti, vpvProxy, sizeof(THUNK1632OBJ));
  3654. thkAssert(pto != NULL && "Invalid proxy pointer");
  3655. thkAssert(pto->dwSignature == PSIG1632 && "Dead or invalid proxy!");
  3656. thkAssert(pto->cRefLocal>=0 && "Invalid proxy refcount");
  3657. thkAssert(pto->cRefLocal>=pto->cRef && "Invalid proxy refcount");
  3658. thkAssert((pto->cRefLocal>0 && pto->cRef>0) || (pto->cRef==0 && pto->cRefLocal==0));
  3659. thkAssert(pto->pphHolder && "Proxy without a holder");
  3660. if (!IsValidInterface(pto->punkThis32))
  3661. {
  3662. thkDebugOut((DEB_ERROR, "1632 %p: Invalid proxied object %p\n",
  3663. vpvProxy, pto->punkThis32));
  3664. }
  3665. WOWRELVDMPTR(vpvProxy);
  3666. }
  3667. #endif
  3668. //+---------------------------------------------------------------------------
  3669. //
  3670. // Function: DebugValidateProxy3216, debug public
  3671. //
  3672. // Synopsis: Validates a 32->16 proxy pointer and its memory
  3673. //
  3674. // Arguments: [pto] - Proxy
  3675. //
  3676. // History: 07-Jul-94 DrewB Created
  3677. //
  3678. //----------------------------------------------------------------------------
  3679. #if DBG == 1
  3680. void DebugValidateProxy3216(THUNK3216OBJ *pto)
  3681. {
  3682. THUNKINFO ti;
  3683. thkAssert(pto != 0 && "Invalid proxy pointer");
  3684. thkAssert(!IsBadReadPtr(pto, sizeof(THUNK3216OBJ)) &&
  3685. !IsBadWritePtr(pto, sizeof(THUNK3216OBJ)) &&
  3686. "Invalid proxy pointer");
  3687. thkAssert(pto->dwSignature == PSIG3216 && "Dead or invalid proxy!");
  3688. thkAssert(pto->cRefLocal>=0 && "Invalid proxy refcount");
  3689. thkAssert(pto->cRefLocal>=pto->cRef && "Invalid proxy refcount");
  3690. thkAssert((pto->cRefLocal>0 && pto->cRef>0) || (pto->cRef==0 && pto->cRefLocal==0));
  3691. thkAssert(pto->pphHolder && "Proxy without a holder");
  3692. if (!IsValidInterface16(&ti, pto->vpvThis16))
  3693. {
  3694. thkDebugOut((DEB_ERROR, "3216 %p: Invalid proxied object %p\n",
  3695. pto, pto->vpvThis16));
  3696. }
  3697. }
  3698. #endif
  3699. //+---------------------------------------------------------------------------
  3700. //
  3701. // Function: ClampLongToShort, public
  3702. //
  3703. // Synopsis: Restricts a long value to a short value by clamping
  3704. //
  3705. // Arguments: [l] - Long
  3706. //
  3707. // Returns: Short
  3708. //
  3709. // History: 16-Aug-94 DrewB Created
  3710. //
  3711. //----------------------------------------------------------------------------
  3712. SHORT ClampLongToShort(LONG l)
  3713. {
  3714. SHORT s;
  3715. if (l < SHRT_MIN)
  3716. {
  3717. s = SHRT_MIN;
  3718. thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
  3719. }
  3720. else if (l > SHRT_MAX)
  3721. {
  3722. s = SHRT_MAX;
  3723. thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
  3724. }
  3725. else
  3726. {
  3727. s = (SHORT)l;
  3728. }
  3729. return s;
  3730. }
  3731. //+---------------------------------------------------------------------------
  3732. //
  3733. // Function: ClampULongToUShort, public
  3734. //
  3735. // Synopsis: Restricts an unsigned long value to an unsigned short value
  3736. // by clamping
  3737. //
  3738. // Arguments: [ul] - Long
  3739. //
  3740. // Returns: UShort
  3741. //
  3742. // History: 16-Aug-94 DrewB Created
  3743. //
  3744. //----------------------------------------------------------------------------
  3745. USHORT ClampULongToUShort(ULONG ul)
  3746. {
  3747. USHORT us;
  3748. if (ul > USHRT_MAX)
  3749. {
  3750. us = USHRT_MAX;
  3751. thkDebugOut((DEB_WARN, "ClampULongToUShort: %ld -> %d\n", ul, us));
  3752. }
  3753. else
  3754. {
  3755. us = (USHORT)ul;
  3756. }
  3757. return us;
  3758. }
  3759. //+---------------------------------------------------------------------------
  3760. //
  3761. // Function: ConvertObjDescriptor
  3762. //
  3763. // Synopsis: Exported API called by WOW to convert ObjectDescriptors to
  3764. // the indicated format.
  3765. //
  3766. //
  3767. // Arguments: [hMem] -- Handle to the ObjectDescriptor to convert.
  3768. // [flag] -- Flag indicating which direction the convertion
  3769. // should take place. Valid values are:
  3770. // CFOLE_UNICODE_TO_ANSI.
  3771. // CFOLE_ANSI_TO_UNICODE.
  3772. //
  3773. // Returns: HGLOBAL to the converted ObjectDescriptor,
  3774. // or NULL on failure.
  3775. //
  3776. // History: 8-16-94 terryru Created
  3777. //
  3778. // Notes:
  3779. //
  3780. //----------------------------------------------------------------------------
  3781. STDAPI_(HGLOBAL) ConvertObjDescriptor( HANDLE hMem, UINT flag )
  3782. {
  3783. const UINT CFOLE_UNICODE_TO_ANSI = 0;
  3784. const UINT CFOLE_ANSI_TO_UNICODE = 1;
  3785. THUNKINFO ti;
  3786. HGLOBAL hMem32;
  3787. HMEM16 hMem16;
  3788. switch ( flag )
  3789. {
  3790. case CFOLE_UNICODE_TO_ANSI:
  3791. if( FAILED( ConvertObjDesc3216( &ti, (HGLOBAL) hMem, &hMem16 )))
  3792. {
  3793. return (HGLOBAL) NULL;
  3794. }
  3795. else
  3796. {
  3797. return (HGLOBAL) hMem16;
  3798. }
  3799. break;
  3800. case CFOLE_ANSI_TO_UNICODE:
  3801. if( FAILED( ConvertObjDesc1632( &ti, (HMEM16) hMem, &hMem32 )))
  3802. {
  3803. return (HGLOBAL) NULL;
  3804. }
  3805. else
  3806. {
  3807. return (HGLOBAL) hMem32;
  3808. }
  3809. break;
  3810. default:
  3811. thkAssert(!"ConvertObjDescriptor, Invalid flag");
  3812. break;
  3813. }
  3814. return (HGLOBAL) NULL;
  3815. }
  3816. #if defined(_CHICAGO_)
  3817. //
  3818. // A hack so everyone can build Chicago OLE until I write the thunking
  3819. // library later this week.
  3820. //
  3821. // (15-Feb-2000: I find the fact that this comment is still here amazingly
  3822. // entertaining - JohnDoty)
  3823. //
  3824. #define ERR ((char*) -1)
  3825. #if DBG==1
  3826. int UnicodeToAnsi(LPSTR sz, LPCWSTR pwsz, LONG cb)
  3827. {
  3828. int ret;
  3829. ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL);
  3830. thkAssert(ret != 0 && "Lost characters in thk Unicode->Ansi conversion");
  3831. if (ret == 0)
  3832. {
  3833. DebugBreak();
  3834. }
  3835. return ret;
  3836. }
  3837. #else
  3838. #define UnicodeToAnsi(sz,pwsz,cb) WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL)
  3839. #endif
  3840. #if DBG==1
  3841. int AnsiToUnicode(LPWSTR pwsz, LPCSTR sz, LONG cb)
  3842. {
  3843. int ret;
  3844. ret = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb);
  3845. thkAssert(ret != 0 && "Lost characters in thk Ansi->Unicode conversion");
  3846. if (ret == 0)
  3847. {
  3848. DebugBreak();
  3849. }
  3850. return ret;
  3851. }
  3852. #else
  3853. #define AnsiToUnicode(pwsz,sz,cb) MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb)
  3854. #endif
  3855. extern "C"
  3856. DWORD
  3857. WINAPI
  3858. GetShortPathNameX(
  3859. LPCWSTR lpszFullPath,
  3860. LPWSTR lpszShortPath,
  3861. DWORD cchBuffer
  3862. )
  3863. {
  3864. #ifdef DEBUG_OUTPUT
  3865. OutputDebugString("GetShortPathName\n");
  3866. #endif
  3867. CHAR szFullPath[MAX_PATH];
  3868. CHAR szShortBuffer[MAX_PATH];
  3869. DWORD ret;
  3870. UnicodeToAnsi(szFullPath, lpszFullPath, sizeof(szFullPath));
  3871. if (lpszShortPath == NULL)
  3872. {
  3873. ret = GetShortPathNameA(szFullPath, NULL, cchBuffer);
  3874. }
  3875. else
  3876. {
  3877. ret = GetShortPathNameA(szFullPath, szShortBuffer,
  3878. sizeof(szShortBuffer));
  3879. thkAssert(ret != cchBuffer &&
  3880. "GetShortPathName - Output buffer too short");
  3881. //
  3882. // Don't convert the buffer if the
  3883. // call to GetShortPathNameA() failed.
  3884. //
  3885. if(0 != ret)
  3886. {
  3887. //
  3888. // Only convert the actual data, not the whole buffer.
  3889. //
  3890. if (cchBuffer > ret + 1)
  3891. cchBuffer = ret + 1;
  3892. AnsiToUnicode(lpszShortPath, szShortBuffer, cchBuffer);
  3893. }
  3894. }
  3895. return ret;
  3896. }
  3897. #endif // _CHICAGO_