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.

1034 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: apinot.cxx
  7. //
  8. // Contents: Implementation of non-API thunks
  9. //
  10. // History: 11-Mar-94 BobDay Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. #include <thunkapi.hxx>
  16. #include <wownt32.h>
  17. #include "olethk32.hxx"
  18. #include "apinot.hxx"
  19. #include "tlsthk.hxx"
  20. //
  21. // The following is a global static used by OLE32 to call back into
  22. // this DLL. There is no static data associated with the static, so
  23. // it merely defines a virtual interface that OLE32 can use.
  24. //
  25. OleThunkWOW g_thkOleThunkWOW;
  26. //
  27. // The following API is exported from WOW32.DLL. There is no global include
  28. // file that it exists in yet.
  29. //
  30. #if defined(_CHICAGO_)
  31. /* Not supported under Chicago yet. */
  32. /* But it's probably not important anymore. */
  33. #define WOWFreeMetafile(x) (0)
  34. #else
  35. extern "C" BOOL WINAPI WOWFreeMetafile( HANDLE h32 );
  36. #endif
  37. //+---------------------------------------------------------------------------
  38. //
  39. // Function: CoInitializeNot, public
  40. //
  41. // Synopsis: Thunks for the 16-bit applications call to CoInitialize
  42. //
  43. // Arguments: [lpmalloc] - Parameter from the 16-bit world
  44. //
  45. // Returns: Appropriate status code
  46. //
  47. // History: 11-Mar-94 BobDay Created
  48. //
  49. //----------------------------------------------------------------------------
  50. STDAPI_(DWORD) CoInitializeNot( LPMALLOC lpMalloc )
  51. {
  52. HRESULT hresult;
  53. hresult = CoInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
  54. return (DWORD)hresult;
  55. }
  56. //+---------------------------------------------------------------------------
  57. //
  58. // Function: OleInitializeNot, public
  59. //
  60. // Synopsis: Thunks for the 16-bit applications call to OleInitialize
  61. //
  62. // Arguments: [lpmalloc] - Parameter from the 16-bit world
  63. //
  64. // Returns: Appropriate status code
  65. //
  66. // History: 11-Mar-94 BobDay Created
  67. //
  68. //----------------------------------------------------------------------------
  69. STDAPI_(DWORD) OleInitializeNot( LPMALLOC lpMalloc )
  70. {
  71. HRESULT hresult;
  72. hresult = OleInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
  73. return (DWORD)hresult;
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Function: RegisterDelayedClassFactories
  78. //
  79. // Synopsis: This function is called to actually do the registration of
  80. // the delayed class factories.
  81. //
  82. // Effects: When the application specific 'trigger' is hit
  83. // (ie OleRegGetUserType for WordPerfect), this routine is
  84. // called to actually do all of the delayed class factory
  85. // registrations.
  86. //
  87. // Arguments: (none)
  88. //
  89. // Requires:
  90. //
  91. // Returns: nothing
  92. //
  93. // History: 4-18-95 kevinro Created
  94. //
  95. //----------------------------------------------------------------------------
  96. void RegisterDelayedClassFactories()
  97. {
  98. thkDebugOut((DEB_ITRACE,
  99. "_IN RegisterDelayedClassFactories()\n"));
  100. PThreadData pdata;
  101. IUnknown *punk;
  102. HRESULT hr;
  103. DelayedRegistrationTable *pTable = NULL;
  104. DelayRegistration *pdelayed;
  105. DWORD dwReg;
  106. int i;
  107. //
  108. // Get the thread specific data and table to determine if there are
  109. // any delayed registrations. If not, just call the real routine.
  110. //
  111. pdata = TlsThkGetData();
  112. if (pdata == NULL)
  113. {
  114. goto exitRtn;
  115. }
  116. if ((pTable = pdata->pDelayedRegs) == NULL)
  117. {
  118. goto exitRtn;
  119. }
  120. //
  121. //
  122. //
  123. for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
  124. {
  125. pdelayed = &(pTable->_Entries[i]);
  126. if((pdelayed->_punk != NULL) && (pdelayed->_dwRealKey == 0))
  127. {
  128. hr = CoRegisterClassObject(pdelayed->_clsid,
  129. pdelayed->_punk,
  130. pdelayed->_dwClsContext,
  131. pdelayed->_flags,
  132. &(pdelayed->_dwRealKey));
  133. if (FAILED(hr))
  134. {
  135. thkDebugOut((DEB_ERROR,
  136. "RegisterDelayedClassFactory gets %x\n",hr));
  137. }
  138. }
  139. }
  140. exitRtn:
  141. thkDebugOut((DEB_ITRACE,
  142. "OUT RegisterDelayedClassFactories()\n"));
  143. }
  144. //+---------------------------------------------------------------------------
  145. //
  146. // Function: CoRevokeClassObjectNot
  147. //
  148. // Synopsis: Unregisters a class object that might have been delayed
  149. //
  150. // Effects: The 16-bit API CoRevokeClassObject has been directed to this
  151. // routine. This routine will check the list of interfaces that
  152. // have been registered, and will try to determine if the key
  153. // needs to be translated.
  154. //
  155. // Arguments: [dwKey] -- Key to revoke
  156. //
  157. // History: 4-18-95 kevinro Created
  158. //
  159. // Notes:
  160. //
  161. //----------------------------------------------------------------------------
  162. HRESULT CoRevokeClassObjectNot( DWORD dwKey)
  163. {
  164. thkDebugOut((DEB_ITRACE,
  165. "_IN CoRevokeClassObjectNot(dwKey = %x)\n",
  166. dwKey));
  167. PThreadData pdata;
  168. IUnknown *punk;
  169. HRESULT hr;
  170. DelayedRegistrationTable *pTable = NULL;
  171. DWORD dwReg = ~dwKey;
  172. //
  173. // Get the thread specific data and table to determine if there are
  174. // any delayed registrations. If not, just call the real routine.
  175. //
  176. pdata = TlsThkGetData();
  177. if (pdata == NULL)
  178. {
  179. goto exitRtn;
  180. }
  181. if ((pTable = pdata->pDelayedRegs) == NULL)
  182. {
  183. goto exitRtn;
  184. }
  185. //
  186. // the 'fake' key is really the bitwise not of the index
  187. //
  188. if ( dwReg >= MAX_DELAYED_REGISTRATIONS)
  189. {
  190. goto exitRtn;
  191. }
  192. if(pTable->_Entries[dwReg]._punk != NULL)
  193. {
  194. punk = pTable->_Entries[dwReg]._punk;
  195. pTable->_Entries[dwReg]._punk = NULL;
  196. dwKey = pTable->_Entries[dwReg]._dwRealKey;
  197. pTable->_Entries[dwReg]._dwRealKey = 0;
  198. //
  199. // The class object table normally does an addref on the class factory.
  200. // We are also holding an addref on the punk. Release it.
  201. //
  202. if (punk != NULL)
  203. {
  204. punk->Release();
  205. //
  206. // If the real key is zero, then we never did actually finish
  207. // the registration. In this case, we return S_OK, because we
  208. // are faking the app out anyway. This might happen if the app
  209. // decides to shutdown for some reason without triggering the
  210. // operation that causes us to register its class objects
  211. //
  212. if (dwKey == 0)
  213. {
  214. hr = S_OK;
  215. goto exitNow;
  216. }
  217. }
  218. }
  219. exitRtn:
  220. hr = CoRevokeClassObject(dwKey);
  221. exitNow:
  222. thkDebugOut((DEB_ITRACE,"OUT CoRevokeClassObjectNot():%x\n",hr));
  223. return(hr);
  224. }
  225. //+---------------------------------------------------------------------------
  226. //
  227. // Function: CoRegisterClassObjectDelayed
  228. //
  229. // Synopsis: Delay the registration of class objects. Some applications,
  230. // such as Word Perfect 6.1, register their class objects then
  231. // do peek message operations BEFORE they are fully initialized.
  232. // This causes problems because we can call in and do
  233. // CreateInstance calls before they are ready for them. This
  234. // wonderful hack will delay the registration of class objects
  235. // until someone calls RegisterClassObjectsNow(), which is
  236. // called when we know it is safe.
  237. //
  238. // Novell knows about this hack, and promised not to change
  239. // the 16-bit code on us.
  240. //
  241. // Effects: Store all of the registration information in an array, and
  242. // return a special key value.
  243. //
  244. //
  245. // Arguments: ( Same as CoRegisterClassObject)
  246. //
  247. // Requires: The associated routine CoUnregisterClassObjectDelayed needs
  248. // to be called in the CoRevokeClassObject path to check to see
  249. // if the key being passed in is a special key. That way we
  250. // can translate the key before calling the real routine.
  251. //
  252. // The special key value is not of the key
  253. //
  254. // Returns: S_OK or E_UNEXPECTED
  255. //
  256. // History: 4-14-95 kevinro Created
  257. //
  258. // Notes:
  259. //
  260. //----------------------------------------------------------------------------
  261. HRESULT CoRegisterClassObjectDelayed( REFCLSID refclsid, LPUNKNOWN punk,
  262. DWORD dwClsContext, DWORD flags, DWORD *pdwReg)
  263. {
  264. thkDebugOut((DEB_ITRACE,"_IN CoRegisterClassObjectDelayed\n"));
  265. PThreadData pdata;
  266. int i;
  267. DelayedRegistrationTable *pTable = NULL;
  268. //
  269. // Assume this is going to fail
  270. //
  271. HRESULT hr = E_UNEXPECTED;
  272. *pdwReg = 0;
  273. pdata = TlsThkGetData();
  274. if (pdata == NULL)
  275. {
  276. goto exitRtn;
  277. }
  278. if ((pTable = pdata->pDelayedRegs) == NULL)
  279. {
  280. pTable = pdata->pDelayedRegs = new DelayedRegistrationTable();
  281. }
  282. if (pTable != NULL)
  283. {
  284. for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
  285. {
  286. if(pTable->_Entries[i]._punk == NULL)
  287. {
  288. pTable->_Entries[i]._punk = punk;
  289. pTable->_Entries[i]._clsid = refclsid;
  290. pTable->_Entries[i]._dwClsContext = dwClsContext;
  291. pTable->_Entries[i]._flags = flags;
  292. //
  293. // The class object table normally does an
  294. // addref on the class factory. We will hang on to this
  295. // to keep the class factory and the 3216 proxy alive
  296. //
  297. punk->AddRef();
  298. *pdwReg = ~i;
  299. hr = S_OK;
  300. break;
  301. }
  302. }
  303. }
  304. exitRtn:
  305. thkDebugOut((DEB_ITRACE,"OUT CoRegisterClassObjectDelayed() : %x\n",hr));
  306. return(hr);
  307. }
  308. //+---------------------------------------------------------------------------
  309. //
  310. // Function: CoRegisterClassObjectNot, public
  311. //
  312. // Synopsis: Thunks for the 16-bit applications call CoRegisterClassObject
  313. // Here we check for the registered class objects to set the
  314. // thread's compatability bits.
  315. //
  316. // Arguments: [refclsid] - CLSID for the class to register
  317. // [punk] - ClassFactory interface
  318. // [dwClsContext] - Class context
  319. // [flags] - flags
  320. // [lpdwreg] - register
  321. //
  322. // Returns: Appropriate status code
  323. //
  324. // History: 18-Jul-94 BobDay Created
  325. //
  326. //----------------------------------------------------------------------------
  327. EXTERN_C const CLSID CDECL CLSID_EXCEL5_WORKSHEET =
  328. { 0x020810, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
  329. EXTERN_C const CLSID CDECL CLSID_WORD6_DOCUMENT =
  330. { 0x020900, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
  331. EXTERN_C const CLSID CDECL CLSID_WPWIN61 =
  332. { 0x89FE3FE3, 0x9FF6, 0x101B, {0xB6, 0x78, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02}};
  333. EXTERN_C const CLSID CDECL CLSID_WPWIN61_FILE =
  334. { 0x1395F281, 0x4326, 0x101b, {0x8B, 0x9A, 0xCE, 0x29, 0x3E, 0xF3, 0x84, 0x49}};
  335. EXTERN_C const CLSID CDECL CLSID_IKITARO_130 =
  336. { 0x02B501, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
  337. DEFINE_OLEGUID(CLSID_EXCEL5_WORKSHEET, 0x20810, 0, 0);
  338. STDAPI_(DWORD) CoRegisterClassObjectNot( REFCLSID refclsid, LPUNKNOWN punk,
  339. DWORD dwClsContext, DWORD flags,
  340. LPDWORD lpdwreg )
  341. {
  342. //
  343. // Excel didn't AddRef the IOleObjectClientSite returned from
  344. // the IOleObject::GetClientSite method.
  345. //
  346. if ( IsEqualCLSID(refclsid,CLSID_EXCEL5_WORKSHEET) )
  347. {
  348. DWORD dw;
  349. dw = TlsThkGetAppCompatFlags();
  350. TlsThkSetAppCompatFlags(dw | OACF_CLIENTSITE_REF);
  351. thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_CLIENTSITE_REF enabled\n"));
  352. }
  353. //
  354. // WinWord didn't call OleSetMenuDescriptor(NULL) during
  355. // IOleInPlaceFrame::RemoveMenus. We do it for them.
  356. //
  357. // Also WinWord thinks GDI objects like palettes and bitmaps can be
  358. // transferred on HGLOBALs during GetData calls. In order to thunk
  359. // them properly, we need to patch up the STGMEDIUMS given to use
  360. // by word. This is controlled by OACF_USEGDI.
  361. //
  362. // YAWC: Word chokes and dies because it fails to disconnect some of its
  363. // objects. During shutdown of a link, for example, cleaning up the stdid
  364. // table causes WORD to fault.
  365. //
  366. else if ( IsEqualCLSID(refclsid,CLSID_WORD6_DOCUMENT) )
  367. {
  368. DWORD dw;
  369. dw = TlsThkGetAppCompatFlags();
  370. TlsThkSetAppCompatFlags(dw | OACF_RESETMENU | OACF_USEGDI | OACF_NO_UNINIT_CLEANUP);
  371. thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_RESETMENU enabled\n"));
  372. thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_USEGDI enabled\n"));
  373. thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_NO_UNINIT_CLEANUP enabled\n"));
  374. }
  375. else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61) )
  376. {
  377. thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
  378. thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61)\n"));
  379. return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
  380. }
  381. else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61_FILE) )
  382. {
  383. thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
  384. thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61_FILE)\n"));
  385. return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
  386. }
  387. else if ( IsEqualCLSID(refclsid,CLSID_IKITARO_130) )
  388. {
  389. // Note: Ikitaro queries for IViewObject and uses it as IViewObject2
  390. DWORD dw = TlsThkGetAppCompatFlags();
  391. thkDebugOut((DEB_WARN,"Ikitaro hack triggered\n"));
  392. TlsThkSetAppCompatFlags(dw | OACF_IVIEWOBJECT2);
  393. }
  394. return (DWORD)CoRegisterClassObject( refclsid, punk, dwClsContext,
  395. flags, lpdwreg );
  396. }
  397. //+---------------------------------------------------------------------------
  398. //
  399. // Function: OleRegGetUserTypeNot
  400. //
  401. // Synopsis: Adds a hook for a WordPerfect hack. Check out the functions
  402. // CoRegisterClassObjectDelayed and
  403. // RegisterDelayedClassFactories for details. In essence, when
  404. // this function is called for the WPWIN61 classID, we know
  405. // that it is safe to register all of the delayed class objects.
  406. // This determination was done by debugging Wordperfect. When
  407. // they call this API, then are actually done initializing the
  408. // internals of their app.
  409. //
  410. // Effects:
  411. //
  412. // History: 4-18-95 kevinro Created
  413. //
  414. // Notes:
  415. //
  416. //----------------------------------------------------------------------------
  417. STDAPI_(DWORD)
  418. OleRegGetUserTypeNot(REFCLSID clsid,DWORD dwFormOfType,LPOLESTR *pszUserType)
  419. {
  420. //
  421. // Wordperfect has a bug. When they call OleRegGetUserType for their
  422. // classid, we know that it is safe to register their class objects for
  423. // real.
  424. //
  425. // See CoRegisterClassObjectDelayed for details
  426. //
  427. if ( IsEqualCLSID(clsid,CLSID_WPWIN61) )
  428. {
  429. thkDebugOut((DEB_WARN,"Registering WordPerfects class objects\n"));
  430. RegisterDelayedClassFactories();
  431. }
  432. return OleRegGetUserType(clsid,dwFormOfType,pszUserType);
  433. }
  434. //+---------------------------------------------------------------------------
  435. //
  436. // Member: OleThunkWOW::LoadProcDll, public
  437. //
  438. // Synopsis: Callback function for 32-bit OLE to load a 16-bit DLL
  439. //
  440. // Arguments: [pszDllName] - Name of 16-bit DLL
  441. // [lpvpfnGetClassObject] - returned 16:16 address of
  442. // "DllGetClassObject"
  443. // [lpvpfnCanUnloadNow] - returned 16:16 address of
  444. // "DllCanUnloadNow"
  445. // [lpvhmodule] - returned 16-bit hmodule
  446. //
  447. // Returns: Appropriate status code
  448. //
  449. // History: 11-Mar-94 BobDay Created
  450. //
  451. //----------------------------------------------------------------------------
  452. STDMETHODIMP
  453. OleThunkWOW::LoadProcDll(
  454. LPCTSTR pszDllName,
  455. LPDWORD lpvpfnGetClassObject,
  456. LPDWORD lpvpfnCanUnloadNow,
  457. LPDWORD lpvhmodule
  458. )
  459. {
  460. HRESULT hr;
  461. UINT uiSize;
  462. VPSTR vpstr16;
  463. VPVOID vplpds16;
  464. LOADPROCDLLSTRUCT UNALIGNED *lplpds16;
  465. char string[256];
  466. // Ensure that Interop is enabled
  467. Win4Assert(gfIteropEnabled);
  468. // Ensure that callbacks are allowed on this thread
  469. Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
  470. uiSize = lstrlen(pszDllName) + 1;
  471. vpstr16 = STACKALLOC16(uiSize*sizeof(TCHAR));
  472. if (vpstr16 == 0)
  473. {
  474. hr = E_OUTOFMEMORY;
  475. goto Exit;
  476. }
  477. #ifndef _CHICAGO_
  478. hr = Convert_LPOLESTR_to_VPSTR(pszDllName, vpstr16,
  479. uiSize, uiSize*sizeof(TCHAR));
  480. #else
  481. hr = Convert_LPSTR_to_VPSTR(pszDllName, vpstr16,
  482. uiSize, uiSize*sizeof(TCHAR));
  483. #endif
  484. if (FAILED(hr))
  485. {
  486. goto EH_vpstr16;
  487. }
  488. vplpds16 = STACKALLOC16(sizeof(LOADPROCDLLSTRUCT));
  489. if (vplpds16 == 0)
  490. {
  491. hr = E_OUTOFMEMORY;
  492. goto EH_vpstr16;
  493. }
  494. lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
  495. lplpds16->vpDllName = vpstr16;
  496. lplpds16->vpfnGetClassObject = 0;
  497. lplpds16->vpfnCanUnloadNow = 0;
  498. lplpds16->vhmodule = 0;
  499. RELVDMPTR(vplpds16);
  500. hr = CallbackTo16( gdata16Data.fnLoadProcDll, vplpds16 );
  501. if (SUCCEEDED(hr))
  502. {
  503. lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
  504. *lpvpfnGetClassObject = lplpds16->vpfnGetClassObject;
  505. *lpvpfnCanUnloadNow = lplpds16->vpfnCanUnloadNow;
  506. *lpvhmodule = lplpds16->vhmodule;
  507. RELVDMPTR(vplpds16);
  508. #ifdef _CHICAGO_
  509. thkDebugOut((DEB_WARN, "Loaded COM DLL: %s with HMODULE: 0x%x\n",
  510. pszDllName, *lpvhmodule));
  511. #else
  512. thkDebugOut((DEB_WARN, "Loaded COM DLL: %ws with HMODULE: 0x%x\n",
  513. pszDllName, *lpvhmodule));
  514. #endif
  515. }
  516. else
  517. {
  518. hr = CO_E_DLLNOTFOUND;
  519. }
  520. STACKFREE16(vplpds16, sizeof(LOADPROCDLLSTRUCT));
  521. EH_vpstr16:
  522. STACKFREE16(vpstr16,uiSize*sizeof(TCHAR));
  523. Exit:
  524. return hr;
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: OleThunkWOW::UnloadProcDll, public
  529. //
  530. // Synopsis: Callback function for 32-bit OLE to unload a 16-bit DLL
  531. //
  532. // Arguments: [vhmodule] - 16-bit hmodule
  533. //
  534. // Returns: Appropriate status code
  535. //
  536. // History: 11-Mar-94 BobDay Created
  537. //
  538. //----------------------------------------------------------------------------
  539. STDMETHODIMP
  540. OleThunkWOW::UnloadProcDll(
  541. HMODULE vhmodule
  542. )
  543. {
  544. HRESULT hr = S_OK;
  545. // Ensure that Interop is enabled and callbacks are
  546. // not allowed on this thread
  547. if(gfIteropEnabled && TlsThkGetThkMgr()->AreCallbacksAllowed())
  548. hr = CallbackTo16(gdata16Data.fnUnloadProcDll, HandleToUlong(vhmodule));
  549. return(hr);
  550. }
  551. //+---------------------------------------------------------------------------
  552. //
  553. // Member: OleThunkWOW::CallGetClassObject, public
  554. //
  555. // Synopsis: Callback function for 32-bit OLE to call 16-bit
  556. // DllGetClassObject
  557. //
  558. // Arguments: [vpfnGetClassObject] - 16:16 address of DllGetClassObject
  559. // [rclsid] - CLSID of object
  560. // [riid] - IID of interface on object
  561. // [ppv] - returned object interface
  562. //
  563. // Returns: Appropriate status code
  564. //
  565. // History: 11-Mar-94 BobDay Created
  566. //
  567. //----------------------------------------------------------------------------
  568. STDMETHODIMP
  569. OleThunkWOW::CallGetClassObject(
  570. DWORD vpfnGetClassObject,
  571. REFCLSID rclsid,
  572. REFIID riid,
  573. LPVOID FAR *ppv
  574. )
  575. {
  576. DWORD dwResult;
  577. VPVOID vpcgcos16;
  578. CALLGETCLASSOBJECTSTRUCT UNALIGNED *lpcgcos16;
  579. VPVOID iface16;
  580. IIDIDX iidx;
  581. IUnknown *punkThis32;
  582. CThkMgr *pThkMgr;
  583. ThreadData *ptd;
  584. // Ensure that Interop is enabled
  585. Win4Assert(gfIteropEnabled);
  586. // Ensure that callbacks are allowed on this thread
  587. Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
  588. ptd = TlsThkGetData();
  589. if (ptd == NULL)
  590. {
  591. thkDebugOut((DEB_WARN, "WARNING: CallGetClassObject refused\n"));
  592. dwResult = (DWORD)E_FAIL;
  593. goto Exit;
  594. }
  595. pThkMgr = ptd->pCThkMgr;
  596. vpcgcos16 = STACKALLOC16(sizeof(CALLGETCLASSOBJECTSTRUCT));
  597. if (vpcgcos16 == 0)
  598. {
  599. dwResult = (DWORD)E_OUTOFMEMORY;
  600. goto Exit;
  601. }
  602. lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
  603. lpcgcos16->vpfnGetClassObject = vpfnGetClassObject;
  604. lpcgcos16->clsid = rclsid;
  605. lpcgcos16->iid = riid;
  606. lpcgcos16->iface = 0;
  607. RELVDMPTR(vpcgcos16);
  608. dwResult = CallbackTo16( gdata16Data.fnCallGetClassObject, vpcgcos16 );
  609. if ( SUCCEEDED(dwResult) )
  610. {
  611. lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
  612. iface16 = lpcgcos16->iface;
  613. iidx = IidToIidIdx(riid);
  614. // We're on the way out creating a proxy so set the state
  615. // appropriately
  616. pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
  617. // Get a 32-bit proxy object for the 16-bit object
  618. punkThis32 = pThkMgr->FindProxy3216(NULL, iface16, NULL, iidx, FALSE, NULL);
  619. pThkMgr->SetThkState(THKSTATE_NOCALL);
  620. // Set the out param
  621. *(IUnknown **)ppv = punkThis32;
  622. // As this is an OUT parameter, release the actual 16-bit interface
  623. // This could be the last release on the 16-bit interface, if the
  624. // proxy was not successfully created
  625. ReleaseOnObj16(iface16);
  626. if(punkThis32 == NULL) {
  627. dwResult = (DWORD)E_OUTOFMEMORY;
  628. }
  629. RELVDMPTR(vpcgcos16);
  630. }
  631. else { // need to map dwResult only for failure cases (see hmMappings)
  632. dwResult = TransformHRESULT_1632( dwResult );
  633. }
  634. STACKFREE16(vpcgcos16, sizeof(CALLGETCLASSOBJECTSTRUCT));
  635. Exit:
  636. return dwResult;
  637. }
  638. //+---------------------------------------------------------------------------
  639. //
  640. // Member: OleThunkWOW::CallCanUnloadNow, public
  641. //
  642. // Synopsis: Callback function for 32-bit OLE to call 16-bit
  643. // CanUnloadNow
  644. //
  645. // Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow
  646. //
  647. // Returns: Appropriate status code
  648. //
  649. // History: 11-Mar-94 BobDay Created
  650. //
  651. //----------------------------------------------------------------------------
  652. STDMETHODIMP OleThunkWOW::CallCanUnloadNow(
  653. DWORD vpfnCanUnloadNow)
  654. {
  655. HRESULT hr = S_OK;
  656. // Ensure that Interop is enabled and callbacks are
  657. // not allowed on this thread
  658. if(gfIteropEnabled && TlsThkGetThkMgr()->AreCallbacksAllowed())
  659. hr = CallbackTo16(gdata16Data.fnCallCanUnloadNow, vpfnCanUnloadNow);
  660. return(hr);
  661. }
  662. //+---------------------------------------------------------------------------
  663. //
  664. // Member: OleThunkWOW::GetThunkManager, public
  665. //
  666. // Synopsis: Callback function for 32-bit OLE to retrieve the thunkmanager
  667. //
  668. // Arguments: [ppThkMgr] - Thunk manager return
  669. //
  670. // Returns: Appropriate status code
  671. //
  672. // History: 11-May-94 JohannP Created
  673. //
  674. //----------------------------------------------------------------------------
  675. STDMETHODIMP OleThunkWOW::GetThunkManager(IThunkManager **ppThkMgr)
  676. {
  677. thkDebugOut((DEB_THUNKMGR, "%sIn OleThunkWOW::GetThunkManager\n",
  678. NestingLevelString()));
  679. thkAssert(ppThkMgr != NULL);
  680. IUnknown *pUnk = TlsThkGetThkMgr();
  681. thkAssert(pUnk && "Invalid Thunkmanager");
  682. *ppThkMgr = (IThunkManager *)pUnk;
  683. pUnk->AddRef();
  684. thkDebugOut((DEB_THUNKMGR, "%sOut OleThunkWOW::GetThunkManager: (%p)\n",
  685. NestingLevelString(), pUnk));
  686. return NOERROR;
  687. }
  688. //+---------------------------------------------------------------------------
  689. //
  690. // Member: OleThunkWOW::WinExec16, public
  691. //
  692. // Synopsis: Callback function for 32-bit OLE to run an application
  693. //
  694. // Arguments: [pszCommandLine] - command line for WinExec
  695. // [usShow] - fShow for WinExec
  696. //
  697. // Returns: Appropriate status code
  698. //
  699. // History: 27-Jul-94 AlexT Created
  700. //
  701. //----------------------------------------------------------------------------
  702. STDMETHODIMP OleThunkWOW::WinExec16(
  703. LPCOLESTR pszCommandLine,
  704. USHORT usShow
  705. )
  706. {
  707. HRESULT hr;
  708. UINT uiSize;
  709. VPSTR vpstr16;
  710. VPVOID vplpds16;
  711. WINEXEC16STRUCT UNALIGNED *lpwes16;
  712. ULONG ulRet;
  713. // Ensure that Interop is enabled
  714. Win4Assert(gfIteropEnabled);
  715. // Ensure that callbacks are allowed on this thread
  716. Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
  717. uiSize = lstrlenW(pszCommandLine) + 1;
  718. vpstr16 = STACKALLOC16(uiSize*2);
  719. if (vpstr16 == 0)
  720. {
  721. hr = E_OUTOFMEMORY;
  722. goto Exit;
  723. }
  724. hr = Convert_LPOLESTR_to_VPSTR(pszCommandLine, vpstr16,
  725. uiSize, uiSize*2);
  726. if (FAILED(hr))
  727. {
  728. goto EH_vpstr16;
  729. }
  730. vplpds16 = STACKALLOC16(sizeof(WINEXEC16STRUCT));
  731. if (vplpds16 == 0)
  732. {
  733. hr = E_OUTOFMEMORY;
  734. goto EH_vpstr16;
  735. }
  736. lpwes16 = FIXVDMPTR(vplpds16, WINEXEC16STRUCT);
  737. lpwes16->vpCommandLine = vpstr16;
  738. lpwes16->vusShow = usShow;
  739. RELVDMPTR(vplpds16);
  740. ulRet = CallbackTo16( gdata16Data.fnWinExec16, vplpds16 );
  741. thkDebugOut((DEB_ITRACE,
  742. "CallbackTo16(WinExec16) returned %ld\n", ulRet));
  743. // According to the Windows spec, return values greater than 31 indicate
  744. // success.
  745. if (ulRet > 31)
  746. {
  747. hr = S_OK;
  748. }
  749. else if (0 == ulRet)
  750. {
  751. // 0 indicates lack of some kind of resource
  752. hr = E_OUTOFMEMORY;
  753. }
  754. else
  755. {
  756. hr = HRESULT_FROM_WIN32(ulRet);
  757. }
  758. STACKFREE16(vplpds16, sizeof(WINEXEC16STRUCT));
  759. EH_vpstr16:
  760. STACKFREE16(vpstr16, uiSize*2);
  761. Exit:
  762. return hr;
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // Method: OleThunkWOW::ConvertHwndToFullHwnd
  767. //
  768. // Synopsis: Converts a 16 bit HWND into a 32-bit HWND
  769. //
  770. // Effects: Since OLE32 doesn't directly link to WOW, this function allows
  771. // the DDE layer to access the routine that maps 16 bit HWND to
  772. // full 32-bit HWND's.
  773. //
  774. // Arguments: [hwnd] -- HWND to convert
  775. //
  776. // History: 8-03-94 kevinro Created
  777. //
  778. // Notes:
  779. //
  780. //----------------------------------------------------------------------------
  781. STDMETHODIMP_(HWND) OleThunkWOW::ConvertHwndToFullHwnd(HWND hwnd)
  782. {
  783. return(FULLHWND_32((USHORT)hwnd));
  784. }
  785. //+---------------------------------------------------------------------------
  786. //
  787. // Method: OleThunkWOW::FreeMetaFile
  788. //
  789. // Synopsis: Calls wow to delete a metafile that has memory reserved in
  790. // the 16 bit address space
  791. //
  792. // Effects: Since OLE32 doesn't directly link to WOW, this function allows
  793. // the DDE layer to access the routine in WOW
  794. //
  795. // Arguments: [hmf] -- HANDLE to delete
  796. //
  797. // History: 8-03-94 kevinro Created
  798. //
  799. // Notes:
  800. //
  801. //----------------------------------------------------------------------------
  802. STDMETHODIMP_(BOOL) OleThunkWOW::FreeMetaFile(HANDLE hmf)
  803. {
  804. return(WOWFreeMetafile(hmf));
  805. }
  806. //+---------------------------------------------------------------------------
  807. //
  808. // Member: OleThunkWOW::YieldTask16, public
  809. //
  810. // Synopsis: Callback function for 32-bit OLE to yield
  811. //
  812. // History: 08-Aug-94 Ricksa Created
  813. //
  814. //----------------------------------------------------------------------------
  815. STDMETHODIMP OleThunkWOW::YieldTask16(void)
  816. {
  817. WOWYield16();
  818. return S_OK;
  819. }
  820. //+---------------------------------------------------------------------------
  821. //
  822. // Member: OleThunkWOW::DirectedYield, public
  823. //
  824. // Synopsis: Does a directed yield in the VDM.
  825. //
  826. // History: 08-Aug-94 Rickhi Created
  827. //
  828. //----------------------------------------------------------------------------
  829. STDMETHODIMP OleThunkWOW::DirectedYield(DWORD dwCalleeTID)
  830. {
  831. WORD hTask16 = WOWHandle16((void *)dwCalleeTID, WOW_TYPE_HTASK);
  832. thkDebugOut((DEB_ITRACE, "WOWDirectedYield16(%x)\n", hTask16));
  833. WOWDirectedYield16(hTask16);
  834. thkDebugOut((DEB_ITRACE, "WOWDirectedYield16() returned\n"));
  835. return S_OK;
  836. }
  837. //+---------------------------------------------------------------------------
  838. //
  839. // Method: OleThunkWOW::PrepareForCleanup
  840. //
  841. // Synopsis: Prepares OLETHK32 for OLE32.DLL's cleanup.
  842. //
  843. // Effects: It does this by taking all of the remaining 3216 proxies
  844. // and marking them such that no callbacks into the 16-bit
  845. // world are possible.
  846. //
  847. // Arguments: -none-
  848. //
  849. // History: 24-Aug-94 bobday Created
  850. //
  851. // Notes:
  852. //
  853. //----------------------------------------------------------------------------
  854. STDMETHODIMP_(void) OleThunkWOW::PrepareForCleanup(void)
  855. {
  856. CThkMgr *pcthkmgr;
  857. if ( TlsThkGetData() != NULL )
  858. {
  859. pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
  860. //
  861. // Tell the thkmgr to prepare for cleaning itself up
  862. //
  863. pcthkmgr->PrepareForCleanup();
  864. }
  865. }
  866. //+---------------------------------------------------------------------------
  867. //
  868. // Method: OleThunkWOW::GetAppCompatibilityFlags
  869. //
  870. // Synopsis: Used to return the current THK app compatibility flags to
  871. // OLE32.DLL
  872. // Arguments: [void] --
  873. //
  874. // Requires:
  875. //
  876. // Returns: Flags defined in ih\thunkapi.hxx
  877. //
  878. // History: 1-11-96 kevinro Created
  879. //
  880. //----------------------------------------------------------------------------
  881. STDMETHODIMP_(DWORD) OleThunkWOW::GetAppCompatibilityFlags(void)
  882. {
  883. return(TlsThkGetAppCompatFlags());
  884. }