Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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