Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3670 lines
119 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: cthkmgr.cxx
  7. //
  8. // Contents: cthunkmanager for an apartment
  9. //
  10. // Classes: CThkMgr derived from IThunkManager
  11. //
  12. // Functions:
  13. //
  14. // History: 5-18-94 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "headers.cxx"
  18. #pragma hdrstop
  19. #include <olepfn.hxx>
  20. #if DBG == 1
  21. BOOL fDebugDump = FALSE;
  22. #define DBG_DUMP(x) if (fDebugDump) { x; }
  23. #else
  24. #define DBG_DUMP(x)
  25. #endif
  26. #define PprxNull(pprx) (((pprx).wType = PPRX_NONE), ((pprx).dwPtrVal = 0))
  27. #define PprxIsNull(pprx) ((pprx).dwPtrVal == 0)
  28. #define Pprx16(vpv) PROXYPTR((DWORD)vpv, PPRX_16)
  29. #define Pprx32(pto) PROXYPTR((DWORD)pto, PPRX_32)
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Function: ResolvePprx, public
  33. //
  34. // Synopsis: Converts a PROXYPTR to a CProxy *
  35. //
  36. // Arguments: [ppprx] - PROXYPTR
  37. //
  38. // Returns: Pointer or NULL
  39. //
  40. // History: 15-Jul-94 DrewB Created
  41. //
  42. //----------------------------------------------------------------------------
  43. CProxy *ResolvePprx(PROXYPTR *ppprx)
  44. {
  45. if (ppprx->wType == PPRX_32)
  46. {
  47. return (CProxy *)ppprx->dwPtrVal;
  48. }
  49. else
  50. {
  51. // Get a pointer to all of the proxy rather than just the CProxy part
  52. return FIXVDMPTR(ppprx->dwPtrVal, THUNK1632OBJ);
  53. }
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Function: ReleasePprx, public
  58. //
  59. // Synopsis: Releases a resolved PROXYPTR
  60. //
  61. // Arguments: [ppprx] - PROXYPTR
  62. //
  63. // History: 10-Oct-94 DrewB Created
  64. //
  65. //----------------------------------------------------------------------------
  66. void ReleasePprx(PROXYPTR *ppprx)
  67. {
  68. if (ppprx->wType == PPRX_16)
  69. {
  70. RELVDMPTR(ppprx->dwPtrVal);
  71. }
  72. }
  73. //+---------------------------------------------------------------------------
  74. //
  75. // Member: CThkMgr::NewHolder, public
  76. //
  77. // Synopsis: Creates a new proxy holder
  78. //
  79. // Arguments: [pUnk] - IUnknown ptr
  80. // [punkProxy] - IUnknown proxy
  81. // [dwFlags] - Flags
  82. //
  83. // Returns: Holder or NULL
  84. //
  85. // History: 19-Mar-97 Gopalk Rewritten to support object identity
  86. //
  87. //----------------------------------------------------------------------------
  88. PROXYHOLDER *CThkMgr::NewHolder(VPVOID pUnk, PROXYPTR unkProxy, DWORD dwFlags)
  89. {
  90. thkDebugOut((DEB_THUNKMGR, "%sIn CThkMgr::NewHolder(0x%X)\n",
  91. NestingLevelString(), dwFlags));
  92. DebugIncrementNestingLevel();
  93. // Local variables
  94. PROXYHOLDER *pph;
  95. CProxy *proxy;
  96. // Allocate a new holder
  97. pph = (PROXYHOLDER *)flHolderFreeList.AllocElement();
  98. if(pph) {
  99. // Initialize
  100. pph->dwFlags = dwFlags;
  101. pph->cProxies = 0;
  102. pph->unkProxy = unkProxy;
  103. PprxNull(pph->pprxProxies);
  104. // Establish the identity of the new holder
  105. if(_pHolderTbl->SetAt((DWORD)pUnk, pph)) {
  106. // Add the IUnknown proxy to the new holder
  107. proxy = ResolvePprx(&unkProxy);
  108. if (proxy) {
  109. AddProxyToHolder(pph, proxy, unkProxy);
  110. ReleasePprx(&unkProxy);
  111. }
  112. else {
  113. _pHolderTbl->RemoveKey((DWORD)pUnk);
  114. flHolderFreeList.FreeElement((DWORD)pph);
  115. }
  116. }
  117. else {
  118. // Free the newly allocated holder
  119. flHolderFreeList.FreeElement((DWORD)pph);
  120. }
  121. }
  122. DebugDecrementNestingLevel();
  123. thkDebugOut((DEB_THUNKMGR, "%sOut CThkMgr::NewHolder => %p\n",
  124. NestingLevelString(), pph));
  125. return pph;
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Member: CThkMgr::AddProxyToHolder, public
  130. //
  131. // Synopsis: Adds a new proxy to a holder
  132. //
  133. // Arguments: [pph] - Holder
  134. // [pprxReal] - Proxy
  135. // [pprx] - Abstract pointer
  136. //
  137. // History: 07-Jul-94 DrewB Extracted
  138. //
  139. //----------------------------------------------------------------------------
  140. void CThkMgr::AddProxyToHolder(PROXYHOLDER *pph, CProxy *pprxReal, PROXYPTR &pprx)
  141. {
  142. thkDebugOut((DEB_THUNKMGR, "%sIn AddProxyToHolder(%p, %p) cProxies %d\n",
  143. NestingLevelString(), pph, pprx.dwPtrVal, pph->cProxies));
  144. DebugIncrementNestingLevel();
  145. thkAssert(ResolvePprx(&pprx) == pprxReal &&
  146. (ReleasePprx(&pprx), TRUE));
  147. // Bump count of held proxies
  148. AddRefHolder(pph);
  149. // Add proxy into list of object proxies
  150. thkAssert(PprxIsNull(pprxReal->pprxObject));
  151. pprxReal->pprxObject = pph->pprxProxies;
  152. pph->pprxProxies = pprx;
  153. thkAssert(pprxReal->pphHolder == NULL);
  154. pprxReal->pphHolder = pph;
  155. DebugDecrementNestingLevel();
  156. thkDebugOut((DEB_THUNKMGR, "%sout AddProxyToHolder(%p, %p) cProxies %d\n",
  157. NestingLevelString(), pph, pprx.dwPtrVal, pph->cProxies));
  158. }
  159. //+---------------------------------------------------------------------------
  160. //
  161. // Member: CThkMgr::AddRefHolder, public
  162. //
  163. // Synopsis: Increments the proxy count for a holder
  164. //
  165. // Arguments: [pph] - Holder
  166. //
  167. // History: 07-Jul-94 DrewB Created
  168. //
  169. //----------------------------------------------------------------------------
  170. void CThkMgr::AddRefHolder(PROXYHOLDER *pph)
  171. {
  172. pph->cProxies++;
  173. thkDebugOut((DEB_THUNKMGR, "%sAddRefHolder(%p) cProxies %d\n",
  174. NestingLevelString(), pph, pph->cProxies));
  175. }
  176. //+---------------------------------------------------------------------------
  177. //
  178. // Method: CThkMgr::ReleaseHolder, public
  179. //
  180. // Synopsis: Releases a proxy reference on the holder
  181. // Cleans up the holder if it was the last reference
  182. //
  183. // Arguments: [pph] - Holder
  184. //
  185. // History: 19-Mar-97 Gopalk Rewritten to support object identity
  186. //
  187. //----------------------------------------------------------------------------
  188. void CThkMgr::ReleaseHolder(PROXYHOLDER *pph, DWORD ProxyType)
  189. {
  190. thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseHolder(%p) pre cProxies %d\n",
  191. NestingLevelString(), pph, pph->cProxies));
  192. DebugIncrementNestingLevel();
  193. // Validation checks
  194. thkAssert(pph->cProxies > 0);
  195. if(ProxyType == PROXYFLAG_PUNKINNER) {
  196. thkAssert(pph->dwFlags & PH_AGGREGATEE);
  197. }
  198. // Decrement holder proxy count
  199. pph->cProxies--;
  200. if(pph->cProxies==0 && !(pph->dwFlags & PH_IDREVOKED)) {
  201. // All interfaces on the object have been released
  202. DWORD dwUnk;
  203. // Mark the holder as zombie
  204. pph->dwFlags |= PH_IDREVOKED;
  205. // Revoke the identity of the holder
  206. if(pph->dwFlags & PH_AGGREGATEE) {
  207. dwUnk = pph->unkProxy.dwPtrVal;
  208. }
  209. else if(pph->unkProxy.wType == PPRX_16) {
  210. THUNK1632OBJ UNALIGNED *Id1632;
  211. Id1632 = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  212. thkAssert(Id1632);
  213. dwUnk = (DWORD) Id1632->punkThis32;
  214. RELVDMPTR(pph->unkProxy.dwPtrVal);
  215. }
  216. else {
  217. thkAssert(pph->unkProxy.wType == PPRX_32);
  218. dwUnk = ((THUNK3216OBJ *) pph->unkProxy.dwPtrVal)->vpvThis16;
  219. }
  220. #if DBG==1
  221. thkAssert(_pHolderTbl->RemoveKey(dwUnk));
  222. #else
  223. _pHolderTbl->RemoveKey(dwUnk);
  224. #endif
  225. }
  226. if(pph->cProxies==0 && ProxyType!=PROXYFLAG_NONE) {
  227. // Not a nested release
  228. CProxy *pprxReal;
  229. PROXYPTR pprx, pprxNext;
  230. // Release all the proxies under the holder
  231. pprx = pph->pprxProxies;
  232. while(!PprxIsNull(pprx)) {
  233. pprxReal = ResolvePprx(&pprx);
  234. thkAssert(pprxReal && "pprx points to an invalid address!");
  235. if (pprxReal) {
  236. pprxNext = pprxReal->pprxObject;
  237. thkAssert(pprxReal->cRefLocal == 0);
  238. thkAssert(pprxReal->pphHolder == pph);
  239. // Remove the proxy
  240. if(pprx.wType == PPRX_16) {
  241. // 1632 proxy
  242. RemoveProxy1632((VPVOID)pprx.dwPtrVal, (THUNK1632OBJ *)pprxReal);
  243. }
  244. else {
  245. // 3216 proxy
  246. RemoveProxy3216((THUNK3216OBJ *)pprxReal);
  247. }
  248. pprx = pprxNext;
  249. }
  250. else
  251. break;
  252. }
  253. // By now, proxy count should be zero
  254. thkAssert(pph->cProxies == 0);
  255. // Return holder to free list
  256. flHolderFreeList.FreeElement((DWORD)pph);
  257. }
  258. DebugDecrementNestingLevel();
  259. thkDebugOut((DEB_THUNKMGR, "%sOUT ReleaseHolder\n", NestingLevelString()));
  260. return;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Method: CThkMgr::Create
  265. //
  266. // Synopsis: static member - creates complete thunkmanager
  267. //
  268. // Arguments: [void] --
  269. //
  270. // Returns: pointer to cthkmgr
  271. //
  272. // History: 6-01-94 JohannP (Johann Posch) Created
  273. // 3-14-97 Gopalk Added Holder table
  274. //
  275. // Notes:
  276. //
  277. //----------------------------------------------------------------------------
  278. CThkMgr *CThkMgr::Create(void)
  279. {
  280. CThkMgr *pcthkmgr = NULL;
  281. CMapDwordPtr *pPT1632 = new CMapDwordPtr(MEMCTX_TASK);
  282. CMapDwordPtr *pPT3216 = new CMapDwordPtr(MEMCTX_TASK);
  283. CMapDwordPtr *pHT = new CMapDwordPtr(MEMCTX_TASK);
  284. if ( (pPT1632 != NULL)
  285. && (pPT3216 != NULL)
  286. && (pHT != NULL)
  287. && (pcthkmgr = new CThkMgr( pPT1632, pPT3216, pHT )) )
  288. {
  289. // install the new thunkmanager
  290. TlsThkSetThkMgr(pcthkmgr);
  291. }
  292. else
  293. {
  294. if (pPT1632)
  295. {
  296. delete pPT1632;
  297. }
  298. if (pPT3216)
  299. {
  300. delete pPT3216;
  301. }
  302. if(pHT)
  303. {
  304. delete pHT;
  305. }
  306. }
  307. return pcthkmgr;
  308. }
  309. //+---------------------------------------------------------------------------
  310. //
  311. // Method: CThkMgr::CThkMgr
  312. //
  313. // Synopsis: private constructor - called by Create
  314. //
  315. // Arguments: [pPT1632] -- 16/32 proxy table
  316. // [pPT3216] -- 32/16 proxy table
  317. //
  318. // History: 6-01-94 JohannP (Johann Posch) Created
  319. // 3-14-97 Gopalk Added Holder table
  320. //
  321. //----------------------------------------------------------------------------
  322. CThkMgr::CThkMgr(CMapDwordPtr *pPT1632,
  323. CMapDwordPtr *pPT3216,
  324. CMapDwordPtr *pHT)
  325. {
  326. _cRefs = 1;
  327. _thkstate = THKSTATE_NOCALL;
  328. _dwState = CALLBACK_ALLOWED;
  329. _piidnode = NULL;
  330. _pProxyTbl1632 = pPT1632;
  331. _pProxyTbl3216 = pPT3216;
  332. _pHolderTbl = pHT;
  333. _pphHolders = NULL;
  334. }
  335. //+---------------------------------------------------------------------------
  336. //
  337. // Method: CThkMgr::~CThkMgr
  338. //
  339. // Synopsis: destructor
  340. //
  341. // History: 6-01-94 JohannP (Johann Posch) Created
  342. //
  343. //----------------------------------------------------------------------------
  344. CThkMgr::~CThkMgr()
  345. {
  346. PROXYHOLDER *pph;
  347. PIIDNODE pin;
  348. thkDebugOut((DEB_ITRACE, "_IN CThkMgr::~CThkMgr()\n"));
  349. RemoveAllProxies();
  350. thkAssert(_pHolderTbl->GetCount() == 0);
  351. delete _pProxyTbl1632;
  352. delete _pProxyTbl3216;
  353. // Clean up IID requests
  354. #if DBG == 1
  355. if (_piidnode != NULL)
  356. {
  357. thkDebugOut((DEB_WARN, "WARNING: IID requests active at shutdown\n"));
  358. }
  359. #endif
  360. while (_piidnode != NULL)
  361. {
  362. pin = _piidnode->pNextNode;
  363. thkDebugOut((DEB_IWARN, "IID request leak: %p {%s}\n",
  364. _piidnode, IidOrInterfaceString(_piidnode->piid)));
  365. flRequestFreeList.FreeElement((DWORD)_piidnode);
  366. _piidnode = pin;
  367. }
  368. thkDebugOut((DEB_ITRACE, "OUT CThkMgr::~CThkMgr()\n"));
  369. }
  370. //+---------------------------------------------------------------------------
  371. //
  372. // Member: CThkMgr::RemoveAllProxies, public
  373. //
  374. // Synopsis: Removes all live proxies from the proxy tables
  375. //
  376. // History: 01-Dec-94 DrewB Created
  377. //
  378. //----------------------------------------------------------------------------
  379. void CThkMgr::RemoveAllProxies(void)
  380. {
  381. POSITION pos;
  382. DWORD dwKey;
  383. VPVOID vpv;
  384. thkDebugOut((DEB_ITRACE, "_IN CThkMgr::RemoveAllProxies()\n"));
  385. // Make sure that we disable 3216 proxies first to guard against calling
  386. // back into 16 bit land.
  387. #if DBG == 1
  388. DWORD dwCount;
  389. dwCount = _pProxyTbl3216->GetCount();
  390. if (dwCount > 0)
  391. {
  392. thkDebugOut((DEB_WARN, "WARNING: %d 3216 proxies left\n", dwCount));
  393. }
  394. #endif
  395. // delete the 3216 proxy table
  396. while (pos = _pProxyTbl3216->GetStartPosition())
  397. {
  398. THUNK3216OBJ *pto3216 = NULL;
  399. _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
  400. thkAssert(pto3216 && "CThkMgr::RemoveAllProxies-- found NULL proxy!");
  401. if (pto3216)
  402. {
  403. thkDebugOut((DEB_IWARN, "3216: %p {%d,%d, %p, %p} %s\n",
  404. pto3216, pto3216->cRefLocal, pto3216->cRef,
  405. pto3216->vpvThis16, pto3216->pphHolder,
  406. IidIdxString(pto3216->iidx)));
  407. pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
  408. RemoveProxy3216(pto3216);
  409. }
  410. }
  411. #if DBG == 1
  412. dwCount = _pProxyTbl1632->GetCount();
  413. if (dwCount > 0)
  414. {
  415. thkDebugOut((DEB_WARN, "WARNING: %d 1632 proxies left\n", dwCount));
  416. }
  417. #endif
  418. // delete the 1632 proxy table
  419. while (pos = _pProxyTbl1632->GetStartPosition())
  420. {
  421. THUNK1632OBJ *pto1632;
  422. _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
  423. pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
  424. #if DBG == 1
  425. thkDebugOut((DEB_IWARN, "1632: %p {%d,%d, %p, %p} %s\n",
  426. vpv, pto1632->cRefLocal, pto1632->cRef,
  427. pto1632->punkThis32, pto1632->pphHolder,
  428. IidIdxString(pto1632->iidx)));
  429. #endif
  430. //
  431. // Determine if this is a 'special' object that we know we want
  432. // to release. If it is, then remove all of the references this
  433. // proxy has on it.
  434. //
  435. if (CoQueryReleaseObject(pto1632->punkThis32) == NOERROR)
  436. {
  437. thkDebugOut((DEB_WARN,
  438. "1632: %p is recognized Releasing object %d times\n",
  439. pto1632->punkThis32,pto1632->cRef));
  440. while (pto1632->cRef)
  441. {
  442. IUnknown *punk;
  443. pto1632->cRef--;
  444. punk = pto1632->punkThis32;
  445. RELVDMPTR(vpv);
  446. if (punk->Release() == 0)
  447. {
  448. break;
  449. }
  450. pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
  451. }
  452. }
  453. // Releases pointer
  454. RemoveProxy1632(vpv, pto1632);
  455. }
  456. thkDebugOut((DEB_ITRACE, "OUT CThkMgr::RemoveAllProxies()\n"));
  457. }
  458. // *** IUnknown methods ***
  459. //+---------------------------------------------------------------------------
  460. //
  461. // Method: CThkMgr::QueryInterface
  462. //
  463. // Synopsis: QueryInterface on the thunkmanager itself
  464. //
  465. // Arguments: [riid] -- IID of interface to return
  466. // [ppvObj] -- Interface return
  467. //
  468. // Returns: HRESULT
  469. //
  470. // History: 6-01-94 JohannP (Johann Posch) Created
  471. //
  472. //----------------------------------------------------------------------------
  473. STDMETHODIMP CThkMgr::QueryInterface (REFIID riid, LPVOID FAR* ppvObj)
  474. {
  475. if (IsBadWritePtr(ppvObj, sizeof(void *)))
  476. {
  477. return E_INVALIDARG;
  478. }
  479. *ppvObj = NULL;
  480. // There is no IID_IThunkManager because nobody needs it
  481. if (IsEqualIID(riid, IID_IUnknown))
  482. {
  483. *ppvObj = (IUnknown *) this;
  484. AddRef();
  485. return S_OK;
  486. }
  487. return E_NOINTERFACE;
  488. }
  489. //+---------------------------------------------------------------------------
  490. //
  491. // Methode: CThkMgr::AddRef
  492. //
  493. // Synopsis: Adds a reference
  494. //
  495. // Returns: New ref count
  496. //
  497. // History: 6-01-94 JohannP (Johann Posch) Created
  498. //
  499. //----------------------------------------------------------------------------
  500. STDMETHODIMP_(ULONG) CThkMgr::AddRef ()
  501. {
  502. InterlockedIncrement( &_cRefs );
  503. return _cRefs;
  504. }
  505. //+---------------------------------------------------------------------------
  506. //
  507. // Methode: CThkMgr::Release
  508. //
  509. // Synopsis: Releases a reference
  510. //
  511. // Returns: New ref count
  512. //
  513. // History: 6-01-94 JohannP (Johann Posch) Created
  514. //
  515. //----------------------------------------------------------------------------
  516. STDMETHODIMP_(ULONG) CThkMgr::Release()
  517. {
  518. if (InterlockedDecrement( &_cRefs ) == 0)
  519. {
  520. return 0;
  521. }
  522. return _cRefs;
  523. }
  524. // *** IThunkManager methods ***
  525. //
  526. //
  527. //+---------------------------------------------------------------------------
  528. //
  529. // Method: CThkMgr::IsIIDRequested
  530. //
  531. // Synopsis: checks if given refiid was requested by WOW
  532. //
  533. // Arguments: [riid] -- refiid
  534. //
  535. // Returns: true if requested by 16 bit
  536. //
  537. // History: 6-01-94 JohannP (Johann Posch) Created
  538. //
  539. //----------------------------------------------------------------------------
  540. STDMETHODIMP_ (BOOL) CThkMgr::IsIIDRequested(REFIID riid)
  541. {
  542. PIIDNODE piidnode = _piidnode;
  543. BOOL fRet = FALSE;
  544. while (piidnode)
  545. {
  546. if (*piidnode->piid == riid)
  547. {
  548. fRet = TRUE;
  549. break;
  550. }
  551. piidnode = piidnode->pNextNode;
  552. }
  553. thkDebugOut((DEB_THUNKMGR, "IsIIDRequested(%s) => %d\n",
  554. GuidString(&riid), fRet));
  555. return fRet;
  556. }
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Member: CThkMgr::IsCustom3216Proxy, public
  560. //
  561. // Synopsis: Attempts to identify the given IUnknown as a 32->16 proxy
  562. // and also checks whether it is a thunked interface or not
  563. //
  564. // Arguments: [punk] - Object
  565. //
  566. // Returns: BOOL
  567. //
  568. // History: 11-Jul-94 DrewB Created
  569. //
  570. //----------------------------------------------------------------------------
  571. STDMETHODIMP_(BOOL) CThkMgr::IsCustom3216Proxy(IUnknown *punk,
  572. REFIID riid)
  573. {
  574. return !IsIIDSupported(riid) && IsProxy3216(punk) != 0;
  575. }
  576. //+---------------------------------------------------------------------------
  577. //
  578. // Method: CThkMgr::IsIIDSupported
  579. //
  580. // Synopsis: Return whether the given interface is thunked or not
  581. //
  582. // Arguments: [riid] -- Interface
  583. //
  584. // Returns: BOOL
  585. //
  586. // History: 6-01-94 JohannP (Johann Posch) Created
  587. //
  588. //----------------------------------------------------------------------------
  589. BOOL CThkMgr::IsIIDSupported(REFIID riid)
  590. {
  591. return IIDIDX_IS_INDEX(IidToIidIdx(riid));
  592. }
  593. //+---------------------------------------------------------------------------
  594. //
  595. // Method: CThkMgr::AddIIDRequest
  596. //
  597. // Synopsis: adds the refiid to the request list
  598. //
  599. // Arguments: [riid] -- Interface
  600. //
  601. // Returns: true on success
  602. //
  603. // History: 6-01-94 JohannP (Johann Posch) Created
  604. //
  605. //----------------------------------------------------------------------------
  606. BOOL CThkMgr::AddIIDRequest(REFIID riid)
  607. {
  608. PIIDNODE piidnode = _piidnode;
  609. thkAssert(!IsIIDSupported(riid));
  610. // create a new node and add at front
  611. piidnode = (PIIDNODE)flRequestFreeList.AllocElement();
  612. if (piidnode == NULL)
  613. {
  614. return FALSE;
  615. }
  616. piidnode->pNextNode = _piidnode;
  617. _piidnode = piidnode;
  618. // IID requests are only valid for the lifetime of the call that
  619. // requested a custom interface, so there's no need to copy
  620. // the IID's memory since it must remain valid for the same time
  621. // period
  622. piidnode->piid = (IID *)&riid;
  623. thkDebugOut((DEB_THUNKMGR, "AddIIDRequest(%s)\n", GuidString(&riid)));
  624. return TRUE;
  625. }
  626. //+---------------------------------------------------------------------------
  627. //
  628. // Method: CThkMgr::RemoveIIDRequest
  629. //
  630. // Synopsis: removes a request for the request list
  631. //
  632. // Arguments: [riid] -- Interface
  633. //
  634. // Returns: true on success
  635. //
  636. // History: 6-01-94 JohannP (Johann Posch) Created
  637. //
  638. //----------------------------------------------------------------------------
  639. void CThkMgr::RemoveIIDRequest(REFIID riid)
  640. {
  641. PIIDNODE piidnode;
  642. PIIDNODE pinPrev;
  643. thkAssert(!IsIIDSupported(riid));
  644. pinPrev = NULL;
  645. piidnode = _piidnode;
  646. while (piidnode)
  647. {
  648. if (*piidnode->piid == riid)
  649. {
  650. break;
  651. }
  652. pinPrev = piidnode;
  653. piidnode = piidnode->pNextNode;
  654. }
  655. thkAssert(piidnode != NULL && "RemoveIIDRequest: IID not found");
  656. thkDebugOut((DEB_THUNKMGR, "RemoveIIDRequest(%s)\n", GuidString(&riid)));
  657. if (pinPrev == NULL)
  658. {
  659. _piidnode = piidnode->pNextNode;
  660. }
  661. else
  662. {
  663. pinPrev->pNextNode = piidnode->pNextNode;
  664. }
  665. flRequestFreeList.FreeElement((DWORD)piidnode);
  666. }
  667. //+---------------------------------------------------------------------------
  668. //
  669. // Method: CThkMgr::CanGetNewProxy1632
  670. //
  671. // Synopsis: Preallocates proxy memory
  672. //
  673. // Arguments: [iidx] - Custom interface or known index
  674. //
  675. // Returns: vpv pointer if proxy is available, fails otherwise
  676. //
  677. // History: 6-01-94 JohannP (Johann Posch) Created
  678. //
  679. //----------------------------------------------------------------------------
  680. VPVOID CThkMgr::CanGetNewProxy1632(IIDIDX iidx)
  681. {
  682. VPVOID vpv;
  683. THUNK1632OBJ UNALIGNED *pto;
  684. thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy1632(%s)\n",
  685. NestingLevelString(), IidIdxString(iidx)));
  686. // Allocate proxy memory
  687. vpv = (VPVOID)flFreeList16.AllocElement();
  688. if (vpv == NULL)
  689. {
  690. thkDebugOut((DEB_WARN, "WARNING: Failed to allocate memory "
  691. "for 16-bit proxies\n"));
  692. goto Exit;
  693. }
  694. // Add custom interface request if necessary
  695. if (vpv && IIDIDX_IS_IID(iidx))
  696. {
  697. // add the request for the unknown interface
  698. if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
  699. {
  700. flFreeList16.FreeElement( (DWORD)vpv );
  701. vpv = 0;
  702. }
  703. }
  704. // Set up the preallocated proxy as a temporary proxy so that
  705. // we can hand it out for nested callbacks
  706. pto = FIXVDMPTR(vpv, THUNK1632OBJ);
  707. thkAssert(pto != NULL);
  708. pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
  709. pto->cRefLocal = 0;
  710. pto->cRef = 0;
  711. pto->iidx = iidx;
  712. pto->punkThis32 = NULL;
  713. pto->pphHolder = NULL;
  714. PprxNull(pto->pprxObject);
  715. pto->grfFlags = PROXYFLAG_TEMPORARY;
  716. #if DBG == 1
  717. // Deliberately make this an invalid proxy. We want it to be used
  718. // in as few places as possible
  719. pto->dwSignature = PSIG1632TEMP;
  720. #endif
  721. RELVDMPTR(vpv);
  722. Exit:
  723. thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy1632: %p\n",
  724. NestingLevelString(), vpv));
  725. return vpv;
  726. }
  727. //+---------------------------------------------------------------------------
  728. //
  729. // Method: CThkMgr::FreeNewProxy1632
  730. //
  731. // Synopsis: frees unused preallocated proxies
  732. //
  733. // Arguments: [iidx] - Custom interface or known index
  734. //
  735. // History: 6-01-94 JohannP (Johann Posch) Created
  736. //
  737. //----------------------------------------------------------------------------
  738. void CThkMgr::FreeNewProxy1632(VPVOID vpv, IIDIDX iidx)
  739. {
  740. thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy1632(%s)\n",
  741. NestingLevelString(), IidIdxString(iidx)));
  742. thkAssert(vpv != 0);
  743. if (IIDIDX_IS_IID(iidx))
  744. {
  745. // remove the request for the unknown interface
  746. RemoveIIDRequest(*IIDIDX_IID(iidx));
  747. }
  748. #if DBG == 1
  749. // Ensure that we're not getting rid of a temporary proxy that's
  750. // in use
  751. THUNK1632OBJ UNALIGNED *pto;
  752. pto = FIXVDMPTR(vpv, THUNK1632OBJ);
  753. if (pto->grfFlags & PROXYFLAG_TEMPORARY)
  754. {
  755. thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
  756. }
  757. RELVDMPTR(vpv);
  758. #endif
  759. // add element to free list
  760. flFreeList16.FreeElement( (DWORD)vpv );
  761. thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy1632\n",
  762. NestingLevelString()));
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // Method: CThkMgr::IsProxy1632
  767. //
  768. // Synopsis: checks if given object is an 16/32 object
  769. //
  770. // Arguments: [vpvObj16] -- Object to check
  771. //
  772. // Returns: 32-bit interface being proxied or NULL
  773. //
  774. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  775. // proper thunking of IN/OUT interfaces
  776. //----------------------------------------------------------------------------
  777. IUnknown *CThkMgr::IsProxy1632(VPVOID vpvThis16)
  778. {
  779. // Local variables
  780. THUNK1632OBJ UNALIGNED *ptoThis16;
  781. IUnknown *punkThis32 = NULL;
  782. THUNKINFO ti;
  783. // Check if the pointer points to valid VDM memory of
  784. // 1632 proxy type
  785. ptoThis16 = (THUNK1632OBJ UNALIGNED *) GetReadPtr16(&ti, vpvThis16, sizeof(THUNK1632OBJ));
  786. if(ptoThis16) {
  787. // Check its vtable
  788. if(ptoThis16->pfnVtbl == gdata16Data.atfnProxy1632Vtbl) {
  789. // Check whether it is alive
  790. if(ptoThis16->pphHolder) {
  791. // Assert that the proxy is indeed alive
  792. thkAssert(ptoThis16->dwSignature == PSIG1632);
  793. #if DBG==1
  794. // In debug builds, ensure that proxy is under its holder
  795. // and that there is atleast one active proxy under the holder
  796. BOOL fFound = FALSE, fActive = FALSE;
  797. CProxy *pProxy;
  798. PROXYPTR PrxCur, PrxPrev;
  799. PrxCur = ptoThis16->pphHolder->pprxProxies;
  800. while(!(fFound && fActive) && !PprxIsNull(PrxCur)) {
  801. // Remember the current proxy and resolve its reference
  802. PrxPrev = PrxCur;
  803. pProxy = ResolvePprx(&PrxCur);
  804. // Assert that the holders match
  805. thkAssert(ptoThis16->pphHolder == pProxy->pphHolder);
  806. if(PrxCur.wType == PPRX_16) {
  807. // Assert that the current 1632 proxy is alive
  808. thkAssert(pProxy->dwSignature == PSIG1632);
  809. // Check if the given and current proxies are same
  810. if(PrxCur.dwPtrVal == vpvThis16)
  811. fFound = TRUE;
  812. }
  813. else {
  814. // Assert that the current proxy is 3216 proxy
  815. thkAssert(PrxCur.wType == PPRX_32);
  816. // Assert that the current proxy is alive
  817. thkAssert(pProxy->dwSignature == PSIG3216);
  818. }
  819. // Check if the current proxy is active
  820. if(pProxy->cRefLocal)
  821. fActive = TRUE;
  822. // Obtain the next proxy under this identity
  823. PrxCur = pProxy->pprxObject;
  824. ReleasePprx(&PrxPrev);
  825. }
  826. thkAssert(fFound && fActive);
  827. #endif
  828. // Initialize the return value
  829. punkThis32 = ptoThis16->punkThis32;
  830. }
  831. }
  832. // Release the VDM pointer
  833. RELVDMPTR(vpvThis16);
  834. }
  835. return punkThis32;
  836. }
  837. //+---------------------------------------------------------------------------
  838. //
  839. // Method: CThkMgr::FindProxy1632
  840. //
  841. // Synopsis: Finds/Generates a 16/32 proxy for a given 32-bit interface.
  842. // If the given 32-bit interface itself is a proxy, returns
  843. // the actual 16-bit Interface
  844. //
  845. // Arguments: [vpvPrealloc] -- Preallocated 16/32 proxy
  846. // [punkThis32] -- 32-bit Interface to be proxied
  847. // [iidx] -- Interface index or IID
  848. // [pfst] -- Return value to hold the kind proxy object
  849. //
  850. // Returns: 16/32 proxy object or the actual 16-bit Interface
  851. //
  852. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  853. // proper thunking of IN/OUT interfaces
  854. //----------------------------------------------------------------------------
  855. VPVOID CThkMgr::FindProxy1632(VPVOID vpvPrealloc, IUnknown *punkThis32,
  856. PROXYHOLDER *pgHolder, IIDIDX iidx, DWORD *pfst)
  857. {
  858. thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy1632(%p, %p, %s)\n",
  859. NestingLevelString(), vpvPrealloc, punkThis32, IidIdxString(iidx)));
  860. DebugIncrementNestingLevel();
  861. // Local variables
  862. THUNK1632OBJ UNALIGNED *pto;
  863. VPVOID vpv, vpvUnk = NULL;
  864. DWORD fst, Fail = FALSE;
  865. // Validation checks
  866. thkAssert(punkThis32 != NULL);
  867. #if DBG == 1
  868. // Ensure that the preallocated proxy is not in use
  869. if (vpvPrealloc) {
  870. pto = FIXVDMPTR(vpvPrealloc, THUNK1632OBJ);
  871. if(pto->grfFlags & PROXYFLAG_TEMPORARY)
  872. thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
  873. RELVDMPTR(vpvPrealloc);
  874. }
  875. #endif
  876. // Initialize return value
  877. fst = FST_ERROR;
  878. // If proxy was preallocated for this IID using CanGetNewProxy, it would
  879. // have added it to the requested IID list.
  880. if (vpvPrealloc != 0 && IIDIDX_IS_IID(iidx))
  881. RemoveIIDRequest(*IIDIDX_IID(iidx));
  882. if(vpv = LookupProxy1632(punkThis32)) {
  883. // Found an existing proxy
  884. thkDebugOut((DEB_THUNKMGR, "%sFindProxy1632 found existing proxy,(%p)->%p\n",
  885. NestingLevelString(), punkThis32, vpv));
  886. // Fix the VDM pointer
  887. pto = FIXVDMPTR(vpv, THUNK1632OBJ);
  888. // Assert that holders match
  889. thkAssert(pto->pphHolder);
  890. if(pgHolder && pto->pphHolder!=pgHolder) {
  891. thkAssert(pto->pphHolder->dwFlags & PH_AGGREGATEE);
  892. }
  893. // Check the proxy IID against the given IID. If the server has passed
  894. // the same 32-bit interface pointer against another IID, it is possible
  895. // for the IID's to be different. If the Interface2 derives from Interface1,
  896. // the interface pointers for them would be the same in C or C++. An
  897. // excellant example would be IPersistStorage deriving from IPersist.
  898. // IIDIDXs are related to interfaces in thunk tables, which are organized
  899. // such that more derived interfaces have higher indices than the less
  900. // derived ones. Custom interfaces have an IID rather than an index, and
  901. // consequently are not affected by the following statement.
  902. if(IIDIDX_IS_INDEX(iidx)) {
  903. // Check if the new IID is more derived than the existing one
  904. if(IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx)) {
  905. // As all 16-bit proxy vtables are the same, there is no need
  906. // to change the vtable pointer.
  907. pto->iidx = iidx;
  908. }
  909. }
  910. // Release the VDM pointer
  911. RELVDMPTR(vpv);
  912. // AddRef the proxy
  913. AddRefProxy1632(vpv);
  914. // Set the type of proxy being returned
  915. fst = FST_USED_EXISTING;
  916. }
  917. else if(vpv = IsProxy3216(punkThis32)) {
  918. // The given 32-bit interface itself is a proxy to a 16-bit
  919. // interface
  920. thkDebugOut((DEB_THUNKMGR, "%sFindProxy1632 shortcut proxy,(%p)->%p\n",
  921. NestingLevelString(), punkThis32, vpv));
  922. THUNK3216OBJ *pProxy3216;
  923. // Assert that the holders match
  924. pProxy3216 = (THUNK3216OBJ *) punkThis32;
  925. thkAssert(pProxy3216->pphHolder);
  926. if(pgHolder && pProxy3216->pphHolder!=pgHolder) {
  927. thkAssert(pProxy3216->pphHolder->dwFlags & PH_AGGREGATEE);
  928. }
  929. // Avoid creating a proxy to another proxy
  930. THKSTATE thkstate;
  931. // Remember the current thunk state
  932. thkstate = GetThkState();
  933. // Set the thunk state to THKSTATE_NOCALL
  934. SetThkState(THKSTATE_NOCALL);
  935. // AddRef actual the 16-bit interface
  936. AddRefOnObj16(vpv);
  937. // Restore previous thunk state
  938. SetThkState(thkstate);
  939. // Set the type of proxy being returned
  940. fst = FST_SHORTCUT;
  941. }
  942. else {
  943. // An existing proxy has not been found and the interface to proxied
  944. // is a real 32-bit interface.
  945. // Check if holder has not been given
  946. if(!pgHolder) {
  947. // This interface is being obtained through a method call
  948. PROXYPTR unkPPtr;
  949. SCODE error;
  950. // Obtain the identity of 32-bit object
  951. error = Object32Identity(punkThis32, &unkPPtr, &fst);
  952. if(error == NOERROR) {
  953. // Check for aggregation case
  954. if(unkPPtr.wType == PPRX_16) {
  955. // Check if vpvThis32 itself is an IUnknown interface
  956. if(iidx == THI_IUnknown) {
  957. // Initialize the return value
  958. vpv = unkPPtr.dwPtrVal;
  959. // Check if the identity has been switched
  960. if(fst == FST_USED_EXISTING) {
  961. // The IUnknown identity has already been established
  962. // The app was trying to pass someother 32-bit interface
  963. // as IUnknown. Switch to correct identity
  964. thkAssert(!"Switched to correct Identity");
  965. // AddRef the proxy being returned
  966. AddRefProxy1632(vpv);
  967. }
  968. else {
  969. thkAssert(fst==FST_CREATED_NEW);
  970. }
  971. }
  972. else {
  973. THUNK1632OBJ UNALIGNED *Id1632;
  974. // Fix the VDM pointer
  975. Id1632 = FIXVDMPTR(unkPPtr.dwPtrVal, THUNK1632OBJ);
  976. // Check if the identity has just been established
  977. if(fst == FST_CREATED_NEW) {
  978. // Check if the Identity and current IID share the same
  979. // 32-bit interface pointer
  980. if(Id1632->punkThis32 == punkThis32) {
  981. // Check if the new IID is more derived than
  982. // the existing one
  983. if(IIDIDX_IS_INDEX(iidx) && iidx>Id1632->iidx) {
  984. // As all 16-bit proxy vtables are the same,
  985. // there is no need to change the vtable pointer
  986. Id1632->iidx = iidx;
  987. }
  988. // Initialize the return value
  989. vpv = unkPPtr.dwPtrVal;
  990. }
  991. else {
  992. // We need to release the IUnknown proxy after adding
  993. // the proxy representing vpvThis16 to the its holder
  994. vpvUnk = unkPPtr.dwPtrVal;
  995. }
  996. }
  997. else {
  998. thkAssert(fst == FST_USED_EXISTING);
  999. }
  1000. // Obtain the holder of the identity
  1001. pgHolder = Id1632->pphHolder;
  1002. // Release the VDM pointer
  1003. RELVDMPTR(unkPPtr.dwPtrVal);
  1004. }
  1005. }
  1006. else {
  1007. // Obtain the holder of the identity
  1008. pgHolder = ((THUNK3216OBJ *)(unkPPtr.dwPtrVal))->pphHolder;
  1009. // Sanity checks
  1010. thkAssert(fst == FST_USED_EXISTING);
  1011. thkAssert(pgHolder->dwFlags & PH_AGGREGATEE);
  1012. // Check if vpvThis32 itself is an IUnknown interface
  1013. if(iidx == THI_IUnknown) {
  1014. // The IUnknown identity has already been established
  1015. // The app was trying to pass someother 32-bit interface
  1016. // as IUnknown. Switch to correct identity
  1017. thkAssert(!"Switched to correct Identity");
  1018. // Initialize the return value
  1019. vpv = ((THUNK3216OBJ *)(unkPPtr.dwPtrVal))->vpvThis16;
  1020. // AddRef the actual 16-bit interface being returned
  1021. AddRefOnObj16(vpv);
  1022. }
  1023. }
  1024. }
  1025. else {
  1026. // Failed to obtain the identity
  1027. Fail = TRUE;
  1028. }
  1029. }
  1030. }
  1031. if(!vpv && !Fail) {
  1032. // Assert that we have holder
  1033. thkAssert(pgHolder);
  1034. // Reset the fst value
  1035. fst = FST_ERROR;
  1036. // Obtain either a preallocated or a new proxy
  1037. if(vpvPrealloc) {
  1038. // Use the preallocated proxy
  1039. vpv = vpvPrealloc;
  1040. vpvPrealloc = NULL;
  1041. }
  1042. else {
  1043. // Create a new proxy
  1044. vpv = flFreeList16.AllocElement();
  1045. }
  1046. // Ensure that we have a proxy
  1047. if(vpv) {
  1048. // Put the new proxy in the proxy list
  1049. if(_pProxyTbl1632->SetAt((DWORD)punkThis32, (void *)vpv)) {
  1050. // Convert a custom IID to THI_IUnknown as we thunk only its IUnknown
  1051. // methods
  1052. if(IIDIDX_IS_IID(iidx))
  1053. iidx = INDEX_IIDIDX(THI_IUnknown);
  1054. // AddRef the 32-bit interface
  1055. punkThis32->AddRef();
  1056. // Update proxy fields
  1057. pto = FIXVDMPTR(vpv, THUNK1632OBJ);
  1058. thkAssert(pto != NULL);
  1059. pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
  1060. pto->cRefLocal = 1;
  1061. pto->cRef = 1;
  1062. pto->iidx = iidx;
  1063. pto->punkThis32 = punkThis32;
  1064. pto->grfFlags = PROXYFLAG_PIFACE;
  1065. PprxNull(pto->pprxObject);
  1066. pto->pphHolder = NULL;
  1067. AddProxyToHolder(pgHolder, pto, Pprx16(vpv));
  1068. #if DBG == 1
  1069. pto->dwSignature = PSIG1632;
  1070. #endif
  1071. thkDebugOut((DEB_THUNKMGR,
  1072. "%sFindProxy1632 added new proxy, %s (%p)->%p (%d,%d)\n",
  1073. NestingLevelString(), inInterfaceNames[pto->iidx].pszInterface,
  1074. punkThis32, vpv, pto->cRefLocal, pto->cRef));
  1075. RELVDMPTR(vpv);
  1076. // Set the type of proxy being returned
  1077. fst = FST_CREATED_NEW;
  1078. }
  1079. else {
  1080. // Cleanup the proxy only if was newly created
  1081. if(fst == FST_CREATED_NEW)
  1082. flFreeList16.FreeElement(vpv);
  1083. vpv = NULL;
  1084. fst = 0;
  1085. }
  1086. }
  1087. }
  1088. else {
  1089. if(Fail) {
  1090. thkAssert(vpv == 0 && fst == FST_ERROR);
  1091. }
  1092. }
  1093. // Cleanup the allocated proxy if it has not been used
  1094. if(vpvPrealloc)
  1095. flFreeList16.FreeElement(vpvPrealloc);
  1096. // Release the IUnknown proxy. If it was newly created for establishing
  1097. // the identity of the given 16-bit interface , the following release
  1098. // would be the last release on the IUnknown proxy and consequently,
  1099. // would destroy it along with its holder
  1100. if(vpvUnk)
  1101. ReleaseProxy1632(vpvUnk);
  1102. // Set the return value
  1103. if(pfst)
  1104. *pfst = fst;
  1105. DebugDecrementNestingLevel();
  1106. thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy1632: (%p)->%p\n",
  1107. NestingLevelString(), punkThis32, vpv));
  1108. return vpv;
  1109. }
  1110. //+---------------------------------------------------------------------------
  1111. //
  1112. // Method: CThkMgr::QueryInterfaceProxy1632
  1113. //
  1114. // Synopsis: QueryInterface on the given proxy
  1115. //
  1116. // Arguments: [ptoThis] -- Proxy to a 32-bit interface
  1117. // [refiid] -- Interface IID
  1118. // [ppv] -- Place where the new interface is returned
  1119. //
  1120. // Returns: SCODE
  1121. //
  1122. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  1123. // proper thunking of IN/OUT interfaces
  1124. //----------------------------------------------------------------------------
  1125. SCODE CThkMgr::QueryInterfaceProxy1632(VPVOID vpvThis16, REFIID refiid,
  1126. LPVOID *ppv)
  1127. {
  1128. thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy1632(%p)\n",
  1129. NestingLevelString(), vpvThis16));
  1130. DebugIncrementNestingLevel();
  1131. // Local variables
  1132. SCODE scRet;
  1133. THUNK1632OBJ UNALIGNED *ptoThis;
  1134. IUnknown *punkThis, *punkNew;
  1135. PROXYHOLDER *pph;
  1136. VPVOID vpv;
  1137. DWORD fst, dwFlags;
  1138. // Validation checks
  1139. DebugValidateProxy1632(vpvThis16);
  1140. // Initialize
  1141. *ppv = NULL;
  1142. // Perform app compatiblity hacks
  1143. // Ikitaro queries for IViewObject and uses it as IViewObject2
  1144. REFIID newiid = ((TlsThkGetAppCompatFlags() & OACF_IVIEWOBJECT2) &&
  1145. IsEqualIID(refiid, IID_IViewObject)) ?
  1146. IID_IViewObject2 : refiid;
  1147. // Convert interface IID to an IIDIDX
  1148. IIDIDX iidx = IidToIidIdx(newiid);
  1149. // Check if a custom interface has been requested
  1150. if(IIDIDX_IS_IID(iidx)) {
  1151. thkDebugOut((DEB_THUNKMGR, "%sQueryInterfaceProxy1632: unknown iid %s\n",
  1152. NestingLevelString(), IidIdxString(iidx)));
  1153. // Add the request for the unknown interface
  1154. if(!AddIIDRequest(newiid))
  1155. return E_OUTOFMEMORY;
  1156. }
  1157. // Obtain the 32-bit interface
  1158. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1159. dwFlags = ptoThis->grfFlags;
  1160. pph = ptoThis->pphHolder;
  1161. if(dwFlags & PROXYFLAG_TEMPORARY) {
  1162. // QI on a temporary proxy
  1163. punkThis = *(IUnknown **) ptoThis->punkThis32;
  1164. thkAssert(!pph);
  1165. }
  1166. else {
  1167. // QI on a normal proxy
  1168. punkThis = ptoThis->punkThis32;
  1169. Win4Assert(pph);
  1170. }
  1171. thkAssert(punkThis);
  1172. RELVDMPTR(vpvThis16);
  1173. // Ensure that the aggregatee identity gets correctly established
  1174. if(dwFlags & PROXYFLAG_PUNKOUTER && iidx == THI_IUnknown) {
  1175. // QI by the aggregatee for identity
  1176. thkAssert(pph->unkProxy.dwPtrVal == vpvThis16);
  1177. // AddRef and return outer proxy
  1178. AddRefProxy1632(vpvThis16);
  1179. *ppv = (void *) vpvThis16;
  1180. }
  1181. else {
  1182. // Execute the QI on the 32-bit interface
  1183. scRet = punkThis->QueryInterface(newiid, (void **) &punkNew);
  1184. if(SUCCEEDED(scRet)) {
  1185. if(punkNew) {
  1186. // Check if this is a QI on an interface on the aggregatee
  1187. if(pph && (pph->dwFlags & PH_AGGREGATEE)) {
  1188. if(dwFlags & PROXYFLAG_PIFACE) {
  1189. // QI on an interface on the aggregatee which
  1190. // delegates to the aggregator
  1191. // Note the above QI call can be short circuited as
  1192. // an optimization. It will be carried out in future
  1193. // after ensuring that apps do not break due to such
  1194. // short circuiting
  1195. thkAssert(pph->unkProxy.wType == PPRX_32);
  1196. }
  1197. else if(dwFlags & PROXYFLAG_PUNKOUTER) {
  1198. // QI by the aggregatee on aggregator
  1199. thkAssert(pph->unkProxy.dwPtrVal == vpvThis16);
  1200. }
  1201. else {
  1202. // QI by the aggregator on the aggregatee
  1203. thkAssert(dwFlags & PROXYFLAG_PUNKINNER);
  1204. thkAssert(pph->unkProxy.wType == PPRX_32);
  1205. }
  1206. // As aggregation is involved, we cannot be certain of
  1207. // identity of the returned interface
  1208. pph = NULL;
  1209. }
  1210. // Set the thunk status
  1211. SetThkState(THKSTATE_INVOKETHKOUT32);
  1212. vpv = FindProxy1632(NULL, punkNew, pph, iidx, &fst);
  1213. if(vpv) {
  1214. // Set the return value
  1215. *ppv = (void *)vpv;
  1216. #if DBG==1
  1217. if(pph) {
  1218. // Ensure that the given and new proxies either have the same
  1219. // holder or point to same identity
  1220. if(fst & FST_PROXY_STATUS) {
  1221. THUNK1632OBJ UNALIGNED *ptoNew;
  1222. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1223. ptoNew = FIXVDMPTR(vpv, THUNK1632OBJ);
  1224. thkAssert(ptoNew->pphHolder == ptoThis->pphHolder);
  1225. RELVDMPTR(vpvThis16);
  1226. RELVDMPTR(vpv);
  1227. }
  1228. else {
  1229. THUNK3216OBJ *ptoNew = (THUNK3216OBJ *) punkNew;
  1230. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1231. thkAssert(fst == FST_SHORTCUT);
  1232. thkAssert(ptoNew->pphHolder != ptoThis->pphHolder);
  1233. thkAssert(ptoNew->pphHolder->dwFlags & PH_AGGREGATEE);
  1234. thkAssert(ptoNew->pphHolder->unkProxy.wType == PPRX_16);
  1235. RELVDMPTR(vpvThis16);
  1236. }
  1237. }
  1238. #endif
  1239. // Check for 32-bit custom interfaces that are not supported
  1240. if((fst & FST_PROXY_STATUS) && IIDIDX_IS_IID(iidx)) {
  1241. // Release proxy and fake E_NOINTERFACE
  1242. ReleaseProxy1632(vpv);
  1243. scRet = E_NOINTERFACE;
  1244. }
  1245. }
  1246. else {
  1247. scRet = E_OUTOFMEMORY;
  1248. }
  1249. // As the new interface is an OUT parameter, release the actual
  1250. // 32-bit interface. This would counter the AddRef made by
  1251. // a successfule FindProxy3216, else it would clean up the
  1252. // reference count
  1253. punkNew->Release();
  1254. // Resert thunk status
  1255. SetThkState(THKSTATE_NOCALL);
  1256. }
  1257. else {
  1258. // Corel draw returns NOERROR while setting returned interface to NULL
  1259. // We modify the returned value to suit 32-bit QI semantics.
  1260. scRet = E_NOINTERFACE;
  1261. }
  1262. }
  1263. }
  1264. if(IIDIDX_IS_IID(iidx)) {
  1265. // Clean up custom interface request
  1266. RemoveIIDRequest(refiid);
  1267. }
  1268. DebugDecrementNestingLevel();
  1269. thkDebugOut((DEB_THUNKMGR, "%sOut QueryInterfaceProxy1632(%p) => %p, 0x%08lX\n",
  1270. NestingLevelString(), ptoThis, *ppv, scRet));
  1271. return scRet;
  1272. }
  1273. //+---------------------------------------------------------------------------
  1274. //
  1275. // Member: CThkMgr::LockProxy, public
  1276. //
  1277. // Synopsis: Locks a proxy so that it can't be freed
  1278. //
  1279. // Arguments: [pprx] - Proxy
  1280. //
  1281. // History: 11-Aug-94 DrewB Created
  1282. //
  1283. //----------------------------------------------------------------------------
  1284. void CThkMgr::LockProxy(CProxy *pprx)
  1285. {
  1286. pprx->grfFlags |= PROXYFLAG_LOCKED;
  1287. }
  1288. //+---------------------------------------------------------------------------
  1289. //
  1290. // Method: CThkMgr::TransferLocalRefs1632
  1291. //
  1292. // Synopsis: Transfer the all local references maintained by the proxy
  1293. // to the actual object
  1294. //
  1295. // Arguments: [vpvProxy] -- 16/32 proxy
  1296. //
  1297. // Returns: refcount
  1298. //
  1299. // History: Mar 12,96 Gopalk Created
  1300. //
  1301. //----------------------------------------------------------------------------
  1302. DWORD CThkMgr::TransferLocalRefs1632(VPVOID vpvProxy)
  1303. {
  1304. // Debug output
  1305. thkDebugOut((DEB_THUNKMGR, "%sIn TransferLocalRefs1632(%p)\n",
  1306. NestingLevelString(), vpvProxy));
  1307. DebugIncrementNestingLevel();
  1308. // Validation check
  1309. DebugValidateProxy1632(vpvProxy);
  1310. // Local variables
  1311. THUNK1632OBJ UNALIGNED *pProxy1632;
  1312. IUnknown *pUnk32;
  1313. DWORD cRef;
  1314. // Fix memory pointed to by 16:16 pointer
  1315. pProxy1632 = FIXVDMPTR(vpvProxy, THUNK1632OBJ);
  1316. pUnk32 = pProxy1632->punkThis32;
  1317. // Transfer all local references maintained by the proxy
  1318. while(pProxy1632->cRefLocal > pProxy1632->cRef) {
  1319. // Increment actual ref count before AddRef on the actual object
  1320. ++pProxy1632->cRef;
  1321. // The following AddRef could cause callbacks to 16-bit world
  1322. // and hence unfix the memory pointed to by 16:16 pointer
  1323. RELVDMPTR(vpvProxy);
  1324. // AddRef the actual object
  1325. pUnk32->AddRef();
  1326. // Refix memory pointed to by 16:16 pointer
  1327. pProxy1632 = FIXVDMPTR(vpvProxy, THUNK1632OBJ);
  1328. }
  1329. // Debug output
  1330. DebugDecrementNestingLevel();
  1331. thkDebugOut((DEB_THUNKMGR, "%sOut TransferLocalRefs1632(%p)(%ld,%ld)\n",
  1332. NestingLevelString(), vpvProxy, pProxy1632->cRefLocal,
  1333. pProxy1632->cRef));
  1334. // Cleanup
  1335. cRef = pProxy1632->cRefLocal;
  1336. RELVDMPTR(vpvProxy);
  1337. // Debug validation
  1338. DebugValidateProxy1632(vpvProxy);
  1339. return cRef;
  1340. }
  1341. //+---------------------------------------------------------------------------
  1342. //
  1343. // Method: CThkMgr::TransferLocalRefs3216
  1344. //
  1345. // Synopsis: Transfer the all local references maintained by the proxy
  1346. // to the actual object
  1347. //
  1348. // Arguments: [vpvProxy1632] -- 16/32 proxy
  1349. //
  1350. // Returns: refcount
  1351. //
  1352. // History: Mar 12,96 Gopalk Created
  1353. //
  1354. //----------------------------------------------------------------------------
  1355. DWORD CThkMgr::TransferLocalRefs3216(VPVOID vpvProxy)
  1356. {
  1357. // Debug output
  1358. thkDebugOut((DEB_THUNKMGR, "%sIn TransferLocalRefs3216(%p)\n",
  1359. NestingLevelString(), vpvProxy));
  1360. DebugIncrementNestingLevel();
  1361. // Local variables
  1362. THUNK3216OBJ *pProxy3216 = (THUNK3216OBJ *) vpvProxy;
  1363. DWORD cRef;
  1364. // Validation check
  1365. DebugValidateProxy3216(pProxy3216);
  1366. // Transfer all local references maintained by the proxy
  1367. while(pProxy3216->cRefLocal > pProxy3216->cRef) {
  1368. // Increment actual ref count before AddRef on the actual object
  1369. ++pProxy3216->cRef;
  1370. // AddRef the actual object
  1371. AddRefOnObj16(pProxy3216->vpvThis16);
  1372. }
  1373. // Validation check
  1374. DebugValidateProxy3216(pProxy3216);
  1375. // Initialize return value
  1376. cRef = pProxy3216->cRefLocal;
  1377. // Debug output
  1378. DebugDecrementNestingLevel();
  1379. thkDebugOut((DEB_THUNKMGR, "%sOut TransferLocalRefs3216(%p)(%ld,%ld)\n",
  1380. NestingLevelString(), vpvProxy, pProxy3216->cRefLocal,
  1381. pProxy3216->cRef));
  1382. return cRef;
  1383. }
  1384. //+---------------------------------------------------------------------------
  1385. //
  1386. // Method: CThkMgr::AddRefProxy1632
  1387. //
  1388. // Synopsis: addrefs proxy object - delegate call on to real object
  1389. //
  1390. // Arguments: [vpvThis16] -- 16/32 proxy
  1391. //
  1392. // Returns: local refcount
  1393. //
  1394. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  1395. // proper thunking of IN/OUT interfaces
  1396. //
  1397. // Notes: cRef is the addref passed on to the real object
  1398. // cRefLocal is the addref collected locally
  1399. //----------------------------------------------------------------------------
  1400. DWORD CThkMgr::AddRefProxy1632(VPVOID vpvThis16)
  1401. {
  1402. thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy1632(%p)\n",
  1403. NestingLevelString(), vpvThis16));
  1404. DebugIncrementNestingLevel();
  1405. // Local variable
  1406. THUNK1632OBJ UNALIGNED *ptoThis;
  1407. DWORD cRef;
  1408. // Validation checks
  1409. DebugValidateProxy1632(vpvThis16);
  1410. // Fix the VDM pointer
  1411. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1412. // Assert that proxy has a holder
  1413. thkAssert(ptoThis->pphHolder);
  1414. // Increment local refcount
  1415. thkAssert(ptoThis->cRefLocal >= 0);
  1416. ptoThis->cRefLocal++;
  1417. // Check for the need to AddRef the holder
  1418. if(ptoThis->cRefLocal == 1) {
  1419. // Assert that an aggregatee is not being revived
  1420. thkAssert(!(ptoThis->grfFlags & PROXYFLAG_PUNKINNER));
  1421. // AddRef the holder
  1422. AddRefHolder(ptoThis->pphHolder);
  1423. // Mark the proxy as revived
  1424. ptoThis->grfFlags |= PROXYFLAG_REVIVED;
  1425. }
  1426. // Check for the need to forward AddRef to the actual 32-bit interface
  1427. if(ptoThis->cRefLocal==1 || (ptoThis->pphHolder->dwFlags & PH_AGGREGATEE)) {
  1428. IUnknown *punk;
  1429. #if DBG==1
  1430. DWORD refsBefore, refsAfter;
  1431. PROXYHOLDER *pph;
  1432. THUNK3216OBJ *punkOuter;
  1433. // Check if the object is an aggregatee
  1434. pph = ptoThis->pphHolder;
  1435. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  1436. // Assert that identity is in the 16-bit world
  1437. thkAssert(pph->unkProxy.wType == PPRX_32);
  1438. // Obtain the references on the outer proxy
  1439. punkOuter = (THUNK3216OBJ *) pph->unkProxy.dwPtrVal;
  1440. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  1441. refsBefore = punkOuter->cRefLocal;
  1442. }
  1443. #endif
  1444. // Increment before calling the actual 32-bit interface
  1445. ptoThis->cRef++;
  1446. // Release VDM pointer before calling app code
  1447. punk = ptoThis->punkThis32;
  1448. RELVDMPTR(vpvThis16);
  1449. // AddRef the actual 32-bit interface
  1450. punk->AddRef();
  1451. // Refix the VDM pointer
  1452. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1453. #if DBG==1
  1454. // Check if the object is an aggregatee
  1455. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  1456. // Ensure that the above AddRef translated to a AddRef on the
  1457. // outer proxy
  1458. punkOuter = (THUNK3216OBJ *) pph->unkProxy.dwPtrVal;
  1459. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  1460. refsAfter = punkOuter->cRefLocal;
  1461. thkAssert(refsBefore == refsAfter-1);
  1462. }
  1463. #endif
  1464. }
  1465. DebugDecrementNestingLevel();
  1466. thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy1632(%p), (%ld,%ld)\n",
  1467. NestingLevelString(), vpvThis16,
  1468. ptoThis->cRefLocal, ptoThis->cRef));
  1469. cRef = ptoThis->cRefLocal;
  1470. RELVDMPTR(vpvThis16);
  1471. DebugValidateProxy1632(vpvThis16);
  1472. return cRef;
  1473. }
  1474. //+---------------------------------------------------------------------------
  1475. //
  1476. // Method: CThkMgr::ReleaseProxy1632
  1477. //
  1478. // Synopsis: release on 16/32 proxy - delegate call on to real object
  1479. //
  1480. // Arguments: [vpvThis16] -- proxy
  1481. //
  1482. // Returns: local refcount
  1483. //
  1484. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  1485. // proper thunking of IN/OUT interfaces
  1486. //----------------------------------------------------------------------------
  1487. DWORD CThkMgr::ReleaseProxy1632(VPVOID vpvThis16)
  1488. {
  1489. thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy1632(%p)\n",
  1490. NestingLevelString(), vpvThis16));
  1491. DebugIncrementNestingLevel();
  1492. // Local variables
  1493. THUNK1632OBJ UNALIGNED *ptoThis;
  1494. DWORD dwLocalRefs, dwRefs, dwRet;
  1495. PROXYHOLDER *pph;
  1496. DWORD ProxyType;
  1497. // Validation checks
  1498. DebugValidateProxy1632(vpvThis16);
  1499. // Fix the VDM pointer
  1500. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1501. // Assert that proxy has a holder
  1502. thkAssert(ptoThis->pphHolder);
  1503. // Check for the need to forward the release to the actual
  1504. // 32-bit interface
  1505. if(ptoThis->cRef == ptoThis->cRefLocal) {
  1506. IUnknown *punk;
  1507. #if DBG==1
  1508. DWORD refsBefore, refsAfter;
  1509. THUNK3216OBJ *punkOuter;
  1510. // Check if the object is an aggregatee
  1511. pph = ptoThis->pphHolder;
  1512. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  1513. // Assert that identity is in the 16-bit world
  1514. thkAssert(pph->unkProxy.wType == PPRX_32);
  1515. // Obtain the references on the outer proxy
  1516. punkOuter = (THUNK3216OBJ *) pph->unkProxy.dwPtrVal;
  1517. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  1518. refsBefore = punkOuter->cRefLocal;
  1519. }
  1520. #endif
  1521. // Assert that proxy holds references on the 32-bit interface
  1522. thkAssert(ptoThis->cRef);
  1523. // Release the VDM pointer before calling app code
  1524. punk = ptoThis->punkThis32;
  1525. RELVDMPTR(vpvThis16);
  1526. // Release the actual 32-bit interface
  1527. dwRet = punk->Release();
  1528. #if DBG==1
  1529. if(dwRet==0 && TlsThkGetThkMgr()->GetThkState()==THKSTATE_VERIFY32INPARAM) {
  1530. thkDebugOut((DEB_WARN, "WARINING: 32-bit 0x%x IN parameter with zero "
  1531. "ref count\n", punk));
  1532. if(thkInfoLevel & DEB_FAILURES)
  1533. thkAssert(!"Wish to Debug");
  1534. }
  1535. #endif
  1536. // Refix the VDM pointer
  1537. ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  1538. // Decrement after calling the actual 32-bit interface
  1539. --ptoThis->cRef;
  1540. #if DBG==1
  1541. // Check if the object is an aggregatee
  1542. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  1543. // Ensure that the above release translated to a release on the
  1544. // outer proxy
  1545. punkOuter = (THUNK3216OBJ *) pph->unkProxy.dwPtrVal;
  1546. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  1547. refsAfter = punkOuter->cRefLocal;
  1548. thkAssert(refsBefore == refsAfter+1);
  1549. }
  1550. #endif
  1551. }
  1552. // Decrement the local refcount
  1553. dwLocalRefs = --ptoThis->cRefLocal;
  1554. thkAssert(ptoThis->cRefLocal>=0);
  1555. dwRefs = ptoThis->cRef;
  1556. pph = ptoThis->pphHolder;
  1557. ProxyType = ptoThis->grfFlags & PROXYFLAG_TYPE;
  1558. // Release the VDM pointer
  1559. RELVDMPTR(vpvThis16);
  1560. // Check if the proxy needs to be cleaned up
  1561. if(dwLocalRefs == 0) {
  1562. // Debug dump
  1563. thkAssert(dwRefs == 0);
  1564. DBG_DUMP(DebugDump1632());
  1565. // Release the holder. If this is the last release on
  1566. // the holder, the proxy would be destroyed. Hence,
  1567. // we should not use any member variables hereafter.
  1568. ReleaseHolder(pph, ProxyType);
  1569. }
  1570. DebugDecrementNestingLevel();
  1571. thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy1632(%p) => %ld,%ld\n",
  1572. NestingLevelString(), vpvThis16, dwLocalRefs, dwRefs));
  1573. return dwLocalRefs;
  1574. }
  1575. //+---------------------------------------------------------------------------
  1576. //
  1577. // Member: CThkMgr::RemoveProxy1632, public
  1578. //
  1579. // Synopsis: Destroys the given proxy
  1580. //
  1581. // Arguments: [vpv] - 16-bit proxy pointer
  1582. // [pto] - Flat proxy pointer
  1583. //
  1584. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  1585. // proper thunking of IN/OUT interfaces
  1586. //
  1587. // Notes: Also unfixes VDM pointer passed
  1588. //
  1589. //----------------------------------------------------------------------------
  1590. void CThkMgr::RemoveProxy1632(VPVOID vpv, THUNK1632OBJ *pto)
  1591. {
  1592. // Revoke the assosiation between the proxy and
  1593. // the 32-bit interface
  1594. if(!(pto->grfFlags & PROXYFLAG_PUNKOUTER)) {
  1595. #if DBG==1
  1596. thkAssert(_pProxyTbl1632->RemoveKey((DWORD) pto->punkThis32));
  1597. #else
  1598. _pProxyTbl1632->RemoveKey((DWORD) pto->punkThis32);
  1599. #endif
  1600. }
  1601. // Release the holder if needed
  1602. if(pto->cRefLocal)
  1603. ReleaseHolder(pto->pphHolder, PROXYFLAG_NONE);
  1604. // Check if the proxy is locked
  1605. if(!(pto->grfFlags & PROXYFLAG_LOCKED)) {
  1606. // In debug builds, mark the proxy dead
  1607. #if DBG == 1
  1608. pto->dwSignature = PSIG1632DEAD;
  1609. // Return the proxy to free list
  1610. if (!fSaveProxy)
  1611. #endif
  1612. {
  1613. thkAssert(pto->pphHolder);
  1614. pto->pphHolder = NULL;
  1615. flFreeList16.FreeElement((DWORD)vpv);
  1616. }
  1617. }
  1618. // Release the VDM pointer
  1619. RELVDMPTR(vpv);
  1620. return;
  1621. }
  1622. //+---------------------------------------------------------------------------
  1623. //
  1624. // Method: CThkMgr::CanGetNewProxy3216
  1625. //
  1626. // Synopsis: checks if new proxy is available
  1627. //
  1628. // Arguments: [iidx] - Custom interface or known index
  1629. //
  1630. // Returns: Preallocated proxy or NULL
  1631. //
  1632. // History: 6-01-94 JohannP (Johann Posch) Created
  1633. //
  1634. //----------------------------------------------------------------------------
  1635. THUNK3216OBJ *CThkMgr::CanGetNewProxy3216(IIDIDX iidx)
  1636. {
  1637. thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy3216(%s)\n",
  1638. NestingLevelString(), IidIdxString(iidx)));
  1639. LPVOID pvoid;
  1640. pvoid = (LPVOID)flFreeList32.AllocElement();
  1641. if ( pvoid == NULL)
  1642. {
  1643. thkDebugOut((DEB_WARN, "WARNING: CThkMgr::CanGetNewProxy3216, "
  1644. "AllocElement failed\n"));
  1645. return NULL;
  1646. }
  1647. // check if the proxy is requested for a no-thop-interface
  1648. if (pvoid && IIDIDX_IS_IID(iidx))
  1649. {
  1650. // add the request for the unknown interface
  1651. if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
  1652. {
  1653. flFreeList32.FreeElement( (DWORD)pvoid );
  1654. pvoid = NULL;
  1655. }
  1656. }
  1657. thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy3216: %p \n",
  1658. NestingLevelString(), pvoid));
  1659. return (THUNK3216OBJ *)pvoid;
  1660. }
  1661. //+---------------------------------------------------------------------------
  1662. //
  1663. // Method: CThkMgr::FreeNewProxy3216
  1664. //
  1665. // Synopsis: frees previous reserved proxy
  1666. //
  1667. // Arguments: [pto] - Proxy
  1668. // [iidx] - Custom interface or known index
  1669. //
  1670. // History: 6-01-94 JohannP (Johann Posch) Created
  1671. //
  1672. //----------------------------------------------------------------------------
  1673. void CThkMgr::FreeNewProxy3216(THUNK3216OBJ *pto, IIDIDX iidx)
  1674. {
  1675. thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy3216(%p, %s)\n",
  1676. NestingLevelString(), pto, IidIdxString(iidx)));
  1677. thkAssert(pto != NULL);
  1678. if (IIDIDX_IS_IID(iidx))
  1679. {
  1680. // add the request for the unknown interface
  1681. RemoveIIDRequest(*IIDIDX_IID(iidx));
  1682. }
  1683. thkAssert(pto != NULL);
  1684. flFreeList32.FreeElement( (DWORD)pto );
  1685. thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy3216\n",
  1686. NestingLevelString()));
  1687. }
  1688. //+---------------------------------------------------------------------------
  1689. //
  1690. // Method: CThkMgr::IsProxy3216
  1691. //
  1692. // Synopsis: checks if the given object is a 32/16 proxy
  1693. //
  1694. // Arguments: [punk] -- punk of 32 bit object
  1695. //
  1696. // Returns: 16-bit interface being proxied or NULL
  1697. //
  1698. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  1699. // proper thunking of IN/OUT interfaces
  1700. //----------------------------------------------------------------------------
  1701. VPVOID CThkMgr::IsProxy3216(IUnknown *punkThis32)
  1702. {
  1703. // Local variables
  1704. THUNK3216OBJ *ptoThis32;
  1705. VPVOID vpvThis16 = NULL;
  1706. // Check if the pointer points to valid memory of 3216 proxy type
  1707. if(!IsBadWritePtr(punkThis32, sizeof(THUNK3216OBJ))) {
  1708. ptoThis32 = (THUNK3216OBJ *) punkThis32;
  1709. // Check its vtable
  1710. if(*((void **)ptoThis32->pfnVtbl) == ::QueryInterfaceProxy3216 &&
  1711. *((void **)ptoThis32->pfnVtbl + 1) == ::AddRefProxy3216 &&
  1712. *((void **)ptoThis32->pfnVtbl + 2) == ::ReleaseProxy3216) {
  1713. // Check whether it is alive
  1714. if(ptoThis32->pphHolder) {
  1715. // Assert that the given proxy is indeed alive
  1716. thkAssert(ptoThis32->dwSignature == PSIG3216);
  1717. #if DBG==1
  1718. // In debug builds, ensure that proxy is under its holder
  1719. // and that there is atleast one active proxy under the holder
  1720. BOOL fFound = FALSE, fActive = FALSE;
  1721. CProxy *pProxy;
  1722. PROXYPTR PrxCur, PrxPrev;
  1723. PrxCur = ptoThis32->pphHolder->pprxProxies;
  1724. while(!(fFound && fActive) && !PprxIsNull(PrxCur)) {
  1725. // Remember the proxy and resolve its reference
  1726. PrxPrev = PrxCur;
  1727. pProxy = ResolvePprx(&PrxCur);
  1728. // Assert that the holders match
  1729. thkAssert(ptoThis32->pphHolder == pProxy->pphHolder);
  1730. if(PrxCur.wType == PPRX_32) {
  1731. // Assert that the current 3216 proxy is alive
  1732. thkAssert(pProxy->dwSignature == PSIG3216);
  1733. // Check if the given and current proxies are same
  1734. if(PrxCur.dwPtrVal == (DWORD) punkThis32)
  1735. fFound = TRUE;
  1736. }
  1737. else {
  1738. // Assert that the current proxy is 1632 proxy
  1739. thkAssert(PrxCur.wType == PPRX_16);
  1740. // Assert that the current proxy is alive
  1741. thkAssert(pProxy->dwSignature == PSIG1632);
  1742. }
  1743. // Check if the current proxy is active
  1744. if(pProxy->cRefLocal)
  1745. fActive = TRUE;
  1746. // Obtain the next proxy under this identity
  1747. PrxCur = pProxy->pprxObject;
  1748. ReleasePprx(&PrxPrev);
  1749. }
  1750. thkAssert(fFound && fActive);
  1751. #endif
  1752. // Initialize the return value
  1753. vpvThis16 = ptoThis32->vpvThis16;
  1754. }
  1755. }
  1756. }
  1757. return vpvThis16;
  1758. }
  1759. //+---------------------------------------------------------------------------
  1760. //
  1761. // Method: CThkMgr::CreateOuter32
  1762. //
  1763. // Synopsis: Generates a new 3216 proxy for a given 16-bit outer IUnknown
  1764. // If the given 16-bit IUnknown itself is a proxy, returns
  1765. // the actual 32-bit interface
  1766. //
  1767. // Arguments: [vpvOuter16] -- Outer IUnknown
  1768. // [ppAggHolder] -- Pointer to the proxy holder returned here
  1769. // [pfst] -- Proxy type is returned here
  1770. //
  1771. // Returns: 3216 proxy or the actual 32-bit Interface
  1772. //
  1773. // History: Mar 14,97 Gopalk Created to support aggregation
  1774. // Feb 11, 98 MPrabhu Change to pass back pUnkOuter's holder
  1775. //
  1776. //----------------------------------------------------------------------------
  1777. IUnknown *CThkMgr::CreateOuter32(VPVOID vpvOuter16, PROXYHOLDER **ppAggHolder, DWORD *pfst)
  1778. {
  1779. thkDebugOut((DEB_THUNKMGR, "%sIn CreateOuter32(%p)\n",
  1780. NestingLevelString(), vpvOuter16));
  1781. DebugIncrementNestingLevel();
  1782. // Local variables
  1783. IUnknown *punkOuter32;
  1784. THUNK1632OBJ UNALIGNED *Id1632;
  1785. THUNK3216OBJ *Id3216;
  1786. PROXYHOLDER *pph = NULL;
  1787. DWORD fst = FST_ERROR;
  1788. BOOL fFail = FALSE;
  1789. if(punkOuter32 = IsProxy1632(vpvOuter16)) {
  1790. // The given 16-bit interface itself is a proxy to a 32-bit interface
  1791. Id1632 = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
  1792. pph = Id1632->pphHolder;
  1793. RELVDMPTR(vpvOuter16);
  1794. /* rm: nested aggregation
  1795. if(pph->dwFlags & PH_AGGREGATEE) {
  1796. // Nested aggregation
  1797. thkAssert(pph->unkProxy.wType == PPRX_16);
  1798. thkAssert(!"Nested aggregation case");
  1799. // If proxies for PUNKOUTER and PUNKINNER are modfied to coordinate
  1800. // transfer of references during QI calls on PUNKINNER, creation of
  1801. // proxy to a proxy can be avoided for nested aggreagtion
  1802. // Ensure that the user passed the true identity
  1803. if(pph->unkProxy.dwPtrVal != vpvOuter16) {
  1804. // Identity needs to be switched
  1805. thkAssert(!"Switching to True Identity for Aggregation");
  1806. // Obtain the true identity
  1807. vpvOuter16 = pph->unkProxy.dwPtrVal;
  1808. }
  1809. // Reset the return value to create a identity proxy
  1810. punkOuter32 = NULL;
  1811. }
  1812. else {
  1813. */
  1814. // Aggregation through delegation
  1815. thkAssert(!"Aggregation through delegation");
  1816. punkOuter32->AddRef();
  1817. // Initialize return value
  1818. fst = FST_SHORTCUT;
  1819. /* rm: nested aggregation
  1820. }
  1821. */
  1822. }
  1823. else if(Id3216 = LookupProxy3216(vpvOuter16)) {
  1824. // Found an existing proxy
  1825. thkDebugOut((DEB_THUNKMGR, "%sCreateOuter32 found existing proxy,(%p)->%p\n",
  1826. NestingLevelString(), vpvOuter16, Id3216));
  1827. // Validate the proxy
  1828. DebugValidateProxy3216(Id3216);
  1829. // Obtain its holder
  1830. pph = Id3216->pphHolder;
  1831. // Assert that the holder represents a 16-bit identity
  1832. thkAssert(pph->unkProxy.wType == PPRX_32);
  1833. thkAssert(pph->dwFlags & PH_NORMAL);
  1834. // Ensure that the user passed the true identity
  1835. if(pph->unkProxy.dwPtrVal != (DWORD) Id3216) {
  1836. // Identity needs to be switched
  1837. thkAssert(!"Switching to True Identity for Aggregation");
  1838. // Obtain the true identity
  1839. vpvOuter16 = Id3216->vpvThis16;
  1840. }
  1841. }
  1842. else {
  1843. // No interface on the identity has crossed thunking layer
  1844. // Ensure that the user passed the true identity
  1845. SCODE scRet;
  1846. VPVOID vpvUnk;
  1847. scRet = QueryInterfaceOnObj16(vpvOuter16, IID_IUnknown, (void **)&vpvUnk);
  1848. if(SUCCEEDED(scRet) && vpvUnk) {
  1849. // Fix up the reference count
  1850. ReleaseOnObj16(vpvOuter16);
  1851. // Switch the identity if needed
  1852. if(vpvOuter16 != vpvUnk) {
  1853. // Identity needs to be switched
  1854. thkAssert(!"Switching to True Identity for Aggregation");
  1855. // Obtain the true identity
  1856. vpvOuter16 = vpvUnk;
  1857. }
  1858. }
  1859. else {
  1860. // This is pretty nasty.
  1861. Win4Assert(!"QI for IUnknown on the 16-bit interface failed");
  1862. Win4Assert(!vpvUnk);
  1863. // But I am allowing the behavior as some 16-bit apps like
  1864. // VB4.0 pass interfaces that do not respond to QI for
  1865. // IUnknown
  1866. }
  1867. }
  1868. // Create a new 1632 proxy
  1869. if(!punkOuter32 && vpvOuter16) {
  1870. Id3216 = (THUNK3216OBJ *) flFreeList32.AllocElement();
  1871. if(Id3216) {
  1872. // AddRef the 16-bit IUnknown
  1873. AddRefOnObj16(vpvOuter16);
  1874. // Update proxy fields
  1875. Id3216->pfnVtbl = (DWORD) athopiInterfaceThopis[THI_IUnknown].pt3216fn;
  1876. Id3216->cRefLocal = 1;
  1877. Id3216->cRef = 1;
  1878. Id3216->iidx = THI_IUnknown;
  1879. Id3216->vpvThis16 = vpvOuter16;
  1880. Id3216->grfFlags = PROXYFLAG_PUNKOUTER;
  1881. PprxNull(Id3216->pprxObject);
  1882. Id3216->pphHolder = NULL;
  1883. #if DBG == 1
  1884. Id3216->dwSignature = PSIG3216;
  1885. #endif
  1886. // Create a new AGGREGATE holder
  1887. pph = NewHolder((DWORD)Id3216, PROXYPTR((DWORD)Id3216, PPRX_32),
  1888. PH_AGGREGATEE);
  1889. if(pph) {
  1890. // Initialize the return values
  1891. fst = FST_CREATED_NEW;
  1892. punkOuter32 = (IUnknown *) Id3216;
  1893. }
  1894. else {
  1895. flFreeList32.FreeElement((DWORD) Id3216);
  1896. ReleaseOnObj16(vpvOuter16);
  1897. }
  1898. }
  1899. }
  1900. // Set the return value
  1901. if(pfst)
  1902. *pfst = fst;
  1903. if (pph)
  1904. *ppAggHolder = pph;
  1905. DebugDecrementNestingLevel();
  1906. thkDebugOut((DEB_THUNKMGR, "%sOut CreateOuter32(%p)->%p\n",
  1907. NestingLevelString(), punkOuter32, vpvOuter16));
  1908. // This may be a proxy or a real 16-bit interface
  1909. return punkOuter32;
  1910. }
  1911. //+---------------------------------------------------------------------------
  1912. //
  1913. // Method: CThkMgr::CreateOuter16
  1914. //
  1915. // Synopsis: Generates a new 1632 proxy for a given 32-bit outer IUnknown
  1916. // If the given 32-bit IUnknown itself is a proxy, returns
  1917. // the actual 16-bit interface
  1918. //
  1919. // Arguments: [punkOuter32] -- Outer IUnknown
  1920. // [ppAggHolder] -- Pointer to the proxy holder returned here
  1921. // [pfst] -- Proxy type is returned here
  1922. //
  1923. // Returns: 1632 proxy or the actual 16-bit Interface
  1924. //
  1925. // History: Mar 14,97 Gopalk Created to support aggregation
  1926. // Feb 11, 98 MPrabhu Change to pass back pUnkOuter's holder
  1927. //
  1928. //----------------------------------------------------------------------------
  1929. VPVOID CThkMgr::CreateOuter16(IUnknown *punkOuter32, PROXYHOLDER **ppAggHolder, DWORD *pfst)
  1930. {
  1931. thkDebugOut((DEB_THUNKMGR, "%sIn CreateOuter16(%p)\n",
  1932. NestingLevelString(), punkOuter32));
  1933. DebugIncrementNestingLevel();
  1934. // Local variables
  1935. VPVOID vpvOuter16;
  1936. THUNK1632OBJ UNALIGNED *Id1632;
  1937. PROXYHOLDER *pph = NULL;
  1938. DWORD fst = FST_ERROR;
  1939. if(vpvOuter16 = IsProxy3216(punkOuter32)) {
  1940. // The given 32-bit interface itself is a proxy to a 16-bit interface
  1941. pph = ((THUNK3216OBJ *) punkOuter32)->pphHolder;
  1942. /* rm: nested aggregation
  1943. if(pph->dwFlags & PH_AGGREGATEE) {
  1944. // Nested aggregation
  1945. thkAssert(pph->unkProxy.wType == PPRX_32);
  1946. thkAssert(!"Nested aggregation case");
  1947. // If proxies for PUNKOUTER and PUNKINNER are modfied to coordinate
  1948. // transfer of references during QI calls on PUNKINNER, creation of
  1949. // proxy to a proxy can be avoided for nested aggreagtion
  1950. // Ensure that the user passed the true identity
  1951. if(pph->unkProxy.dwPtrVal != (DWORD) punkOuter32) {
  1952. // Identity needs to be switched
  1953. thkAssert(!"Switching to True Identity for Aggregation");
  1954. // Obtain the true identity
  1955. punkOuter32 = (IUnknown *) pph->unkProxy.dwPtrVal;
  1956. }
  1957. // Reset the return value to create a identity proxy
  1958. vpvOuter16 = NULL;
  1959. }
  1960. else {
  1961. */
  1962. // Aggregation through delegation
  1963. thkAssert(!"Aggregation through delegation");
  1964. AddRefOnObj16(vpvOuter16);
  1965. // Initialize return value
  1966. fst = FST_SHORTCUT;
  1967. /* rm: nested aggregation
  1968. }
  1969. */
  1970. }
  1971. else if(vpvOuter16 = LookupProxy1632(punkOuter32)) {
  1972. // Found an existing proxy
  1973. thkDebugOut((DEB_THUNKMGR, "%sCreateOuter16 found existing proxy,(%p)->%p\n",
  1974. NestingLevelString(), punkOuter32, vpvOuter16));
  1975. // Validate the proxy
  1976. DebugValidateProxy1632(vpvOuter16);
  1977. // Obtain its holder
  1978. Id1632 = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
  1979. pph = Id1632->pphHolder;
  1980. RELVDMPTR(vpvOuter16);
  1981. // Assert that the holder represents a 32-bit identity
  1982. thkAssert(pph->unkProxy.wType == PPRX_16);
  1983. thkAssert(pph->dwFlags & PH_NORMAL);
  1984. // Ensure that the user passed the true identity
  1985. if(pph->unkProxy.dwPtrVal != vpvOuter16) {
  1986. // Identity needs to be switched
  1987. thkAssert(!"Switching to True Identity for Aggregation");
  1988. // Obtain the true identity
  1989. Id1632 = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  1990. punkOuter32 = Id1632->punkThis32;
  1991. RELVDMPTR(pph->unkProxy.dwPtrVal);
  1992. }
  1993. // Reset the return value to create a identity proxy
  1994. vpvOuter16 = NULL;
  1995. }
  1996. else {
  1997. // No interface on the identity has crossed thunking layer
  1998. // Ensure that the user passed the true identity
  1999. SCODE scRet;
  2000. IUnknown *pUnk;
  2001. scRet = punkOuter32->QueryInterface(IID_IUnknown, (void **) &pUnk);
  2002. if(SUCCEEDED(scRet) && pUnk) {
  2003. // Fix up the reference count
  2004. punkOuter32->Release();
  2005. // Switch the identity if needed
  2006. if(punkOuter32 != pUnk) {
  2007. // Identity needs to be switched
  2008. thkAssert(!"Switching to True Identity for Aggregation");
  2009. // Obtain the true identity
  2010. punkOuter32 = pUnk;
  2011. }
  2012. }
  2013. else {
  2014. // This is pretty nasty.
  2015. Win4Assert(!"QI for IUnknown on the 32-bit interface failed");
  2016. Win4Assert(!pUnk);
  2017. punkOuter32 = NULL;
  2018. }
  2019. }
  2020. // Create a new 1632 proxy
  2021. if(!vpvOuter16 && punkOuter32) {
  2022. vpvOuter16 = flFreeList16.AllocElement();
  2023. if(vpvOuter16) {
  2024. // AddRef the 32-bit IUnknown
  2025. punkOuter32->AddRef();
  2026. Id1632 = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
  2027. thkAssert(Id1632);
  2028. // Update proxy fields
  2029. Id1632->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
  2030. Id1632->cRefLocal = 1;
  2031. Id1632->cRef = 1;
  2032. Id1632->iidx = THI_IUnknown;
  2033. Id1632->punkThis32 = punkOuter32;
  2034. Id1632->grfFlags = PROXYFLAG_PUNKOUTER;
  2035. PprxNull(Id1632->pprxObject);
  2036. Id1632->pphHolder = NULL;
  2037. #if DBG == 1
  2038. Id1632->dwSignature = PSIG1632;
  2039. #endif
  2040. RELVDMPTR(vpvOuter16);
  2041. // Create a new AGGREGATEE holder
  2042. pph = NewHolder(vpvOuter16, PROXYPTR(vpvOuter16, PPRX_16), PH_AGGREGATEE);
  2043. if(pph) {
  2044. // Initialize return value
  2045. fst = FST_CREATED_NEW;
  2046. }
  2047. else {
  2048. flFreeList16.FreeElement(vpvOuter16);
  2049. punkOuter32->Release();
  2050. // Initialize the return value
  2051. vpvOuter16 = NULL;
  2052. }
  2053. }
  2054. }
  2055. // Set the return value
  2056. if(pfst)
  2057. *pfst = fst;
  2058. if (pph)
  2059. *ppAggHolder = pph;
  2060. DebugDecrementNestingLevel();
  2061. thkDebugOut((DEB_THUNKMGR, "%sOut CreateOuter16(%p)->%p\n",
  2062. NestingLevelString(), punkOuter32, vpvOuter16));
  2063. // This may be a 1632 proxy or a real 16-bit interface
  2064. return vpvOuter16;
  2065. }
  2066. //+---------------------------------------------------------------------------
  2067. //
  2068. // Method: CThkMgr::Object32Identity
  2069. //
  2070. // Synopsis: Finds/Creates a 32/16 IUnknown proxy on a given 16-bit object
  2071. // to establish its identity.
  2072. //
  2073. // Arguments: [punkThis32] -- 32-bit Object
  2074. // [pProxy] -- Proxy representing Identity
  2075. // [pfst] -- Search result is returned here
  2076. //
  2077. // Returns: Proxy representing object identity. In addition, the
  2078. // returned proxy is AddRefed only if it represents a
  2079. // 16-bit identity
  2080. //
  2081. // History: Mar 14,97 Gopalk Created to support aggregation and
  2082. // proper thunking of IN/OUT interfaces
  2083. //----------------------------------------------------------------------------
  2084. SCODE CThkMgr::Object32Identity(IUnknown *punkThis32, PROXYPTR *pProxy, DWORD *pfst)
  2085. {
  2086. // Local variables
  2087. DWORD fst = FST_ERROR;
  2088. SCODE scRet;
  2089. VPVOID vpvProxy = NULL;
  2090. IUnknown *pUnk;
  2091. THUNK1632OBJ UNALIGNED *ptoProxy;
  2092. PROXYHOLDER *pph = NULL;
  2093. // QI for IUnknown on the 32-bit interface
  2094. scRet = punkThis32->QueryInterface(IID_IUnknown, (void **) &pUnk);
  2095. if(SUCCEEDED(scRet) && pUnk) {
  2096. // Lookup the indentity
  2097. if(_pHolderTbl->Lookup((VPVOID) pUnk, (void *&)pph)) {
  2098. // Identity exists for IUnknown
  2099. thkAssert(pph);
  2100. if (pph)
  2101. {
  2102. thkAssert(pph->unkProxy.dwPtrVal);
  2103. if(pph->dwFlags & PH_AGGREGATEE) {
  2104. thkAssert(pph->unkProxy.wType == PPRX_32);
  2105. DebugValidateProxy3216((THUNK3216OBJ *) pph->unkProxy.dwPtrVal);
  2106. }
  2107. else {
  2108. thkAssert(pph->unkProxy.wType == PPRX_16);
  2109. DebugValidateProxy1632(pph->unkProxy.dwPtrVal);
  2110. }
  2111. // Fix up the reference count
  2112. pUnk->Release();
  2113. // Initialize return values
  2114. *pProxy = pph->unkProxy;
  2115. fst = FST_USED_EXISTING;
  2116. }
  2117. else
  2118. {
  2119. scRet = E_FAIL;
  2120. fst = FST_ERROR;
  2121. }
  2122. }
  2123. else {
  2124. // Identity does not exist for IUnknown which means that
  2125. // the IUnknown is indeed a 32-bit interface that has
  2126. // not been seen till now. Establish its identity
  2127. thkAssert(!pph);
  2128. // Create the proxy for 32-bit IUnknown
  2129. vpvProxy = flFreeList16.AllocElement();
  2130. if(vpvProxy) {
  2131. // Put the new proxy in the proxy list
  2132. if(_pProxyTbl1632->SetAt((DWORD) pUnk, (void *)vpvProxy)) {
  2133. ptoProxy = FIXVDMPTR(vpvProxy, THUNK1632OBJ);
  2134. thkAssert(ptoProxy);
  2135. // Update proxy fields
  2136. ptoProxy->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
  2137. ptoProxy->cRefLocal = 1;
  2138. ptoProxy->cRef = 1;
  2139. ptoProxy->iidx = THI_IUnknown;
  2140. ptoProxy->punkThis32 = pUnk;
  2141. ptoProxy->grfFlags = PROXYFLAG_PUNK;
  2142. PprxNull(ptoProxy->pprxObject);
  2143. ptoProxy->pphHolder = NULL;
  2144. #if DBG == 1
  2145. ptoProxy->dwSignature = PSIG1632;
  2146. #endif
  2147. RELVDMPTR(vpvProxy);
  2148. // Initialize return value
  2149. pProxy->dwPtrVal = vpvProxy;
  2150. pProxy->wType = PPRX_16;
  2151. // Create a new NONAGGREGATE holder
  2152. pph = NewHolder((VPVOID) pUnk, *pProxy, PH_NORMAL);
  2153. if(pph) {
  2154. // Initialize return value
  2155. fst = FST_CREATED_NEW;
  2156. }
  2157. else {
  2158. // Remove the key from the 1632 proxy table
  2159. #if DBG==1
  2160. thkAssert(_pProxyTbl1632->RemoveKey((DWORD) pUnk));
  2161. #else
  2162. _pProxyTbl1632->RemoveKey((DWORD) pUnk);
  2163. #endif
  2164. }
  2165. }
  2166. }
  2167. }
  2168. }
  2169. else {
  2170. // This is pretty nasty.
  2171. Win4Assert(!"QI for IUnknown on the 32-bit interface failed");
  2172. Win4Assert(!pUnk);
  2173. }
  2174. // Cleanup if something has gone wrong
  2175. if(fst == FST_ERROR) {
  2176. if(vpvProxy) {
  2177. flFreeList16.FreeElement(vpvProxy);
  2178. }
  2179. if(pUnk) {
  2180. pUnk->Release();
  2181. scRet = E_OUTOFMEMORY;
  2182. }
  2183. // Reset return value
  2184. pProxy->dwPtrVal = NULL;
  2185. pProxy->wType = PPRX_NONE;
  2186. }
  2187. else {
  2188. scRet = NOERROR;
  2189. }
  2190. // Indicate the type being returned
  2191. if(pfst)
  2192. *pfst = fst;
  2193. return scRet;
  2194. }
  2195. //+---------------------------------------------------------------------------
  2196. //
  2197. // Method: CThkMgr::Object16Identity
  2198. //
  2199. // Synopsis: Finds/Creates a 32/16 IUnknown proxy on a given 16-bit object
  2200. // to establish its identity.
  2201. //
  2202. // Arguments: [vpvThis16] -- 16-bit Object
  2203. // [pProxy] -- Proxy representing Identity
  2204. // [pfst] -- Search result is returned here
  2205. //
  2206. // Returns: Proxy representing object identity. In addition, the
  2207. // returned proxy is AddRefed only if it represents a
  2208. // 16-bit identity
  2209. //
  2210. // History: Mar 14,97 Gopalk Created to support aggregation and
  2211. // proper thunking of IN/OUT interfaces
  2212. //----------------------------------------------------------------------------
  2213. SCODE CThkMgr::Object16Identity(VPVOID vpvThis16, PROXYPTR *pProxy, DWORD *pfst, BOOL bCallQI, BOOL bExtraAddRef)
  2214. {
  2215. // Local variables
  2216. DWORD fst = FST_ERROR;
  2217. SCODE scRet;
  2218. THUNK3216OBJ *punkProxy = NULL;
  2219. VPVOID vpvUnk = NULL;
  2220. PROXYHOLDER *pph = NULL;
  2221. if (bCallQI) {
  2222. // QI for IUnknown on the 16-bit interface
  2223. scRet = QueryInterfaceOnObj16(vpvThis16, IID_IUnknown, (void **)&vpvUnk);
  2224. }
  2225. else {
  2226. scRet = E_FAIL; // this will force the QI workaround below
  2227. }
  2228. if(FAILED(scRet)) {
  2229. // This is pretty nasty.
  2230. Win4Assert(!"QI for IUnknown on the 16-bit interface failed");
  2231. Win4Assert(!vpvUnk);
  2232. // But I am allowing the behavior as VB4.0 16-bit passes an
  2233. // IStorage to WriteClassStg api that does not respond to QI
  2234. // for IUnknown. See NT Raid Bug #82195
  2235. scRet = NOERROR;
  2236. vpvUnk = vpvThis16;
  2237. // AddRef the 16-bit interface
  2238. AddRefOnObj16(vpvUnk);
  2239. }
  2240. else {
  2241. // Assert that identity has been established
  2242. Win4Assert(vpvUnk);
  2243. }
  2244. // Lookup the indentity
  2245. if(_pHolderTbl->Lookup(vpvUnk, (void *&)pph)) {
  2246. // Identity exists for IUnknown
  2247. thkAssert(pph);
  2248. if (pph)
  2249. {
  2250. thkAssert(pph->unkProxy.dwPtrVal);
  2251. if(pph->dwFlags & PH_AGGREGATEE) {
  2252. thkAssert(pph->unkProxy.wType == PPRX_16);
  2253. DebugValidateProxy1632(pph->unkProxy.dwPtrVal);
  2254. }
  2255. else {
  2256. thkAssert(pph->unkProxy.wType == PPRX_32);
  2257. DebugValidateProxy3216((THUNK3216OBJ *) pph->unkProxy.dwPtrVal);
  2258. }
  2259. // Fix up the reference count
  2260. ReleaseOnObj16(vpvUnk);
  2261. // Initialize return values
  2262. *pProxy = pph->unkProxy;
  2263. fst = FST_USED_EXISTING;
  2264. }
  2265. else
  2266. {
  2267. fst = FST_ERROR;
  2268. scRet = E_FAIL;
  2269. }
  2270. }
  2271. else {
  2272. // Identity does not exist for IUnknown which means that
  2273. // the IUnknown is indeed a 16-bit interface that has
  2274. // not been seen till now. Establish its identity
  2275. thkAssert(!pph);
  2276. // Create the proxy for 16-bit IUnknown
  2277. punkProxy = (THUNK3216OBJ *) flFreeList32.AllocElement();
  2278. if(punkProxy) {
  2279. // Put the new proxy in the proxy list
  2280. if(_pProxyTbl3216->SetAt(vpvUnk, punkProxy)) {
  2281. // Update proxy fields
  2282. punkProxy->pfnVtbl = (DWORD)athopiInterfaceThopis[THI_IUnknown].pt3216fn;
  2283. punkProxy->cRefLocal = 1;
  2284. punkProxy->cRef = 1;
  2285. punkProxy->iidx = THI_IUnknown;
  2286. punkProxy->vpvThis16 = vpvUnk;
  2287. punkProxy->grfFlags = PROXYFLAG_PUNK;
  2288. PprxNull(punkProxy->pprxObject);
  2289. punkProxy->pphHolder = NULL;
  2290. #if DBG == 1
  2291. punkProxy->dwSignature = PSIG3216;
  2292. #endif
  2293. // Initialize return value
  2294. pProxy->dwPtrVal = (DWORD) punkProxy;
  2295. pProxy->wType = PPRX_32;
  2296. // Create a new NONAGGREGATE holder
  2297. pph = NewHolder(vpvUnk, *pProxy, PH_NORMAL);
  2298. if(pph) {
  2299. // Initialize return value
  2300. fst = FST_CREATED_NEW;
  2301. if (bExtraAddRef) { //Hack
  2302. AddRefOnObj16(vpvUnk);
  2303. }
  2304. }
  2305. else {
  2306. // Remove the key from the 3216 proxy table
  2307. #if DBG==1
  2308. thkAssert(_pProxyTbl3216->RemoveKey(vpvUnk));
  2309. #else
  2310. _pProxyTbl3216->RemoveKey(vpvUnk);
  2311. #endif
  2312. }
  2313. }
  2314. }
  2315. }
  2316. // Cleanup if something has gone wrong
  2317. if(fst == FST_ERROR) {
  2318. if(punkProxy) {
  2319. flFreeList32.FreeElement((DWORD) punkProxy);
  2320. }
  2321. if(vpvUnk) {
  2322. ReleaseOnObj16(vpvUnk);
  2323. scRet = E_OUTOFMEMORY;
  2324. }
  2325. // Reset return value
  2326. pProxy->dwPtrVal = NULL;
  2327. pProxy->wType = PPRX_NONE;
  2328. }
  2329. else {
  2330. scRet = NOERROR;
  2331. }
  2332. // Indicate the type being returned
  2333. if(pfst)
  2334. *pfst = fst;
  2335. return scRet;
  2336. }
  2337. //+---------------------------------------------------------------------------
  2338. //
  2339. // Method: CThkMgr::FindProxy3216
  2340. //
  2341. // Synopsis: Finds/Creates a 32/16 proxy for a given 16-bit interface.
  2342. // If the given 16-bit interface itself is a proxy, returns
  2343. // the actual 32-bit Interface
  2344. //
  2345. // Arguments: [vpvPrealloc] -- Preallocated 32/16 proxy
  2346. // [vpvThis16] -- 16-bit Interface to be proxied
  2347. // [iidx] -- Interface index or IID
  2348. // [pfst] -- Return value to hold the kind proxy object
  2349. //
  2350. // Returns: 32/16 proxy object or the actual 32-bit Interface
  2351. //
  2352. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2353. // proper thunking of IN/OUT interfaces
  2354. //----------------------------------------------------------------------------
  2355. IUnknown *CThkMgr::FindProxy3216(THUNK3216OBJ *ptoPrealloc, VPVOID vpvThis16,
  2356. PROXYHOLDER *pgHolder, IIDIDX iidx,
  2357. BOOL bExtraAddRef, DWORD *pfst)
  2358. {
  2359. thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy3216(%p, %p, %s)\n",
  2360. NestingLevelString(), ptoPrealloc, vpvThis16, IidIdxString(iidx)));
  2361. DebugIncrementNestingLevel();
  2362. // Local variables
  2363. THUNK3216OBJ *pto = NULL, *punkProxy = NULL;
  2364. IUnknown *pProxy;
  2365. DWORD fst, Fail = FALSE;
  2366. // Validation checks
  2367. thkAssert(vpvThis16);
  2368. #if DBG == 1
  2369. // Ensure that the preallocated proxy is not in use
  2370. if(ptoPrealloc) {
  2371. if(ptoPrealloc->grfFlags & PROXYFLAG_TEMPORARY)
  2372. thkAssert(ptoPrealloc->cRefLocal == 0 && ptoPrealloc->cRef == 0);
  2373. }
  2374. #endif
  2375. // Initialize the fst value
  2376. fst = FST_ERROR;
  2377. // If proxy was preallocated for this IID using CanGetNewProxy, it would
  2378. // have added it to the requested IID list.
  2379. if (ptoPrealloc != 0 && IIDIDX_IS_IID(iidx))
  2380. RemoveIIDRequest(*IIDIDX_IID(iidx));
  2381. if(pto = LookupProxy3216(vpvThis16)) {
  2382. // Found an existing proxy
  2383. thkDebugOut((DEB_THUNKMGR, "%sFindProxy3216 found existing proxy,(%p)->%p\n",
  2384. NestingLevelString(), vpvThis16, pto));
  2385. // Assert that the holders match
  2386. thkAssert(pto->pphHolder);
  2387. thkAssert(!(pto->grfFlags & PROXYFLAG_PUNKINNER));
  2388. if(pgHolder && pto->pphHolder!=pgHolder) {
  2389. thkAssert(pto->pphHolder->dwFlags & PH_AGGREGATEE);
  2390. }
  2391. // Check the proxy IID against the given IID. If the server has passed
  2392. // the same 32-bit interface pointer against another IID, it is possible
  2393. // for the IID's to be different. If the Interface2 derives from Interface1,
  2394. // the interface pointers for them would be the same in C or C++. An
  2395. // excellant example would be IPersistStorage deriving from IPersist.
  2396. // IIDIDXs are related to interfaces in thunk tables, which are organized
  2397. // such that more derived interfaces have higher indices than the less
  2398. // derived ones. Custom interfaces have an IID rather than an index, and
  2399. // consequently are not affected by the following statement.
  2400. if(IIDIDX_IS_INDEX(iidx)) {
  2401. // Check if the new IID is more derived than the existing one
  2402. if(IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx)) {
  2403. // Change the vtable pointer to the more derived interface
  2404. pto->pfnVtbl = (DWORD)athopiInterfaceThopis[IIDIDX_INDEX(iidx)].pt3216fn;
  2405. pto->iidx = iidx;
  2406. }
  2407. }
  2408. // AddRef the proxy
  2409. AddRefProxy3216(pto);
  2410. // Set return values
  2411. fst = FST_USED_EXISTING;
  2412. pProxy = (IUnknown *)pto;
  2413. }
  2414. else if(pProxy = IsProxy1632(vpvThis16)) {
  2415. // The given 16-bit interface itself is a proxy to a 32-bit
  2416. // interface
  2417. thkDebugOut((DEB_THUNKMGR, "%sFindProxy3216 shortcut proxy,(%p)->%p\n",
  2418. NestingLevelString(), vpvThis16, pProxy));
  2419. THUNK1632OBJ UNALIGNED *pProxy1632;
  2420. // Fix the VDM pointer
  2421. pProxy1632 = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
  2422. // Assert that the holders match
  2423. thkAssert(pProxy1632->pphHolder);
  2424. thkAssert(!(pProxy1632->grfFlags & PROXYFLAG_PUNKINNER));
  2425. if(pgHolder && pProxy1632->pphHolder!=pgHolder) {
  2426. thkAssert(pProxy1632->pphHolder->dwFlags & PH_AGGREGATEE);
  2427. }
  2428. // Release the VDM pointer
  2429. RELVDMPTR(vpvThis16);
  2430. // Avoid creating a proxie to another proxie
  2431. THKSTATE thkstate;
  2432. // Remember the current thunk state
  2433. thkstate = GetThkState();
  2434. // Set the thunk state to THKSTATE_NOCALL
  2435. SetThkState(THKSTATE_NOCALL);
  2436. // AddRef actual the 32-bit interface
  2437. pProxy->AddRef();
  2438. // Restore previous thunk state. Remember the Excel Hack
  2439. SetThkState(thkstate);
  2440. // Set the type of proxy being returned
  2441. fst = FST_SHORTCUT;
  2442. }
  2443. else {
  2444. // An existing proxy has not been found and the interface to proxied
  2445. // is a real 16-bit interface.
  2446. // Check if holder has not been given
  2447. if(!pgHolder) {
  2448. // This interface is being obtained through a method call
  2449. PROXYPTR unkPPtr;
  2450. SCODE error;
  2451. BOOL bCallQI = TRUE;
  2452. if((TlsThkGetAppCompatFlags() & OACF_CRLPNTPERSIST) &&
  2453. (iidx==THI_IPersistStorage)) {
  2454. thkDebugOut((DEB_WARN,"CorelPaint Hack Used\n"));
  2455. bCallQI = FALSE;
  2456. }
  2457. // Obtain the identity of 16-bit object
  2458. error = Object16Identity(vpvThis16, &unkPPtr, &fst, bCallQI, bExtraAddRef);
  2459. if(error == NOERROR) {
  2460. // Check for aggregation case
  2461. if(unkPPtr.wType==PPRX_32) {
  2462. // Check if vpvThis16 itself is an IUnknown interface
  2463. if(iidx == THI_IUnknown) {
  2464. // Initialize the return value
  2465. pProxy = (IUnknown *) unkPPtr.dwPtrVal;
  2466. // Check if the identity has been switched
  2467. if(fst == FST_USED_EXISTING) {
  2468. // The IUnknown identity has already been established
  2469. // The app was trying to pass someother 16-bit interface
  2470. // as IUnknown.
  2471. thkDebugOut((DEB_WARN, "Switched to correct Identity\n"));
  2472. // AddRef the proxy being returned
  2473. AddRefProxy3216((THUNK3216OBJ *) pProxy);
  2474. }
  2475. else {
  2476. thkAssert(fst == FST_CREATED_NEW);
  2477. }
  2478. }
  2479. else {
  2480. THUNK3216OBJ *Id3216 = (THUNK3216OBJ *) unkPPtr.dwPtrVal;
  2481. // Check if the identity has just been established
  2482. if(fst == FST_CREATED_NEW) {
  2483. // Check if the Identity and current IID share the same
  2484. // interface pointer
  2485. if(Id3216->vpvThis16==vpvThis16) {
  2486. // Check if the new IID is more derived than the existing one
  2487. if(IIDIDX_IS_INDEX(iidx) && iidx>Id3216->iidx) {
  2488. // Change the vtable pointer to the more derived interface
  2489. Id3216->pfnVtbl = (DWORD)athopiInterfaceThopis[iidx].pt3216fn;
  2490. Id3216->iidx = iidx;
  2491. }
  2492. // Initialize the return value
  2493. pProxy = (IUnknown *) Id3216;
  2494. }
  2495. else {
  2496. // We need to release the IUnknown proxy after adding
  2497. // the proxy representing vpvThis16 to the its holder
  2498. punkProxy = Id3216;
  2499. }
  2500. }
  2501. else {
  2502. thkAssert(fst == FST_USED_EXISTING);
  2503. }
  2504. // Obtain the holder of the identity
  2505. pgHolder = Id3216->pphHolder;
  2506. }
  2507. }
  2508. else {
  2509. // Obtain the holder of the identity
  2510. THUNK1632OBJ UNALIGNED *Id1632;
  2511. IUnknown *punkTemp;
  2512. Id1632 = FIXVDMPTR(unkPPtr.dwPtrVal, THUNK1632OBJ);
  2513. pgHolder = Id1632->pphHolder;
  2514. punkTemp = Id1632->punkThis32;
  2515. RELVDMPTR(unkPPtr.dwPtrVal);
  2516. // Sanity checks
  2517. thkAssert(fst == FST_USED_EXISTING);
  2518. thkAssert(pgHolder->dwFlags & PH_AGGREGATEE);
  2519. // Check if vpvThis16 itself is an IUnknown interface
  2520. if(iidx == THI_IUnknown) {
  2521. // The IUnknown identity has already been established
  2522. // The app was trying to pass someother 16-bit interface
  2523. // as IUnknown. Switch to correct identity
  2524. thkAssert(!"Switched to correct Identity");
  2525. // Initialize the return value
  2526. pProxy = punkTemp;
  2527. // AddRef the actual 32-bit interface being returned
  2528. pProxy->AddRef();
  2529. }
  2530. }
  2531. }
  2532. else {
  2533. // Failed to obtain the identity
  2534. Fail = TRUE;
  2535. }
  2536. }
  2537. }
  2538. if(!pProxy && !Fail) {
  2539. // Assert that we have holder
  2540. thkAssert(pgHolder);
  2541. // Reset the fst value
  2542. fst = FST_ERROR;
  2543. // Obtain either a preallocated or a new proxy
  2544. if(ptoPrealloc) {
  2545. // Use the preallocated proxy
  2546. pto = ptoPrealloc;
  2547. ptoPrealloc = NULL;
  2548. }
  2549. else {
  2550. // Create a new proxy
  2551. pto = (THUNK3216OBJ *) flFreeList32.AllocElement();
  2552. }
  2553. // Ensure that we have a proxy
  2554. if(pto) {
  2555. // Put the new proxy in the proxy list
  2556. if(_pProxyTbl3216->SetAt(vpvThis16, pto)) {
  2557. // Convert a custom IID to THI_IUnknown as we thunk
  2558. // only its IUnknown methods
  2559. if(IIDIDX_IS_IID(iidx))
  2560. iidx = INDEX_IIDIDX(THI_IUnknown);
  2561. // AddRef the 16-bit interface
  2562. AddRefOnObj16(vpvThis16);
  2563. // Update proxy fields
  2564. pto->pfnVtbl = (DWORD)athopiInterfaceThopis[iidx].pt3216fn;
  2565. pto->cRefLocal = 1;
  2566. pto->cRef = 1;
  2567. pto->iidx = iidx;
  2568. pto->vpvThis16 = vpvThis16;
  2569. pto->grfFlags = PROXYFLAG_PIFACE;
  2570. PprxNull(pto->pprxObject);
  2571. pto->pphHolder = NULL;
  2572. AddProxyToHolder(pgHolder, pto, Pprx32(pto));
  2573. #if DBG == 1
  2574. pto->dwSignature = PSIG3216;
  2575. #endif
  2576. thkDebugOut((DEB_THUNKMGR,
  2577. "%sFindProxy3216 added new proxy, %s (%p)->%p (%d,%d)\n",
  2578. NestingLevelString(), inInterfaceNames[pto->iidx].pszInterface,
  2579. vpvThis16, pto, pto->cRefLocal, pto->cRef));
  2580. // Set the return values
  2581. pProxy = (IUnknown *) pto;
  2582. fst = FST_CREATED_NEW;
  2583. }
  2584. else {
  2585. // Cleanup the proxy only if it was newly created
  2586. if(fst == FST_CREATED_NEW)
  2587. flFreeList32.FreeElement((DWORD) pto);
  2588. pProxy = NULL;
  2589. fst = 0;
  2590. }
  2591. }
  2592. }
  2593. else {
  2594. if(Fail) {
  2595. thkAssert(pProxy == NULL && fst == FST_ERROR);
  2596. }
  2597. }
  2598. // Cleanup the allocated proxy if it has not been used
  2599. if(ptoPrealloc)
  2600. flFreeList32.FreeElement((DWORD)ptoPrealloc);
  2601. // Release the IUnknown proxy. If it was newly created for establishing
  2602. // the identity of the given 16-bit interface , the following release
  2603. // would be the last release on the IUnknown proxy and consequently,
  2604. // would destroy it along with its holder
  2605. if(punkProxy)
  2606. ReleaseProxy3216(punkProxy);
  2607. // Set the return value
  2608. if(pfst)
  2609. *pfst = fst;
  2610. DebugDecrementNestingLevel();
  2611. thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy3216: (%p)->%p\n",
  2612. NestingLevelString(), vpvThis16, pProxy));
  2613. return pProxy;
  2614. }
  2615. //+---------------------------------------------------------------------------
  2616. //
  2617. // Method: CThkMgr::FindAggregate3216
  2618. //
  2619. // Synopsis: Finds/Generates a 32/16 proxy for a given 16-bit interface
  2620. // that is aggregated with the given outer unknown.
  2621. // If the given 16-bit interface itself is a proxy, returns
  2622. // the actual 32-bit Interface
  2623. //
  2624. // Arguments: [ptoPrealloc] -- Preallocated proxy or NULL
  2625. // [vpvOuter16] -- controlling unknown that was passed to
  2626. // 16-bit world
  2627. // [vpvThis16] -- 16-bit interface to be proxied
  2628. // [iidx] -- Interface index or IID
  2629. // [pAggHolder] -- Proxy holder of pUnkOuter
  2630. // [pfst] -- Return value to hold the kind proxy object
  2631. //
  2632. // Returns: 32/16 proxy object or the actual 32-bit Interface
  2633. //
  2634. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2635. // proper thunking of IN/OUT interfaces
  2636. // Feb 11, 98 MPrabhu Change to use pUnkOuter's holder
  2637. //----------------------------------------------------------------------------
  2638. IUnknown *CThkMgr::FindAggregate3216(THUNK3216OBJ *ptoPrealloc, VPVOID vpvOuter16,
  2639. VPVOID vpvThis16, IIDIDX iidx, PROXYHOLDER *pAggHolder, DWORD *pfst)
  2640. {
  2641. thkDebugOut((DEB_THUNKMGR, "%sIn FindAggregate3216(%p, %p, %p, %s)\n",
  2642. NestingLevelString(), ptoPrealloc, vpvOuter16, vpvThis16,
  2643. IidIdxString(iidx)));
  2644. DebugIncrementNestingLevel();
  2645. // Local variables
  2646. THUNK1632OBJ UNALIGNED *p1632ProxyOuter;
  2647. THUNK3216OBJ *p3216ProxyOuter;
  2648. PROXYHOLDER *pph;
  2649. IUnknown *pUnk = NULL;
  2650. DWORD fstPrx = FST_ERROR;
  2651. // Validation checks
  2652. thkAssert(vpvThis16 != NULL && vpvOuter16 != NULL);
  2653. // Obtain the identity holder
  2654. // Check if the outer IUnknown is a 32-bit interface
  2655. #if DBG == 1
  2656. if(IsProxy1632(vpvOuter16)) {
  2657. // The outer IUnknown is a 32-bit interface
  2658. p1632ProxyOuter = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
  2659. pph = p1632ProxyOuter->pphHolder;
  2660. thkAssert(pph == pAggHolder);
  2661. // Ensure that the holder is marked PH_AGGREGATEE
  2662. thkAssert(pph);
  2663. thkAssert(pph->dwFlags & PH_AGGREGATEE);
  2664. RELVDMPTR(vpvOuter16);
  2665. }
  2666. #endif
  2667. // Aggregation through delegation.
  2668. pph = pAggHolder;
  2669. // Find/Generate the proxy for the given 16-bit interface
  2670. pUnk = FindProxy3216(ptoPrealloc, vpvThis16, pph, iidx, FALSE, &fstPrx);
  2671. // Initialize the return value
  2672. if(pfst)
  2673. *pfst = fstPrx;
  2674. DebugDecrementNestingLevel();
  2675. thkDebugOut((DEB_THUNKMGR, "%sOut FindAggregate3216,(%p)->%p\n",
  2676. NestingLevelString(), vpvThis16, pUnk));
  2677. // This may be a proxy or a real 32-bit interface
  2678. return(pUnk);
  2679. }
  2680. //+---------------------------------------------------------------------------
  2681. //
  2682. // Method: CThkMgr::FindAggregate1632
  2683. //
  2684. // Synopsis: Finds/Generates a 16/32 proxy for a given 32-bit interface
  2685. // that is aggregated with the given outer unknown.
  2686. // If the given 32-bit interface itself is a proxy, returns
  2687. // the actual 16-bit Interface
  2688. //
  2689. // Arguments: [ptoPrealloc] -- Preallocated proxy or NULL
  2690. // [punkOuter32] -- controlling unknown that was passed to
  2691. // 32-bit world
  2692. // [punkThis32] -- 16-bit interface to be proxied
  2693. // [iidx] -- Interface index or IID
  2694. // [pAggHolder] -- Proxy holder of pUnkOuter
  2695. // [pfst] -- Return value to hold the kind proxy object
  2696. //
  2697. // Returns: 32/16 proxy object or the actual 32-bit Interface
  2698. //
  2699. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2700. // proper thunking of IN/OUT interfaces
  2701. // Feb 11, 98 MPrabhu Change to use pUnkOuter's holder
  2702. //----------------------------------------------------------------------------
  2703. VPVOID CThkMgr::FindAggregate1632(VPVOID vpvPrealloc, IUnknown *punkOuter32,
  2704. IUnknown *punkThis32, IIDIDX iidx, PROXYHOLDER *pAggHolder, DWORD *pfst)
  2705. {
  2706. thkDebugOut((DEB_THUNKMGR, "%sIn FindAggregate1632(%p, %p, %p, %s)\n",
  2707. NestingLevelString(), vpvPrealloc, punkOuter32, punkThis32,
  2708. IidIdxString(iidx)));
  2709. DebugIncrementNestingLevel();
  2710. // Local variables
  2711. THUNK1632OBJ UNALIGNED *p1632ProxyOuter;
  2712. THUNK3216OBJ *p3216ProxyOuter;
  2713. PROXYHOLDER *pph;
  2714. VPVOID vpvProxy = NULL;
  2715. DWORD fstPrx = FST_ERROR;
  2716. // Validation checks
  2717. thkAssert(punkThis32 != NULL && punkOuter32 != NULL);
  2718. // Obtain the identity holder
  2719. // Check if the outer IUnknown is a 16-bit interface
  2720. #if DBG == 1
  2721. if(IsProxy3216(punkOuter32)) {
  2722. // The outer IUnknown is a 16-bit interface
  2723. p3216ProxyOuter = (THUNK3216OBJ *) punkOuter32;
  2724. pph = p3216ProxyOuter->pphHolder;
  2725. thkAssert(pph == pAggHolder);
  2726. // Ensure that the holder is marked PH_AGGREGATEE
  2727. thkAssert(pph);
  2728. thkAssert(pph->dwFlags & PH_AGGREGATEE);
  2729. }
  2730. #endif
  2731. // Aggregation through delegation.
  2732. // The outer IUnknown must be a 32-bit interface
  2733. pph = pAggHolder;
  2734. // Find/Generate the proxy for the given 32-bit interface
  2735. vpvProxy = FindProxy1632(vpvPrealloc, punkThis32, pph, iidx, &fstPrx);
  2736. // Initialize the return value
  2737. if(pfst)
  2738. *pfst = fstPrx;
  2739. DebugDecrementNestingLevel();
  2740. thkDebugOut((DEB_THUNKMGR, "%sOut FindAggregate1632,(%p)->%p\n",
  2741. NestingLevelString(), punkThis32, vpvProxy));
  2742. // This may be a proxy or a real 16-bit interface
  2743. return(vpvProxy);
  2744. }
  2745. //+---------------------------------------------------------------------------
  2746. //
  2747. // Method: CThkMgr::QueryInterfaceProxy3216
  2748. //
  2749. // Synopsis: QueryInterface on the given proxy
  2750. //
  2751. // Arguments: [ptoThis] -- Proxy to a 16-bit interface
  2752. // [refiid] -- Interface IID
  2753. // [ppv] -- Place where the new interface is returned
  2754. //
  2755. // Returns: HRESULT
  2756. //
  2757. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2758. // proper thunking of IN/OUT interfaces
  2759. //----------------------------------------------------------------------------
  2760. SCODE CThkMgr::QueryInterfaceProxy3216(THUNK3216OBJ *ptoThis, REFIID refiid,
  2761. LPVOID *ppv)
  2762. {
  2763. thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy3216(%p)\n",
  2764. NestingLevelString(), ptoThis));
  2765. DebugIncrementNestingLevel();
  2766. // Local variables
  2767. SCODE scRet = S_OK;
  2768. IUnknown *punkProxy;
  2769. PROXYHOLDER *pph;
  2770. VPVOID vpvUnk;
  2771. DWORD fst;
  2772. // Validation checks
  2773. DebugValidateProxy3216(ptoThis);
  2774. // Initialize the return value
  2775. *ppv = NULL;
  2776. // Convert interface IID to an IIDIDX
  2777. IIDIDX iidx = IidToIidIdx(refiid);
  2778. // Check if a custom interface has been requested
  2779. if(IIDIDX_IS_IID(iidx)) {
  2780. thkDebugOut((DEB_THUNKMGR, "%sQueryInterfaceProxy3216: unknown iid %s\n",
  2781. NestingLevelString(), IidIdxString(iidx)));
  2782. // Add the request for the unknown interface
  2783. if(!AddIIDRequest(refiid))
  2784. return E_OUTOFMEMORY;
  2785. }
  2786. thkAssert(ptoThis->vpvThis16);
  2787. // Ensure that the aggregatee identity gets correctly established
  2788. if(ptoThis->grfFlags & PROXYFLAG_PUNKOUTER && iidx == THI_IUnknown) {
  2789. // QI by the aggregatee for identity
  2790. thkAssert(ptoThis->pphHolder->unkProxy.dwPtrVal == (DWORD) ptoThis);
  2791. // AddRef and return outer proxy
  2792. AddRefProxy3216(ptoThis);
  2793. *ppv = (void *) ptoThis;
  2794. }
  2795. else {
  2796. // Execute the QI on the 16-bit interface
  2797. scRet = QueryInterfaceOnObj16(ptoThis->vpvThis16, refiid, (void **)&vpvUnk);
  2798. if(SUCCEEDED(scRet)) {
  2799. if(vpvUnk) {
  2800. // Obtain the identity holder
  2801. pph = ptoThis->pphHolder;
  2802. // Check if this is a QI on an interface on the aggregatee
  2803. if(pph->dwFlags & PH_AGGREGATEE) {
  2804. if(ptoThis->grfFlags & PROXYFLAG_PIFACE) {
  2805. // QI on an interface on the aggregatee which
  2806. // delegates to the aggregator
  2807. // Note the above QI call can be short circuited as
  2808. // an optimization. It will be carried out in future
  2809. // after ensuring that apps do not break due to such
  2810. // short circuiting
  2811. thkAssert(pph->unkProxy.wType == PPRX_16);
  2812. }
  2813. else if(ptoThis->grfFlags & PROXYFLAG_PUNKOUTER) {
  2814. // QI by the aggregatee on aggregator
  2815. thkAssert(pph->unkProxy.dwPtrVal == (DWORD) ptoThis);
  2816. }
  2817. else {
  2818. // QI by the aggregator on the aggregatee
  2819. thkAssert(ptoThis->grfFlags & PROXYFLAG_PUNKINNER);
  2820. thkAssert(pph->unkProxy.wType == PPRX_16);
  2821. }
  2822. // As aggregation is involved, we cannot be certain of
  2823. // identity of the returned interface
  2824. pph = NULL;
  2825. }
  2826. // Set the thunk status
  2827. SetThkState(THKSTATE_INVOKETHKOUT32);
  2828. punkProxy = FindProxy3216(NULL, vpvUnk, pph, iidx, FALSE, &fst);
  2829. if(punkProxy) {
  2830. // Set the return value
  2831. *ppv = punkProxy;
  2832. #if DBG==1
  2833. if(pph) {
  2834. // Ensure that the given and new proxies either have the same
  2835. // holder or point to same identity
  2836. if(fst & FST_PROXY_STATUS) {
  2837. THUNK3216OBJ *ptoNew = (THUNK3216OBJ *) punkProxy;
  2838. thkAssert(ptoNew->pphHolder == ptoThis->pphHolder);
  2839. }
  2840. else {
  2841. THUNK1632OBJ UNALIGNED *ptoNew;
  2842. ptoNew = FIXVDMPTR(vpvUnk, THUNK1632OBJ);
  2843. thkAssert(fst == FST_SHORTCUT);
  2844. thkAssert(ptoNew->pphHolder != ptoThis->pphHolder);
  2845. thkAssert(ptoNew->pphHolder->dwFlags & PH_AGGREGATEE);
  2846. thkAssert(ptoNew->pphHolder->unkProxy.wType == PPRX_32);
  2847. RELVDMPTR(vpvUnk);
  2848. }
  2849. }
  2850. #endif
  2851. }
  2852. else {
  2853. scRet = E_OUTOFMEMORY;
  2854. }
  2855. // As the new interface is an OUT parameter, release the actual
  2856. // 16-bit interface. This would counter the AddRef made by
  2857. // a successfull FindProxy3216, else it would clean up the
  2858. // reference count
  2859. ReleaseOnObj16(vpvUnk);
  2860. // Reset thunk status
  2861. SetThkState(THKSTATE_NOCALL);
  2862. }
  2863. else {
  2864. // Corel draw returns NOERROR while setting returned interface to NULL
  2865. // We modify the returned value to suit 32-bit QI semantics.
  2866. scRet = E_NOINTERFACE;
  2867. }
  2868. }
  2869. }
  2870. if(IIDIDX_IS_IID(iidx)) {
  2871. // Clean up custom interface request
  2872. RemoveIIDRequest(refiid);
  2873. }
  2874. DebugDecrementNestingLevel();
  2875. thkDebugOut((DEB_THUNKMGR, "%sOut QueryInterfaceProxy3216(%p) => %p, 0x%08lX\n",
  2876. NestingLevelString(), ptoThis, *ppv, scRet));
  2877. return scRet;
  2878. }
  2879. //+---------------------------------------------------------------------------
  2880. //
  2881. // Method: CThkMgr::AddRefProxy3216
  2882. //
  2883. // Synopsis: addref on the given object - can addref the real object
  2884. //
  2885. // Arguments: [ptoThis] -- proxy object
  2886. //
  2887. // Returns: local refcount
  2888. //
  2889. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2890. // proper thunking of IN/OUT interfaces
  2891. //----------------------------------------------------------------------------
  2892. DWORD CThkMgr::AddRefProxy3216(THUNK3216OBJ *ptoThis)
  2893. {
  2894. thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy3216(%p)\n",
  2895. NestingLevelString(), ptoThis));
  2896. DebugIncrementNestingLevel();
  2897. // Validation checks
  2898. DebugValidateProxy3216(ptoThis);
  2899. thkAssert(ptoThis->pphHolder);
  2900. // Increment local refcount
  2901. thkAssert(ptoThis->cRefLocal >= 0);
  2902. ptoThis->cRefLocal++;
  2903. // Check for the need to AddRef the holder
  2904. if(ptoThis->cRefLocal == 1) {
  2905. // Assert that an aggregatee is not being revived
  2906. thkAssert(!(ptoThis->grfFlags & PROXYFLAG_PUNKINNER));
  2907. // AddRef the holder
  2908. AddRefHolder(ptoThis->pphHolder);
  2909. // Mark the proxy as revived
  2910. ptoThis->grfFlags |= PROXYFLAG_REVIVED;
  2911. }
  2912. // Check for the need to forward AddRef to the actual 16-bit interface
  2913. if(ptoThis->cRefLocal==1 || (ptoThis->pphHolder->dwFlags & PH_AGGREGATEE)) {
  2914. #if DBG==1
  2915. DWORD refsBefore, refsAfter;
  2916. PROXYHOLDER *pph;
  2917. THUNK1632OBJ UNALIGNED *punkOuter;
  2918. // Check if the object is an aggregatee
  2919. pph = ptoThis->pphHolder;
  2920. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  2921. // Assert that identity is in the 32-bit world
  2922. thkAssert(pph->unkProxy.wType == PPRX_16);
  2923. // Obtain the references on the outer proxy
  2924. punkOuter = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  2925. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  2926. refsBefore = punkOuter->cRefLocal;
  2927. RELVDMPTR(pph->unkProxy.dwPtrVal);
  2928. }
  2929. #endif
  2930. // Increment before calling the actual 16-bit interface
  2931. ptoThis->cRef++;
  2932. // AddRef the actual 16-bit interface
  2933. AddRefOnObj16(ptoThis->vpvThis16);
  2934. #if DBG==1
  2935. // Check if the object is an aggregatee
  2936. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  2937. // Ensure that the above AddRef translated to a AddRef on the
  2938. // outer proxy
  2939. punkOuter = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  2940. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  2941. refsAfter = punkOuter->cRefLocal;
  2942. thkAssert(refsBefore == refsAfter-1);
  2943. RELVDMPTR(pph->unkProxy.dwPtrVal);
  2944. }
  2945. #endif
  2946. }
  2947. DebugValidateProxy3216(ptoThis);
  2948. DebugDecrementNestingLevel();
  2949. thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy3216(%p),(%ld,%ld)\n",
  2950. NestingLevelString(), ptoThis, ptoThis->cRefLocal,
  2951. ptoThis->cRef));
  2952. return ptoThis->cRefLocal;
  2953. }
  2954. //+---------------------------------------------------------------------------
  2955. //
  2956. // Method: CThkMgr::ReleaseProxy3216
  2957. //
  2958. // Synopsis: release on the proxy or aggregate
  2959. //
  2960. // Arguments: [ptoThis] -- proxy object
  2961. //
  2962. // Returns: local refcount
  2963. //
  2964. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  2965. // proper thunking of IN/OUT interfaces
  2966. //----------------------------------------------------------------------------
  2967. DWORD CThkMgr::ReleaseProxy3216(THUNK3216OBJ *ptoThis)
  2968. {
  2969. thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy3216(%p)\n",
  2970. NestingLevelString(), ptoThis));
  2971. DebugIncrementNestingLevel();
  2972. // Local variables
  2973. DWORD dwLocalRefs, dwRefs;
  2974. DWORD ProxyType;
  2975. // Validation checks
  2976. DebugValidateProxy3216(ptoThis);
  2977. thkAssert(ptoThis->pphHolder);
  2978. // Check for the need to forward the release to the actual
  2979. // 16-bit interface
  2980. if(ptoThis->cRef == ptoThis->cRefLocal) {
  2981. #if DBG==1
  2982. DWORD refsBefore, refsAfter;
  2983. PROXYHOLDER *pph;
  2984. THUNK1632OBJ UNALIGNED *punkOuter;
  2985. // Check if the object is an aggregatee
  2986. pph = ptoThis->pphHolder;
  2987. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  2988. // Assert that identity is in the 32-bit world
  2989. thkAssert(pph->unkProxy.wType == PPRX_16);
  2990. // Obtain the references on the outer proxy
  2991. punkOuter = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  2992. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  2993. refsBefore = punkOuter->cRefLocal;
  2994. RELVDMPTR(pph->unkProxy.dwPtrVal);
  2995. }
  2996. #endif
  2997. // Release the actual 16-bit interface
  2998. thkAssert(ptoThis->cRef);
  2999. ReleaseOnObj16(ptoThis->vpvThis16);
  3000. // Decrement after calling the actual 16-bit interface
  3001. --ptoThis->cRef;
  3002. #if DBG==1
  3003. // Check if the object is an aggregatee
  3004. if((pph->dwFlags & PH_AGGREGATEE) && (ptoThis->grfFlags & PROXYFLAG_PIFACE)) {
  3005. // Ensure that the above release translated to a release on the
  3006. // outer proxy
  3007. punkOuter = FIXVDMPTR(pph->unkProxy.dwPtrVal, THUNK1632OBJ);
  3008. thkAssert(punkOuter->cRef == punkOuter->cRefLocal);
  3009. refsAfter = punkOuter->cRefLocal;
  3010. thkAssert(refsBefore == refsAfter+1);
  3011. RELVDMPTR(pph->unkProxy.dwPtrVal);
  3012. }
  3013. #endif
  3014. }
  3015. // Decrement the local refcount
  3016. thkAssert(ptoThis->cRefLocal > 0);
  3017. dwLocalRefs = --ptoThis->cRefLocal;
  3018. dwRefs = ptoThis->cRef;
  3019. ProxyType = ptoThis->grfFlags & PROXYFLAG_TYPE;
  3020. // Check if the proxy needs to be cleaned up
  3021. if(dwLocalRefs == 0) {
  3022. // Debug dump
  3023. thkAssert(dwRefs == 0);
  3024. DBG_DUMP(DebugDump3216());
  3025. // Release the holder. If this is the last release on
  3026. // the holder, the proxy would be destroyed. Hence,
  3027. // we should not use any member variables hereafter.
  3028. ReleaseHolder(ptoThis->pphHolder, ProxyType);
  3029. }
  3030. DebugDecrementNestingLevel();
  3031. thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy3216(%p) => %ld,%ld\n",
  3032. NestingLevelString(), ptoThis, dwLocalRefs, dwRefs));
  3033. return dwLocalRefs;
  3034. }
  3035. //+---------------------------------------------------------------------------
  3036. //
  3037. // Member: CThkMgr::RemoveProxy3216, public
  3038. //
  3039. // Synopsis: Destroys the given proxy
  3040. //
  3041. // Arguments: [pto] - Flat proxy pointer
  3042. //
  3043. // History: Mar 14,97 Gopalk Rewritten to support aggregation and
  3044. // proper thunking of IN/OUT interfaces
  3045. //----------------------------------------------------------------------------
  3046. void CThkMgr::RemoveProxy3216(THUNK3216OBJ *pto)
  3047. {
  3048. // Revoke the assosiation between the proxy and
  3049. // the 16-bit interface
  3050. if(!(pto->grfFlags & PROXYFLAG_PUNKOUTER)) {
  3051. #if DBG==1
  3052. thkAssert(_pProxyTbl3216->RemoveKey(pto->vpvThis16));
  3053. #else
  3054. _pProxyTbl3216->RemoveKey(pto->vpvThis16);
  3055. #endif
  3056. }
  3057. // Release the holder if needed
  3058. if(pto->cRefLocal > 0)
  3059. ReleaseHolder(pto->pphHolder, PROXYFLAG_NONE);
  3060. // Check if the proxy is locked
  3061. if(!(pto->grfFlags & PROXYFLAG_LOCKED)) {
  3062. #if DBG == 1
  3063. // In debug builds, mark the proxy dead
  3064. pto->dwSignature = PSIG3216DEAD;
  3065. // Return the proxy to free list
  3066. if (!fSaveProxy)
  3067. #endif
  3068. {
  3069. thkAssert(pto->pphHolder);
  3070. pto->pphHolder = NULL;
  3071. flFreeList32.FreeElement((DWORD)pto);
  3072. }
  3073. }
  3074. return;
  3075. }
  3076. //+---------------------------------------------------------------------------
  3077. //
  3078. // Member: CThkMgr::PrepareForCleanup, public
  3079. //
  3080. // Synopsis: Marks the 3216 Proxies so that OLE32 cannot call them.
  3081. //
  3082. // Arguments: -none-
  3083. //
  3084. // History: 24-Aug-94 BobDay Created
  3085. //
  3086. //----------------------------------------------------------------------------
  3087. void CThkMgr::PrepareForCleanup( void )
  3088. {
  3089. POSITION pos;
  3090. DWORD dwKey;
  3091. THUNK3216OBJ *pto3216;
  3092. //
  3093. // CODEWORK: OLE32 should be setup so that it doesn't callback while the
  3094. // thread is detaching. Then this function becomes obsolete.
  3095. //
  3096. // Check if callbacks were disabled earlier
  3097. if(AreCallbacksAllowed())
  3098. {
  3099. // Disable callbacks on this thread as the 16-bit TASK state has
  3100. // been reclaimed by NTVDM by now
  3101. DisableCallbacks();
  3102. // delete the 3216 proxy table
  3103. pos = _pProxyTbl3216->GetStartPosition();
  3104. while (pos)
  3105. {
  3106. pto3216 = NULL;
  3107. _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
  3108. if (pto3216 != NULL)
  3109. {
  3110. thkDebugOut((DEB_IWARN, "Preparing 3216 Proxy for cleanup: "
  3111. "%08lX %08lX %s\n",
  3112. pto3216,
  3113. pto3216->vpvThis16,
  3114. IidIdxString(pto3216->iidx)));
  3115. pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
  3116. }
  3117. }
  3118. }
  3119. }
  3120. #if DBG == 1
  3121. void CThkMgr::DebugDump3216()
  3122. {
  3123. THUNK3216OBJ *pto3216;
  3124. DWORD dwKey;
  3125. POSITION pos;
  3126. thkDebugOut((DEB_THUNKMGR, "%s DebugDump3216\n",NestingLevelString()));
  3127. pos = _pProxyTbl3216->GetStartPosition();
  3128. while (pos)
  3129. {
  3130. _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
  3131. thkDebugOut((DEB_THUNKMGR,
  3132. "%s Proxy3216:Key:%p->%p, (%s) (%d,%d)\n",
  3133. NestingLevelString(), dwKey, pto3216,
  3134. IidIdxString(pto3216->iidx), pto3216->cRefLocal,
  3135. pto3216->cRef));
  3136. }
  3137. }
  3138. void CThkMgr::DebugDump1632()
  3139. {
  3140. THUNK1632OBJ UNALIGNED *pto1632;
  3141. DWORD dwKey;
  3142. VPVOID vpv;
  3143. POSITION pos;
  3144. thkDebugOut((DEB_THUNKMGR, "%s DebugDump1632\n",NestingLevelString()));
  3145. pos = _pProxyTbl1632->GetStartPosition();
  3146. while (pos)
  3147. {
  3148. _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
  3149. pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
  3150. thkDebugOut((DEB_THUNKMGR,
  3151. "%s Proxy1632:key:%p->%p, (%s) (%d,%d)\n",
  3152. NestingLevelString(), dwKey, pto1632,
  3153. IidIdxString(pto1632->iidx), pto1632->cRefLocal,
  3154. pto1632->cRef));
  3155. RELVDMPTR(vpv);
  3156. }
  3157. }
  3158. #endif