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.

503 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: inv32.cxx
  7. //
  8. // Contents: Implementation of InvokeOn32
  9. //
  10. // History: 22-Feb-94 DrewB Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. STDAPI_(BOOL) IsValidInterface( void FAR* pv );
  16. #include <apilist.hxx>
  17. //+---------------------------------------------------------------------------
  18. //
  19. // Function: InvokeOn32, public
  20. //
  21. // Synopsis: Sets up the THUNKINFO and starts thunking for a 16->32 call
  22. //
  23. // Arguments: [dw1] - Ignored
  24. // [dwMethod] - Method index
  25. // [pvStack32] - 32-bit stack
  26. //
  27. // Returns: Appropriate status code
  28. //
  29. // History: 18-Dec-93 JohannP Created
  30. // 21-Feb-94 DrewB Modified
  31. // 09-Dec-94 JohannP added stack switching
  32. //
  33. // Note: On WIN95 this function get is executed on the 32 bit stack.
  34. //
  35. //----------------------------------------------------------------------------
  36. #if DBG == 1
  37. extern "C"
  38. {
  39. ULONG InvokeOn32_count = 0;
  40. ULONG InvokeOn32_break = 0;
  41. int _iInvokeOn32BreakIidx = -1;
  42. int _iInvokeOn32BreakMethod = -1;
  43. };
  44. #endif
  45. // InvokeOn32 uses a lot of local variables so allocate its locals
  46. // rather than declaring them on the stack. This saves roughly
  47. // 150 bytes of stack per call
  48. struct INVOKE32RECORD
  49. {
  50. THOP CONST *pThop;
  51. THOP CONST * CONST *ppThop;
  52. UINT uiThop;
  53. VTBLFN CONST *pvfnVtbl;
  54. VTBLFN CONST * CONST *ppvfnThis32;
  55. DWORD dwStack32[MAX_PARAMS];
  56. THUNKINFO ti;
  57. VPVOID vpvThis16;
  58. THUNK1632OBJ UNALIGNED *pto;
  59. IIDIDX iidx;
  60. ThreadData *ptd;
  61. };
  62. STDAPI_(DWORD) SSAPI(InvokeOn32)(DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
  63. {
  64. // NOTE: Do not declare local variables in this routine
  65. // except for debug builds
  66. INVOKE32RECORD *pir;
  67. DWORD dwResult;
  68. #if DBG == 1
  69. ULONG ulInvokeOn32_count = ++InvokeOn32_count;
  70. if (InvokeOn32_count == InvokeOn32_break)
  71. {
  72. DebugBreak();
  73. }
  74. thkDebugOut((DEB_ITRACE, "%sInvokeOn32(0x%08x, %p)\n",
  75. NestingLevelString(),
  76. dwMethod, pvStack16));
  77. #endif // DBG
  78. if(!TlsThkGetData())
  79. return(CO_E_NOTINITIALIZED);
  80. pir = (INVOKE32RECORD *)STACKALLOC32(sizeof(INVOKE32RECORD));
  81. if (pir == NULL)
  82. {
  83. // This error isn't guaranteed to mean anything for
  84. // this call. Not much else we can do, though
  85. return (DWORD)E_OUTOFMEMORY;
  86. }
  87. // pvStack16 is the pointer to the first parameter of the 16-bit
  88. // routine. The compiler will adjust it appropriately according
  89. // to the calling convention of the routine so for PASCAL APIs
  90. // it will be high and for CDECL methods it will be low
  91. pir->ti.s16.pbStart = (BYTE *)pvStack16;
  92. pir->ti.s16.pbCurrent = pir->ti.s16.pbStart;
  93. pir->ti.s32.pbStart = (BYTE *)pir->dwStack32;
  94. pir->ti.s32.pbCurrent = pir->ti.s32.pbStart;
  95. pir->ti.scResult = S_OK;
  96. pir->ti.fResultThunked = FALSE;
  97. if (dwMethod >= THK_API_BASE)
  98. {
  99. dwMethod -= THK_API_BASE;
  100. pir->iidx = IIDIDX_INVALID;
  101. // APIs are handled as if there were a giant interface which
  102. // contains all the APIs as methods.
  103. pir->ppThop = apthopsApiThops;
  104. pir->uiThop = THK_API_COUNT;
  105. pir->pvfnVtbl = apfnApiFunctions;
  106. // APIs are pascal so we need to move downward in memory to
  107. // get to the next parameter
  108. pir->ti.s16.iDir = -1;
  109. pir->ti.dwCallerProxy = 0;
  110. }
  111. else
  112. {
  113. // For each interface there is an array of thop strings, one for
  114. // each method. The IUnknown methods don't have thop strings so
  115. // bias the thop string pointer to account for that
  116. thkAssert(dwMethod >= SMI_COUNT);
  117. // Methods are cdecl so we need to move upwards in memory to
  118. // get to the next parameter
  119. pir->ti.s16.iDir = 1;
  120. // We need to look up the appropriate method pointer by
  121. // looking in the 32-bit object's vtable
  122. GET_STACK16(&pir->ti, pir->vpvThis16, VPVOID);
  123. thkDebugOut((DEB_INVOKES,
  124. "InvokeOn32: vpvThis16 = %08lX\n", pir->vpvThis16 ));
  125. pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
  126. if (pir->pto == NULL)
  127. {
  128. STACKFREE32(pir, sizeof(INVOKE32RECORD));
  129. return (DWORD)E_INVALIDARG;
  130. }
  131. if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
  132. {
  133. // Make sure proxy is still valid.
  134. // After PPC/Win95 we might want to look at using
  135. // a signiture for validating this rather than IsValidInterface
  136. // because it will speed this code path up.
  137. if (!IsValidInterface(pir->pto->punkThis32))
  138. {
  139. thkDebugOut((
  140. DEB_ERROR, "InvokeOn32: %p: Invalid proxied object %p\n",
  141. pir->vpvThis16, pir->pto->punkThis32));
  142. STACKFREE32(pir, sizeof(INVOKE32RECORD));
  143. RELVDMPTR(pir->vpvThis16);
  144. return (DWORD)E_INVALIDARG;
  145. }
  146. DebugValidateProxy1632(pir->vpvThis16);
  147. pir->ppvfnThis32 = (VTBLFN CONST * CONST*)pir->pto->punkThis32;
  148. }
  149. else
  150. {
  151. // Temporary proxies cannot be validated
  152. // A temporary proxy's this pointer is actually a pointer
  153. // to the real this pointer, so indirect through the this
  154. // pointer to retrieve the real this pointer
  155. pir->ppvfnThis32 = (VTBLFN CONST * CONST *)*(void **)pir->pto->punkThis32;
  156. thkAssert(pir->ppvfnThis32 != NULL);
  157. thkDebugOut((DEB_WARN, "WARNING: InvokeOn32 on temporary "
  158. "%s proxy for %p\n", IidIdxString(pir->pto->iidx),
  159. pir->ppvfnThis32));
  160. }
  161. pir->iidx = pir->pto->iidx;
  162. RELVDMPTR(pir->vpvThis16);
  163. if (pir->ppvfnThis32 == NULL)
  164. {
  165. STACKFREE32(pir, sizeof(INVOKE32RECORD));
  166. return (DWORD)E_FAIL;
  167. }
  168. pir->ti.dwCallerProxy = pir->vpvThis16;
  169. thkAssert(pir->iidx < THI_COUNT);
  170. pir->ppThop = athopiInterfaceThopis[pir->iidx].ppThops-SMI_COUNT;
  171. pir->uiThop = athopiInterfaceThopis[pir->iidx].uiSize;
  172. pir->pvfnVtbl = *pir->ppvfnThis32;
  173. // Push the 32-bit this pointer on the stack first
  174. TO_STACK32(&pir->ti, pir->ppvfnThis32, VTBLFN CONST * CONST*);
  175. }
  176. thkAssert(dwMethod < pir->uiThop);
  177. pir->pThop = pir->ppThop[dwMethod];
  178. thkAssert(pir->pThop != NULL);
  179. pir->ti.pThop = pir->pThop;
  180. pir->ti.pvfn = pir->pvfnVtbl[dwMethod];
  181. pir->ti.iidx = pir->iidx;
  182. pir->ti.dwMethod = dwMethod;
  183. pir->ptd = TlsThkGetData();
  184. if (pir->ptd == NULL)
  185. {
  186. thkDebugOut((DEB_WARN, "WARNING: InvokeOn32: Call refused\n"));
  187. STACKFREE32(pir, sizeof(INVOKE32RECORD));
  188. return (DWORD)E_FAIL;
  189. }
  190. pir->ti.pThkMgr = pir->ptd->pCThkMgr;
  191. thkAssert(pir->ti.pThkMgr != NULL);
  192. #if DBG == 1
  193. if (pir->iidx == IIDIDX_INVALID)
  194. {
  195. thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p, %s\n",
  196. NestingLevelString(), ulInvokeOn32_count,
  197. pir->ti.pvfn, apszApiNames[dwMethod]));
  198. }
  199. else
  200. {
  201. thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p:%p, %s::%s (0x%0x:0x%0x)\n",
  202. NestingLevelString(), ulInvokeOn32_count,
  203. pir->ppvfnThis32, pir->ti.pvfn,
  204. inInterfaceNames[pir->iidx].pszInterface,
  205. inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
  206. pir->iidx,
  207. dwMethod));
  208. }
  209. #endif
  210. DebugIncrementNestingLevel();
  211. // save and set the new thunk state
  212. pir->ti.pThkMgr->SetThkState(THKSTATE_INVOKETHKIN32);
  213. #if DBG == 1
  214. if ((_iInvokeOn32BreakIidx > 0 &&
  215. _iInvokeOn32BreakIidx == (int)pir->iidx) &&
  216. (_iInvokeOn32BreakMethod < 0 ||
  217. _iInvokeOn32BreakMethod == (int)dwMethod))
  218. {
  219. DebugBreak();
  220. }
  221. #endif
  222. #if DBG == 1
  223. SStackRecord sr;
  224. RecordStackState16(&sr);
  225. #endif
  226. #if DBG == 1
  227. if (fStabilizeProxies)
  228. #endif
  229. {
  230. // HACK HACK HACK
  231. // Because of changes in the way refcounting rules work between
  232. // 16 and 32-bits, we have to stabilize this pointers for
  233. // 16->32 calls. To effect this, we do a purely local AddRef
  234. //
  235. // Temporary proxies are not valid proxies so they cannot
  236. // be stabilized
  237. if (pir->iidx != IIDIDX_INVALID)
  238. {
  239. DWORD dwFlags;
  240. pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
  241. dwFlags = pir->pto->grfFlags;
  242. RELVDMPTR(pir->vpvThis16);
  243. if ((dwFlags & PROXYFLAG_TEMPORARY) == 0)
  244. {
  245. pir->ti.pThkMgr->AddRefProxy1632(pir->vpvThis16);
  246. }
  247. }
  248. }
  249. dwResult = EXECUTE_THOP1632(&pir->ti);
  250. #if DBG == 1
  251. if (fStabilizeProxies)
  252. #endif
  253. {
  254. // Remove our stabilization reference
  255. // Note that we don't really know whether the proxy is
  256. // still valid, so we're just crossing our fingers here
  257. // and hoping that things continue to work
  258. if (pir->iidx != IIDIDX_INVALID)
  259. {
  260. DWORD dwFlags;
  261. pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
  262. dwFlags = pir->pto->grfFlags;
  263. RELVDMPTR(pir->vpvThis16);
  264. if ((dwFlags & PROXYFLAG_TEMPORARY) == 0)
  265. {
  266. DebugValidateProxy1632(pir->vpvThis16);
  267. pir->ti.pThkMgr->ReleaseProxy1632(pir->vpvThis16);
  268. }
  269. }
  270. }
  271. #if DBG == 1
  272. if ( !pir->ti.fResultThunked && FAILED(dwResult) )
  273. {
  274. if (pir->iidx == IIDIDX_INVALID)
  275. {
  276. thkDebugOut((DEB_FAILURES,
  277. "InvokeOn32 probable failure %s sc = %08lX\n",
  278. apszApiNames[dwMethod],
  279. dwResult));
  280. }
  281. else
  282. {
  283. thkDebugOut((DEB_FAILURES,
  284. "InvokeOn32 probable failure %s::%s sc = %08lX\n",
  285. inInterfaceNames[pir->iidx].pszInterface,
  286. inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
  287. dwResult));
  288. }
  289. if(thkInfoLevel & DEB_DBGFAIL)
  290. thkAssert(!"Wish to Debug");
  291. }
  292. CheckStackState16(&sr);
  293. #endif
  294. pir->ti.pThkMgr->SetThkState(THKSTATE_NOCALL);
  295. DebugDecrementNestingLevel();
  296. if ( !pir->ti.fResultThunked )
  297. {
  298. dwResult = TransformHRESULT_3216( dwResult );
  299. }
  300. #if DBG == 1
  301. if (pir->iidx == IIDIDX_INVALID)
  302. {
  303. thkDebugOut((DEB_INVOKES,
  304. "%s#(%04X):InvokeOn32 on %p, %s returns 0x%08lX\n",
  305. NestingLevelString(), ulInvokeOn32_count, pir->ti.pvfn,
  306. apszApiNames[dwMethod], dwResult ));
  307. }
  308. else
  309. {
  310. thkDebugOut((DEB_INVOKES,
  311. "%s#(%04X):InvokeOn32 on %p:%p, %s::%s returns 0x%08lX\n",
  312. NestingLevelString(), ulInvokeOn32_count,
  313. pir->ppvfnThis32,
  314. pir->ti.pvfn, inInterfaceNames[pir->iidx].pszInterface,
  315. inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
  316. dwResult));
  317. }
  318. #endif
  319. STACKFREE32(pir, sizeof(INVOKE32RECORD));
  320. return dwResult;
  321. }
  322. #ifdef _CHICAGO_
  323. //+---------------------------------------------------------------------------
  324. //
  325. // Function: SSCallback16
  326. //
  327. // Synopsis: Switches to 16 bit and calls back to 16 bit.
  328. //
  329. // Arguments: [vpfn16] -- function pointer
  330. // [dwParam] -- pointer to parameter
  331. //
  332. // Returns:
  333. //
  334. // History: 12-08-94 JohannP (Johann Posch) Created
  335. //
  336. // Notes:
  337. //
  338. //----------------------------------------------------------------------------
  339. DWORD WINAPI SSCallback16(DWORD vpfn16, DWORD dwParam)
  340. {
  341. DWORD dwRet;
  342. // switch to the 16 bit stack
  343. //
  344. if (SSONBIGSTACK())
  345. {
  346. StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32->16(%p)\n",NestingLevelString(), vpfn16));
  347. dwRet = SSCall(8, SSF_SmallStack, WOWCallback16, vpfn16, dwParam);
  348. StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32<-16 done\n",NestingLevelString() ));
  349. }
  350. else
  351. {
  352. dwRet = WOWCallback16(vpfn16, dwParam);
  353. }
  354. return dwRet;
  355. }
  356. //+---------------------------------------------------------------------------
  357. //
  358. // Function: SSCallback16Ex
  359. //
  360. // Synopsis: Like SSCallback16 except can handle up 16 bytes of parametes
  361. //
  362. // Arguments: [vpfn16] -- see Callback16Ex
  363. // [dwFlags] --
  364. // [cbArgs] --
  365. // [pArgs] --
  366. // [pdwRetCode] --
  367. //
  368. // Returns:
  369. //
  370. // History: 12-08-94 JohannP (Johann Posch) Created
  371. //
  372. // Notes:
  373. //
  374. //----------------------------------------------------------------------------
  375. BOOL WINAPI SSCallback16Ex(DWORD vpfn16, DWORD dwFlags,
  376. DWORD cbArgs, PVOID pArgs, PDWORD pdwRetCode)
  377. {
  378. DWORD dwRet;
  379. // switch to the 16 bit stack
  380. //
  381. if (SSONBIGSTACK())
  382. {
  383. StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32->16 (%p)\n",NestingLevelString(), vpfn16));
  384. dwRet = SSCall(20, SSF_SmallStack, WOWCallback16Ex,vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
  385. StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32<-16 done\n",NestingLevelString() ));
  386. }
  387. else
  388. {
  389. dwRet = WOWCallback16Ex(vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
  390. }
  391. return dwRet;
  392. }
  393. //+---------------------------------------------------------------------------
  394. //
  395. // Function: InvokeOn32
  396. //
  397. // Synopsis: Switches to the 32 bit stack and calls SSAPI(InvokeOn32)
  398. //
  399. // Arguments: [dw1] -- See SSAPI(InvokeOn32)
  400. // [dwMethod] --
  401. // [pvStack16] --
  402. //
  403. // Returns:
  404. //
  405. // History: 12-08-94 JohannP (Johann Posch) Created
  406. //
  407. // Notes: Only executed under WIN95
  408. //
  409. //----------------------------------------------------------------------------
  410. STDAPI_(DWORD) InvokeOn32 (DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
  411. {
  412. DWORD dwRes;
  413. if (SSONSMALLSTACK())
  414. {
  415. StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16->32 (0x%08x, %p)\n",
  416. NestingLevelString(), dwMethod, pvStack16));
  417. dwRes = SSCall(12 ,SSF_BigStack, SSInvokeOn32, dw1, dwMethod, pvStack16);
  418. StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16<-32 done(0x%08x, %p)\n",
  419. NestingLevelString(), dwMethod, pvStack16));
  420. }
  421. else
  422. dwRes = SSInvokeOn32(dw1, dwMethod, pvStack16);
  423. return dwRes;
  424. }
  425. #endif // _CHICAGO_