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.

546 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: thkmgr.cxx
  7. //
  8. // Contents: Thunk manager initialization
  9. // IUnknown transition functions
  10. //
  11. // History: 5-18-94 JohannP (Johann Posch) Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "headers.cxx"
  15. #pragma hdrstop
  16. //+---------------------------------------------------------------------------
  17. //
  18. // Function: ThkMgrInitialize
  19. //
  20. // Synopsis: Creates a new thunkmanager and set it for given thread
  21. //
  22. // Arguments: [dw1]
  23. // [dw2]
  24. // [dw3]
  25. //
  26. // Returns: HRESULT
  27. //
  28. // History: 5-18-94 JohannP (Johann Posch) Created
  29. //
  30. // Notes: Called from CoInitialize
  31. //
  32. //----------------------------------------------------------------------------
  33. STDAPI ThkMgrInitialize(DWORD dw1, DWORD dw2, DWORD dw3)
  34. {
  35. CThkMgr *pcthkmgr = NULL;
  36. thkDebugOut((DEB_THUNKMGR, "In ThkMgrInitialize()\n"));
  37. //
  38. // If we are already initialized, do nothing.
  39. //
  40. if (TlsGetValue(dwTlsThkIndex) != NULL)
  41. {
  42. thkDebugOut((DEB_THUNKMGR, "OUT ThkMgrInitialize() Already Init\n"));
  43. return(NOERROR);
  44. }
  45. //
  46. // initialize the Tls storage
  47. //
  48. if ( NOERROR != TlsThkInitialize())
  49. {
  50. thkDebugOut((DEB_ERROR, "TlsThkInitialize failed"));
  51. return E_OUTOFMEMORY;
  52. }
  53. thkAssert(TlsThkGetThkMgr() == NULL);
  54. pcthkmgr = CThkMgr::Create();
  55. TlsThkSetThkMgr(pcthkmgr);
  56. thkDebugOut((DEB_THUNKMGR, "Out ThkMgrInitialize() => %p\n",
  57. pcthkmgr));
  58. return (pcthkmgr == NULL) ? E_OUTOFMEMORY : NOERROR;
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: ThkMgrUninitialize
  63. //
  64. // Synopsis: deletes the thunkmanager and removes it from thread data
  65. // tls data are removed as well
  66. //
  67. // Arguments: [dw1]
  68. // [dw2]
  69. // [dw3]
  70. //
  71. // History: 5-18-94 JohannP (Johann Posch) Created
  72. //
  73. // Notes: Called during CoUninitialize
  74. //
  75. //----------------------------------------------------------------------------
  76. STDAPI_(void) ThkMgrUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
  77. {
  78. thkDebugOut((DEB_THUNKMGR, "In ThkMgrUninitialize()\n"));
  79. thkAssert(TlsGetValue(dwTlsThkIndex) != NULL);
  80. CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
  81. if (pcthkmgr != NULL)
  82. {
  83. // Note: the thunkmanger gets removed from tlsthk
  84. delete pcthkmgr;
  85. }
  86. // If we weren't called from 16-bit code then it's not safe to reset
  87. // the 16-bit stack allocator here because we may be doing this
  88. // in thread cleanup and it may not be safe to call back into
  89. // 16-bit code
  90. TlsThkGetStack32()->Reset();
  91. // uninitialize the tls data for this apartment
  92. TlsThkUninitialize();
  93. thkDebugOut((DEB_THUNKMGR, "Out ThkMgrUninitialize()\n"));
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Function: IUnknownObj32
  98. //
  99. // Synopsis: Entry point from 16bit for IUnknown methods
  100. //
  101. // Arguments: [vpvThis16] -- Proxy object
  102. // [wMethod] -- IUnknown method
  103. // [vpvData] -- Call data
  104. //
  105. // Returns: Call result, pdata contains out data for particular call
  106. //
  107. // History: 5-18-94 JohannP (Johann Posch) Created
  108. //
  109. //----------------------------------------------------------------------------
  110. STDAPI_(DWORD) IUnknownObj32(VPVOID vpvThis16, DWORD wMethod, VPVOID vpvData)
  111. {
  112. DWORD dwRet;
  113. LONG vpvInterface;
  114. IID iid;
  115. if (TlsThkGetData() == NULL)
  116. {
  117. thkDebugOut((DEB_WARN, "WARNING: IUnknownObj32 call refused\n"));
  118. if (wMethod == SMI_QUERYINTERFACE)
  119. {
  120. return (DWORD)E_FAIL;
  121. }
  122. else
  123. {
  124. return 0;
  125. }
  126. }
  127. // Note: at this point we should always get a thunkmanager
  128. CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
  129. thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
  130. thkAssert(vpvThis16 != 0 && "IUnknownObj32: invalid pointer." );
  131. thkAssert(wMethod < SMI_COUNT);
  132. switch (wMethod)
  133. {
  134. case SMI_QUERYINTERFACE:
  135. thkAssert(vpvData != NULL &&
  136. "IUnknownObj32.QueryInterface without IID");
  137. // Copy the 16-bit IID into 32-bit memory for the real call
  138. iid = *FIXVDMPTR(vpvData, IID);
  139. RELVDMPTR(vpvData);
  140. thkDebugOut((DEB_UNKNOWN,
  141. "%sIn QueryInterface1632(%p, %s)\n",
  142. NestingLevelString(), vpvThis16,
  143. IidOrInterfaceString(&iid)));
  144. dwRet = pcthkmgr->QueryInterfaceProxy1632(vpvThis16, iid,
  145. (void **)&vpvInterface);
  146. // Translate the 32-bit HRESULT to a 16-bit HRESULT
  147. dwRet = (DWORD)TransformHRESULT_3216((HRESULT)dwRet);
  148. // Pass the return interface pointer back through the IID
  149. // memory. We re-resolve the data pointer since nested
  150. // calls may have occurred
  151. (FIXVDMPTR(vpvData, IID))->Data1 = vpvInterface;
  152. RELVDMPTR(vpvData);
  153. thkDebugOut((DEB_UNKNOWN,
  154. "%sOut QueryInterface1632(%p) => %p, 0x%08lX\n",
  155. NestingLevelString(), vpvThis16, vpvInterface, dwRet));
  156. break;
  157. case SMI_ADDREF:
  158. thkDebugOut((DEB_UNKNOWN, "%sIn AddRef1632(%p)\n",
  159. NestingLevelString(), vpvThis16));
  160. dwRet = pcthkmgr->AddRefProxy1632(vpvThis16);
  161. thkDebugOut((DEB_UNKNOWN, "%sOut AddRef1632(%p) => %d\n",
  162. NestingLevelString(), vpvThis16, dwRet));
  163. break;
  164. case SMI_RELEASE:
  165. thkDebugOut((DEB_UNKNOWN, "%sIn Release1632(%p)\n",
  166. NestingLevelString(), vpvThis16));
  167. dwRet = pcthkmgr->ReleaseProxy1632(vpvThis16);
  168. thkDebugOut((DEB_UNKNOWN, "%sOut Release1632(%p) => %d\n",
  169. NestingLevelString(), vpvThis16, dwRet));
  170. break;
  171. }
  172. return dwRet;
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Function: QueryInterfaceProxy3216
  177. //
  178. // Synopsis: call QueryInterface on a 32 bit proxy
  179. //
  180. // Arguments: [pto] -- This pointer (a 32->16 proxy)
  181. // [refiid] -- Interface queried for
  182. // [ppv] -- Interface return
  183. //
  184. // Returns: HRESULT
  185. //
  186. // History: 5-18-94 JohannP (Johann Posch) Created
  187. //
  188. //----------------------------------------------------------------------------
  189. SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto, REFIID refiid, LPVOID *ppv)
  190. {
  191. HRESULT hrRet;
  192. thkDebugOut((DEB_UNKNOWN, "%sIn QueryInterface3216(%p, %s)\n",
  193. NestingLevelString(), pto,
  194. IidOrInterfaceString(&refiid)));
  195. DebugIncrementNestingLevel();
  196. if (TlsThkGetData() == NULL)
  197. {
  198. thkDebugOut((DEB_WARN, "WARNING: QIProxy3216 call refused\n"));
  199. return E_FAIL;
  200. }
  201. CThkMgr *pcthkmgr = TlsThkGetThkMgr();
  202. thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
  203. if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
  204. {
  205. thkDebugOut((DEB_WARN,
  206. "QueryInterfaceProxy3216: Attempt to QI "
  207. "on cleaned-up proxy %08lX for 16-bit object %08lX %s\n",
  208. pto, pto->vpvThis16,
  209. IidIdxString(IID_IIDIDX(&refiid)) ));
  210. *ppv = NULL;
  211. return E_FAIL;
  212. }
  213. hrRet = pcthkmgr->QueryInterfaceProxy3216(pto, refiid, ppv);
  214. //
  215. // If the QI for IUnknown failed, then return the current this
  216. // pointer as the IUnknown. Watermark 1.02 appears to not support
  217. // IUnknown in its IOleInPlaceActiveObject interface, which causes
  218. // CoMarshalInterface to fail. The reason it used to work is the
  219. // original 16-bit DLL's would just use the provided pointer as
  220. // the punk if IUnknown wasn't supported. The following lines of
  221. // code emulate that behaviour.
  222. //
  223. if ((hrRet == E_NOINTERFACE) && IsEqualIID(refiid,IID_IUnknown))
  224. {
  225. thkDebugOut((DEB_UNKNOWN,
  226. "%s Object %p didn't support QI(IID_IUnknown): Faking it\n",
  227. NestingLevelString(), pto));
  228. ((IUnknown *)pto)->AddRef();
  229. *ppv = pto;
  230. hrRet = S_OK;
  231. }
  232. DebugDecrementNestingLevel();
  233. thkDebugOut((DEB_UNKNOWN,
  234. "%sOut QueryInterface3216(%p) => %p, ret:0x%08lX\n",
  235. NestingLevelString(), pto, *ppv, hrRet));
  236. return hrRet;
  237. }
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Function: AddRefProxy3216
  241. //
  242. // Synopsis: call addref on an 16 bit object
  243. //
  244. // Arguments: [pto] -- This pointer (a 32->16 proxy)
  245. //
  246. // Returns: New refcount
  247. //
  248. // History: 5-18-94 JohannP (Johann Posch) Created
  249. //
  250. //----------------------------------------------------------------------------
  251. DWORD AddRefProxy3216(THUNK3216OBJ *pto)
  252. {
  253. DWORD dwRet;
  254. thkDebugOut((DEB_UNKNOWN, "%sIn AddRef3216(%p)\n",
  255. NestingLevelString(), pto));
  256. DebugIncrementNestingLevel();
  257. if (TlsThkGetData() == NULL)
  258. {
  259. thkDebugOut((DEB_WARN, "WARNING: AddRefProxy3216 call refused\n"));
  260. return 0;
  261. }
  262. CThkMgr *pcthkmgr = TlsThkGetThkMgr();
  263. thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
  264. if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
  265. {
  266. thkDebugOut((DEB_WARN,
  267. "AddRefProxy3216: Attempt to AddRef "
  268. "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
  269. pto, pto->vpvThis16));
  270. return 0;
  271. }
  272. dwRet = pcthkmgr->AddRefProxy3216(pto);
  273. DebugDecrementNestingLevel();
  274. thkDebugOut((DEB_UNKNOWN, "%sOut AddRef3216(%p) => %ld\n",
  275. NestingLevelString(), pto, dwRet));
  276. return dwRet;
  277. }
  278. //+---------------------------------------------------------------------------
  279. //
  280. // Function: ReleaseProxy3216
  281. //
  282. // Synopsis: Release implementation for 32->16 proxies
  283. //
  284. // Arguments: [pto] -- This pointer (a 32->16 proxy)
  285. //
  286. // Returns: New refcount
  287. //
  288. // History: 5-18-94 JohannP (Johann Posch) Created
  289. //
  290. //----------------------------------------------------------------------------
  291. DWORD ReleaseProxy3216(THUNK3216OBJ *pto)
  292. {
  293. DWORD dwRet;
  294. thkDebugOut((DEB_UNKNOWN, "%sIn Release3216(%p)\n",
  295. NestingLevelString(), pto));
  296. DebugIncrementNestingLevel();
  297. if (TlsThkGetData() == NULL)
  298. {
  299. thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy3216 call refused\n"));
  300. return 0;
  301. }
  302. CThkMgr *pcthkmgr = TlsThkGetThkMgr();
  303. thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
  304. if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
  305. {
  306. thkDebugOut((DEB_WARN,
  307. "ReleaseProxy3216: Attempt to Release "
  308. "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
  309. pto, pto->vpvThis16));
  310. return 0;
  311. }
  312. dwRet = pcthkmgr->ReleaseProxy3216(pto);
  313. DebugDecrementNestingLevel();
  314. thkDebugOut((DEB_UNKNOWN, "%sOut Release3216(%p) => %ld\n",
  315. NestingLevelString(), pto, dwRet));
  316. return dwRet;
  317. }
  318. //+---------------------------------------------------------------------------
  319. //
  320. // Function: QueryInterfaceOnObj16
  321. //
  322. // Synopsis: call QueryInterface on an 16 bit object
  323. //
  324. // Arguments: [vpvThis16] -- 16-bit this pointer
  325. // [refiid] -- IID
  326. // [ppv] -- Interface return
  327. //
  328. // Returns: HRESULT
  329. //
  330. // History: 5-18-94 JohannP (Johann Posch) Created
  331. //
  332. //----------------------------------------------------------------------------
  333. struct QIARGS
  334. {
  335. IID iid;
  336. void *pvObject;
  337. };
  338. HRESULT QueryInterfaceOnObj16(VPVOID vpvThis16, REFIID refiid, LPVOID *ppv)
  339. {
  340. HRESULT hrRet;
  341. VPVOID vpvArgs;
  342. QIARGS UNALIGNED *pqa;
  343. BYTE bArgs32[WCB16_MAX_CBARGS];
  344. thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceOnObj16(%p, %s)\n",
  345. NestingLevelString(), vpvThis16,
  346. IidOrInterfaceString(&refiid)));
  347. DebugIncrementNestingLevel();
  348. thkAssert(WCB16_MAX_CBARGS >= 3*sizeof(DWORD));
  349. thkAssert(vpvThis16 != 0 && "QueryInterfaceOnObj16: invalid pointer.");
  350. // Allocate space for the sixteen bit arguments memory
  351. vpvArgs = STACKALLOC16(sizeof(QIARGS));
  352. if (vpvArgs == 0)
  353. {
  354. return E_OUTOFMEMORY;
  355. }
  356. // Fill in the in-param memory
  357. pqa = FIXVDMPTR(vpvArgs, QIARGS);
  358. pqa->iid = refiid;
  359. // Set up the 16-bit stack in pascal order
  360. *(VPVOID *)(bArgs32+0*sizeof(VPVOID)) = vpvArgs+
  361. FIELD_OFFSET(QIARGS, pvObject);
  362. *(VPVOID *)(bArgs32+1*sizeof(VPVOID)) = vpvArgs;
  363. *(VPVOID *)(bArgs32+2*sizeof(VPVOID)) = vpvThis16;
  364. RELVDMPTR(vpvArgs);
  365. // Call to 16-bit stub
  366. if (!CallbackTo16Ex(gdata16Data.fnQueryInterface16, WCB16_PASCAL,
  367. 3*sizeof(DWORD), bArgs32, (DWORD *)&hrRet))
  368. {
  369. hrRet = E_UNEXPECTED;
  370. }
  371. // Transform the 16-bit HRESULT to a 32-bit HRESULT
  372. hrRet = TransformHRESULT_1632(hrRet);
  373. // Copy back out-param memory
  374. pqa = FIXVDMPTR(vpvArgs, QIARGS);
  375. *ppv = pqa->pvObject;
  376. RELVDMPTR(vpvArgs);
  377. STACKFREE16(vpvArgs, sizeof(QIARGS));
  378. DebugDecrementNestingLevel();
  379. thkDebugOut((DEB_THUNKMGR,
  380. "%sOut QueryInterfaceOnObj16(%p) => %p, ret:0x%08lX\n",
  381. NestingLevelString(), vpvThis16, *ppv, hrRet));
  382. return hrRet;
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Function: AddRefOnObj16
  387. //
  388. // Synopsis: calls addref on an 16 bit object
  389. //
  390. // Arguments: [vpvThis16] -- 16-bit this pointer
  391. //
  392. // Returns: New ref count
  393. //
  394. // History: 5-18-94 JohannP (Johann Posch) Created
  395. //
  396. //----------------------------------------------------------------------------
  397. #if DBG == 1
  398. DWORD AddRefOnObj16(VPVOID vpvThis16)
  399. {
  400. DWORD dwRet;
  401. thkDebugOut((DEB_THUNKMGR, "%sIn AddRefOnObj16(%p)\n",
  402. NestingLevelString(), vpvThis16));
  403. DebugIncrementNestingLevel();
  404. dwRet = CallbackTo16(gdata16Data.fnAddRef16, vpvThis16);
  405. DebugDecrementNestingLevel();
  406. thkDebugOut((DEB_THUNKMGR, "%sOut AddRefOnObj16(%p) => %ld\n",
  407. NestingLevelString(), vpvThis16, dwRet));
  408. return dwRet;
  409. }
  410. #endif
  411. //+---------------------------------------------------------------------------
  412. //
  413. // Function: ReleaseOnObj16
  414. //
  415. // Synopsis: Release a 16-bit object
  416. //
  417. // Arguments: [vpvThis16] -- 16-bit this pointer
  418. //
  419. // Returns: New ref count
  420. //
  421. // History: 5-18-94 JohannP (Johann Posch) Created
  422. //
  423. //----------------------------------------------------------------------------
  424. #if DBG == 1
  425. DWORD ReleaseOnObj16(VPVOID vpvThis16)
  426. {
  427. DWORD dwRet;
  428. thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseOnObj16(%p)\n",
  429. NestingLevelString(), vpvThis16));
  430. DebugIncrementNestingLevel();
  431. dwRet = CallbackTo16(gdata16Data.fnRelease16, vpvThis16);
  432. #if DBG==1
  433. if(dwRet==0 && TlsThkGetThkMgr()->GetThkState()==THKSTATE_VERIFY16INPARAM) {
  434. thkDebugOut((DEB_WARN, "WARINING: 16-bit 0x%x IN parameter with zero "
  435. "ref count\n", vpvThis16));
  436. if(thkInfoLevel & DEB_DBGFAIL)
  437. thkAssert(!"Wish to Debug");
  438. }
  439. #endif
  440. DebugDecrementNestingLevel();
  441. thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseOnObj16(%p) => %ld\n",
  442. NestingLevelString(), vpvThis16, dwRet));
  443. return dwRet;
  444. }
  445. #endif
  446. #if DBG == 1
  447. void DebugDump()
  448. {
  449. CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
  450. thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
  451. pcthkmgr->DebugDump3216();
  452. pcthkmgr->DebugDump1632();
  453. }
  454. #endif