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

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