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.

1317 lines
38 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: call32.cxx (16 bit target)
  7. //
  8. // Contents: Functions to call 32 bit dll in WOW
  9. //
  10. // Functions:
  11. //
  12. // History: 16-Dec-93 JohannP Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <headers.cxx>
  16. #pragma hdrstop
  17. #include <ole2ver.h>
  18. #include <ole2sp.h>
  19. #include <olecoll.h>
  20. #include <map_kv.h>
  21. #include "map_htsk.h"
  22. #include "etask.hxx"
  23. #include <call32.hxx>
  24. #include <obj16.hxx>
  25. #include <go1632pr.hxx>
  26. #include <comlocal.hxx>
  27. static LPVOID lpInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
  28. static LPVOID lpSSInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
  29. LPVOID lpIUnknownObj32; // Address of IUnknown methods handler
  30. static LPVOID lpCallbackProcessing; // Address of CallbackProcessing_3216
  31. static LPVOID pfnCSm16ReleaseHandler_Release32;
  32. static LPVOID pfnConvertHr1632; // TranslateHRESULT_1632
  33. static LPVOID pfnConvertHr3216; // TranslateHRESULT_3216
  34. static LPVOID pfnThkAddAppCompatFlag; // Add an AppCompatibility flag
  35. static DWORD hmodOLEThunkDLL; // Module handle of 32-bit OLE interop DLL
  36. EXTERN_C LPVOID lpThkCallOutputFunctionsProc; // Address of ThkCallOutputFunctions in olethk32.dll
  37. //
  38. // Not used on Win95
  39. //
  40. #ifndef _CHICAGO_
  41. static LPVOID pfnIntOpUninitialize; // Uninitialize function
  42. #else
  43. BOOL gfReleaseDLL = TRUE;
  44. #endif
  45. DWORD __loadds FAR PASCAL CallStub16(LPCALLDATA pcd);
  46. // Address of ThkInitialize() in 32-bits
  47. static LPVOID lpThkInitializeProc;
  48. // Address of ThkUninitialize() in 32-bits
  49. static LPVOID lpThkUninitializeProc;
  50. BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue );
  51. DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds );
  52. DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule );
  53. DWORD __loadds FAR PASCAL CallGetClassObject( LPCALLGETCLASSOBJECTSTRUCT
  54. lpcgcos );
  55. DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow );
  56. DWORD __loadds FAR PASCAL QueryInterface16(IUnknown FAR *punk,
  57. REFIID riid,
  58. void FAR * FAR *ppv);
  59. DWORD __loadds FAR PASCAL AddRef16(IUnknown FAR *punk);
  60. DWORD __loadds FAR PASCAL Release16(IUnknown FAR *punk);
  61. DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm);
  62. DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb);
  63. DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom,
  64. IStream FAR *pstmTo);
  65. DWORD __loadds FAR PASCAL SetOwnerPublic16( DWORD hMem16 );
  66. ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes );
  67. extern DWORD Sm16RhVtbl[SMI_COUNT];
  68. // This DBG block allows assertion that the list is the same size
  69. // as a DATA16
  70. #if DBG == 1
  71. DWORD gdata16[] =
  72. #else
  73. DATA16 gdata16 =
  74. #endif
  75. {
  76. (DWORD)atfnProxy1632Vtbl,
  77. (DWORD)CallbackHandler,
  78. (DWORD)TaskAlloc,
  79. (DWORD)TaskFree,
  80. (DWORD)LoadProcDll,
  81. (DWORD)UnloadProcDll,
  82. (DWORD)CallGetClassObject,
  83. (DWORD)CallCanUnloadNow,
  84. (DWORD)QueryInterface16,
  85. (DWORD)AddRef16,
  86. (DWORD)Release16,
  87. (DWORD)ReleaseStgMedium16,
  88. (DWORD)Sm16RhVtbl,
  89. (DWORD)TouchPointer16,
  90. (DWORD)StgMediumStreamHandler16,
  91. (DWORD)CallStub16,
  92. (DWORD)SetOwnerPublic16,
  93. (DWORD)WinExec16
  94. };
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Function: CallbackHandler
  98. //
  99. // Synopsis: Provides 16-bit address that will allow calling back into
  100. // the 32-bit world's callback handler. See IViewObject::Draw
  101. // lpfnContinue function parameter for the reasons for this
  102. // function.
  103. //
  104. // Returns: BOOL
  105. //
  106. // History: 3-Mar-94 BobDay Created
  107. //
  108. //----------------------------------------------------------------------------
  109. BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue )
  110. {
  111. BOOL fResult;
  112. thkDebugOut((DEB_ITRACE, "CallbackHandler\n"));
  113. fResult = (BOOL)CallProcIn32( dwContinue, 0, 0,
  114. lpCallbackProcessing, 0, CP32_NARGS);
  115. return fResult;
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // Function: Call32Initialize, public
  120. //
  121. // Synopsis: Called once when compobj.dll gets loaded.
  122. // Connects to the interop DLL on the 32-bit side and
  123. // finds entry points
  124. //
  125. // Returns: BOOL
  126. //
  127. // History: 18-Feb-94 JohannP Created
  128. //
  129. // Notes: Called at library initialization time
  130. //
  131. //----------------------------------------------------------------------------
  132. #ifdef _CHICAGO_
  133. extern "C" BOOL FAR PASCAL SSInit( void );
  134. extern "C" DWORD _cdecl SSCall(DWORD cbParamBytes,
  135. DWORD flags,
  136. LPVOID lpfnProcAddress,
  137. DWORD param1,...);
  138. #define SSF_BigStack 1
  139. #endif // _CHICAGO_
  140. STDAPI_(BOOL) Call32Initialize(void)
  141. {
  142. LPVOID lpAddr;
  143. BOOL fRet;
  144. DWORD hr;
  145. thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "In Call32Initialize\n"));
  146. thkAssert(sizeof(gdata16) == sizeof(DATA16));
  147. fRet = FALSE;
  148. do
  149. {
  150. // initialize the 32 bit stack
  151. #ifdef _CHICAGO_
  152. if (SSInit() == FALSE)
  153. {
  154. thkDebugOut((DEB_ERROR, "In Call32Initialize; SSInit failed.\n"));
  155. break;
  156. }
  157. #endif // _CHICAGO_
  158. //
  159. // Load the OLETHK32.DLL in WOW
  160. //
  161. hmodOLEThunkDLL = LoadLibraryEx32W("OLETHK32.DLL", 0, 0);
  162. if (hmodOLEThunkDLL == 0)
  163. {
  164. thkDebugOut((DEB_ERROR, "Call32Initialize; LoadLibary failed.\n"));
  165. break;
  166. }
  167. //
  168. // Get the 32-bit initalization routine
  169. //
  170. lpAddr = GetProcAddress32W(hmodOLEThunkDLL, "IntOpInitialize");
  171. if (lpAddr == NULL)
  172. {
  173. thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IntOpInitialize failed.\n"));
  174. break;
  175. }
  176. // Call the initialization routine and pass the 16-bit
  177. // invocation and proxy setup routine pointers
  178. // We want to keep these pointers in VDM form for Callback16
  179. // so we do not have them mapped flat
  180. if ((hr = CallProcIn32((DWORD)(LPDATA16)(&gdata16), 0, 0, lpAddr, 1 << 2, CP32_NARGS)) != NOERROR)
  181. {
  182. thkDebugOut((DEB_ERROR, "Call32Initialize; Call IntOpInitialize failed. hr = %x\n", hr));
  183. break;
  184. }
  185. //
  186. // Get the address of the start of the 32-bit thunk interpreter
  187. //
  188. lpInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "InvokeOn32");
  189. if (lpInvokeOn32Proc == NULL)
  190. {
  191. thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress InvokeOn32 failed.\n"));
  192. break;
  193. }
  194. #ifdef _CHICAGO_
  195. lpSSInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "SSInvokeOn32");
  196. if (lpSSInvokeOn32Proc == NULL)
  197. {
  198. thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress SSInvokeOn32 failed.\n"));
  199. break;
  200. }
  201. #endif
  202. lpIUnknownObj32 = GetProcAddress32W(hmodOLEThunkDLL, "IUnknownObj32");
  203. if (lpIUnknownObj32 == NULL)
  204. {
  205. thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IUnknowObj32 failed.\n"));
  206. break;
  207. }
  208. // proc address to initialize the thunk manager for
  209. // needs to be called for each apartment
  210. lpThkInitializeProc = GetProcAddress32W(hmodOLEThunkDLL,
  211. "ThkMgrInitialize");
  212. if (lpThkInitializeProc == NULL)
  213. {
  214. break;
  215. }
  216. lpThkUninitializeProc = GetProcAddress32W(hmodOLEThunkDLL,
  217. "ThkMgrUninitialize");
  218. if (lpThkUninitializeProc == NULL)
  219. {
  220. break;
  221. }
  222. pfnCSm16ReleaseHandler_Release32 =
  223. GetProcAddress32W(hmodOLEThunkDLL,
  224. "CSm16ReleaseHandler_Release32");
  225. if (pfnCSm16ReleaseHandler_Release32 == NULL)
  226. {
  227. break;
  228. }
  229. //
  230. // Get the address of the callback procedure for 32-bit callbacks
  231. //
  232. lpCallbackProcessing = GetProcAddress32W(hmodOLEThunkDLL,
  233. "CallbackProcessing_3216");
  234. if ( lpCallbackProcessing == NULL )
  235. {
  236. break;
  237. }
  238. pfnConvertHr1632 = GetProcAddress32W(hmodOLEThunkDLL,
  239. "ConvertHr1632Thunk");
  240. if (pfnConvertHr1632 == NULL)
  241. {
  242. break;
  243. }
  244. pfnConvertHr3216 = GetProcAddress32W(hmodOLEThunkDLL,
  245. "ConvertHr3216Thunk");
  246. if (pfnConvertHr3216 == NULL)
  247. {
  248. break;
  249. }
  250. //
  251. // pfnIntOpUninitialize is not used on Win95
  252. //
  253. #ifndef _CHICAGO_
  254. pfnIntOpUninitialize = GetProcAddress32W(hmodOLEThunkDLL,
  255. "IntOpUninitialize");
  256. if (pfnIntOpUninitialize == NULL)
  257. {
  258. break;
  259. }
  260. #endif
  261. pfnThkAddAppCompatFlag = GetProcAddress32W(hmodOLEThunkDLL,
  262. "ThkAddAppCompatFlag");
  263. if (pfnThkAddAppCompatFlag == NULL )
  264. {
  265. break;
  266. }
  267. #if DBG == 1
  268. #ifndef _CHICAGO_
  269. // BUGBUG: doesn't work on Chicago
  270. lpThkCallOutputFunctionsProc = GetProcAddress32W(hmodOLEThunkDLL, "ThkCallOutputFunctions");
  271. if (lpThkCallOutputFunctionsProc == NULL)
  272. {
  273. // Ignore error as stuff will go to debugger screen by default
  274. thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress ThkCallOutputFunctions failed.\n"));
  275. }
  276. #endif // _CHICAGO_
  277. #endif
  278. fRet = TRUE;
  279. }
  280. while (FALSE);
  281. if (!fRet && hmodOLEThunkDLL != 0)
  282. {
  283. FreeLibrary32W(hmodOLEThunkDLL);
  284. }
  285. thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "Out Call32Initialize exit, %d\n", fRet));
  286. return fRet;
  287. }
  288. //+---------------------------------------------------------------------------
  289. //
  290. // Function: Call32Uninitialize, public
  291. //
  292. // Synopsis: Called once when compobj.dll gets unloaded.
  293. // Disconnects to the interop DLL on the 32-bit side
  294. //
  295. // History: 13-Jul-94 BobDay Created
  296. //
  297. // Notes: Called at library WEP time
  298. //
  299. //----------------------------------------------------------------------------
  300. STDAPI_(void) Call32Uninitialize(void)
  301. {
  302. //
  303. // The notification is only sent on Windows/NT. On Win95, the 32-bit
  304. // side has already been cleaned up at this point, so calling over to
  305. // 32-bits is a really bad idea. We could fault.
  306. //
  307. #ifndef _CHICAGO_
  308. // Notify olethk32 that the 16-bit half of interop is going away
  309. if (pfnIntOpUninitialize != NULL)
  310. {
  311. CallProc32W(0, 0, 0, pfnIntOpUninitialize, 0, CP32_NARGS);
  312. }
  313. #endif
  314. //
  315. // Free OLETHK32.DLL
  316. //
  317. if ( CanReleaseDLL() && hmodOLEThunkDLL != 0 )
  318. {
  319. FreeLibrary32W(hmodOLEThunkDLL);
  320. }
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Function: CallThkUninitialize
  325. //
  326. // Synopsis: Uninitialize the thunk manager and the tls data
  327. //
  328. // History: 5-24-94 JohannP (Johann Posch) Created
  329. //
  330. // Notes: Is called after CoUnintialize returned.
  331. //
  332. //----------------------------------------------------------------------------
  333. STDAPI_(void) CallThkMgrUninitialize(void)
  334. {
  335. thkAssert(lpThkUninitializeProc != NULL);
  336. CallProc32W(0, 0, 0,
  337. lpThkUninitializeProc, 0, CP32_NARGS);
  338. }
  339. //+---------------------------------------------------------------------------
  340. //
  341. // Function: CallThkInitialize
  342. //
  343. // Synopsis: Initializes the thunk manager and the tls data
  344. //
  345. // Returns: Appropriate status code
  346. //
  347. // History: 5-24-94 JohannP (Johann Posch) Created
  348. //
  349. // Notes: Called during CoInitialize.
  350. //
  351. //----------------------------------------------------------------------------
  352. STDAPI CallThkMgrInitialize(void)
  353. {
  354. thkAssert(lpThkInitializeProc != NULL);
  355. return (HRESULT)CallProc32W(0, 0, 0,
  356. lpThkInitializeProc, 0, CP32_NARGS);
  357. }
  358. //+---------------------------------------------------------------------------
  359. //
  360. // Function: CallObjectInWOW, public
  361. //
  362. // Synopsis: Wrapper for CallProcIn32 which handles our particular
  363. // form of call for thunked APIs and methods
  364. //
  365. // Arguments: [oid] - Object ID
  366. // [dwMethod] - Method index
  367. // [pvStack] - Beginning of stack in 16-bits
  368. //
  369. // Returns: 32-bit call result
  370. //
  371. // History: 18-Feb-94 JohannP Created
  372. //
  373. //----------------------------------------------------------------------------
  374. STDAPI_(DWORD) CallObjectInWOW(DWORD dwMethod, LPVOID pvStack)
  375. {
  376. thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n"));
  377. thkAssert(lpInvokeOn32Proc != NULL);
  378. #ifdef _CHICAGO_
  379. // Note: only call if this process is still initialized
  380. HTASK htask;
  381. Etask etask;
  382. if (! ( LookupEtask(htask, etask)
  383. && (etask.m_htask == GetCurrentProcess()) ) )
  384. {
  385. thkDebugOut((DEB_ITRACE, "CallObjectInWOW failed not ETask (%08lX)(0x%08lX, %p)\n",
  386. lpInvokeOn32Proc, dwMethod, pvStack));
  387. return (DWORD)E_UNEXPECTED;
  388. }
  389. #endif
  390. // If the stack pointer is NULL then pass along our own stack
  391. // It won't be used but we need a valid pointer for CallProcIn32
  392. // to work on
  393. if (pvStack == NULL)
  394. {
  395. pvStack = PASCAL_STACK_PTR(dwMethod);
  396. }
  397. thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n",
  398. lpInvokeOn32Proc, dwMethod, pvStack));
  399. // Translate the stack pointer from 16:16 to flat 32
  400. // The other user parameters aren't pointers
  401. return CallProcIn32(0, dwMethod, (DWORD)pvStack,
  402. lpInvokeOn32Proc, (1 << 0), CP32_NARGS);
  403. }
  404. //+---------------------------------------------------------------------------
  405. //
  406. // Method: SSCallObjectInWOW
  407. //
  408. // Synopsis:
  409. //
  410. // Arguments: [dwMetho] --
  411. // [pvStack] --
  412. //
  413. // Returns:
  414. //
  415. // History: 1-24-95 JohannP (Johann Posch) Created
  416. //
  417. // Notes: Same functionality as CallObjectInWOW except
  418. // not switching to 32 bit stack first.
  419. //
  420. //----------------------------------------------------------------------------
  421. STDAPI_(DWORD) SSCallObjectInWOW(DWORD dwMethod, LPVOID pvStack)
  422. {
  423. thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n"));
  424. thkAssert(lpInvokeOn32Proc != NULL);
  425. // If the stack pointer is NULL then pass along our own stack
  426. // It won't be used but we need a valid pointer for CallProcIn32
  427. // to work on
  428. if (pvStack == NULL)
  429. {
  430. pvStack = PASCAL_STACK_PTR(dwMethod);
  431. }
  432. thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n",
  433. lpInvokeOn32Proc, dwMethod, pvStack));
  434. // Translate the stack pointer from 16:16 to flat 32
  435. // The other user parameters aren't pointers
  436. return CallProcIn32(0, dwMethod, (DWORD)pvStack,
  437. lpSSInvokeOn32Proc, (1 << 0), CP32_NARGS);
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: CallObjectInWOWCheckInit, public
  442. //
  443. // Synopsis: Performs CallObjectInWOW with guaranteed initialization
  444. //
  445. // Arguments: [oid] - Object ID
  446. // [dwMethod] - Method index
  447. // [pvStack] - Beginning of stack in 16-bits
  448. //
  449. // Returns: 32-bit call result
  450. //
  451. // History: 18-Feb-94 JohannP Created
  452. //
  453. // Notes: Since this function can return an error code from
  454. // CoInitialize, it should only be used directly for
  455. // functions which return HRESULTs
  456. // Other functions should check the HRESULT and map
  457. // it into an appropriate return value
  458. //
  459. //----------------------------------------------------------------------------
  460. STDAPI_(DWORD) CallObjectInWOWCheckInit(DWORD dwMethod, LPVOID pvStack)
  461. {
  462. Etask etask;
  463. HTASK htask;
  464. HRESULT hr;
  465. thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckInit\n"));
  466. if (!IsEtaskInit(htask, etask))
  467. {
  468. hr = CoInitialize( NULL );
  469. if (FAILED(hr))
  470. {
  471. return (DWORD)hr;
  472. }
  473. thkVerify(LookupEtask( htask, etask ));
  474. etask.m_inits = ETASK_FAKE_INIT;
  475. thkVerify(SetEtask(htask, etask));
  476. }
  477. return( CallObjectInWOW( dwMethod, pvStack) );
  478. }
  479. //+---------------------------------------------------------------------------
  480. //
  481. // Function: CallObjectInWOWCheckThkMgr, public
  482. //
  483. // Synopsis: Performs CallObjectInWOW with guaranteed initialization
  484. // of ThkMgr.
  485. //
  486. // Arguments: [oid] - Object ID
  487. // [dwMethod] - Method index
  488. // [pvStack] - Beginning of stack in 16-bits
  489. //
  490. // Returns: 32-bit call result
  491. //
  492. // History: 25-Aug-94 JohannP Created
  493. //
  494. // Notes: Since this function can return an error code from
  495. // ThkMgrInitialize, it should only be used directly for
  496. // functions which return HRESULTs
  497. // Other functions should check the HRESULT and map
  498. // it into an appropriate return value
  499. // This function is used by Storage api's since
  500. // they do not need compobj.
  501. //
  502. //----------------------------------------------------------------------------
  503. STDAPI_(DWORD) CallObjectInWOWCheckThkMgr(DWORD dwMethod, LPVOID pvStack)
  504. {
  505. Etask etask;
  506. HTASK htask;
  507. HRESULT hr;
  508. thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckThkMgr\n"));
  509. // Note: IsEtaskInit will fail until CoInitialize
  510. // gets called.
  511. // ThkMgrInitialize can be called mutliple time
  512. // on the same apartment. This is inefficient but
  513. // the simplest solution; there are only a few
  514. // apps out there which use Storage api's without
  515. // compobj and ole2.
  516. if (!IsEtaskInit(htask, etask))
  517. {
  518. // Note:
  519. // Under Chicago 32-bit DLL's are loaded into a 16-bit apps private
  520. // memory address space. (Under Daytona, 32-bit DLL's are loaded in
  521. // common memory). This causes an abort as the logic assumes that
  522. // OLETHK32.DLL is loaded at this point.
  523. //
  524. // So if not initialize, initialize the thunk layer now.
  525. //
  526. hr = CallThkMgrInitialize();
  527. if (FAILED(hr))
  528. {
  529. return (DWORD)hr;
  530. }
  531. }
  532. return( CallObjectInWOW( dwMethod, pvStack) );
  533. }
  534. //+---------------------------------------------------------------------------
  535. //
  536. // Function: LoadProcDll, public
  537. //
  538. // Synopsis: Routine to load a 16-bit DLL and get the OLE entry points
  539. //
  540. // Arguments: [lplpds] - LoadProcDll struct full of needed goodies
  541. //
  542. // Returns:
  543. //
  544. // History: 11-Mar-94 BobDay Created
  545. //
  546. //----------------------------------------------------------------------------
  547. DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds )
  548. {
  549. DWORD dwResult;
  550. HMODULE hmod16;
  551. LPDWORD lpdw;
  552. thkDebugOut((DEB_ITRACE, "LoadProcDll\n"));
  553. hmod16 = LoadLibrary( (LPSTR)lplpds->vpDllName );
  554. if ( hmod16 < HINSTANCE_ERROR )
  555. {
  556. return OLETHUNK_DLL16NOTFOUND;
  557. }
  558. lplpds->vpfnGetClassObject =
  559. (DWORD)GetProcAddress( hmod16, "DllGetClassObject" );
  560. lplpds->vpfnCanUnloadNow =
  561. (DWORD)GetProcAddress( hmod16, "DllCanUnloadNow" );
  562. lplpds->vhmodule = (DWORD) hmod16;
  563. return S_OK;
  564. }
  565. //+---------------------------------------------------------------------------
  566. //
  567. // Function: UnloadProcDll, public
  568. //
  569. // Synopsis: Routine to unload a 16-bit DLL
  570. //
  571. // Arguments: [vhmodule] - hmodule to unload
  572. //
  573. // Returns:
  574. //
  575. // History: 11-Mar-94 BobDay Created
  576. //
  577. //----------------------------------------------------------------------------
  578. DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule )
  579. {
  580. DWORD dwResult;
  581. HMODULE hmod16;
  582. thkDebugOut((DEB_ITRACE, "UnloadProcDll\n"));
  583. hmod16 = (HMODULE)vhmodule;
  584. FreeLibrary( hmod16 );
  585. return (DWORD)0;
  586. }
  587. //+---------------------------------------------------------------------------
  588. //
  589. // Function: CallGetClassObject, public
  590. //
  591. // Synopsis: Routine to call 16-bit DLL's DllGetClassObject entrypoint
  592. //
  593. // Arguments: [lpcgcos] - CallGetClassObject struct full of needed goodies
  594. //
  595. // Returns:
  596. //
  597. // History: 11-Mar-94 BobDay Created
  598. //
  599. //----------------------------------------------------------------------------
  600. DWORD __loadds FAR PASCAL CallGetClassObject(
  601. LPCALLGETCLASSOBJECTSTRUCT lpcgcos )
  602. {
  603. HRESULT hresult;
  604. HRESULT (FAR PASCAL *lpfn)(CLSID &,IID &,LPVOID FAR *);
  605. thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
  606. lpfn = (HRESULT (FAR PASCAL *)(CLSID &,IID &,LPVOID FAR*))
  607. lpcgcos->vpfnGetClassObject;
  608. hresult = (*lpfn)( lpcgcos->clsid,
  609. lpcgcos->iid,
  610. (LPVOID FAR *)&lpcgcos->iface );
  611. return (DWORD)hresult;
  612. }
  613. //+---------------------------------------------------------------------------
  614. //
  615. // Function: CallCanUnloadNow, public
  616. //
  617. // Synopsis: Routine to call 16-bit DLL's DllCanUnloadNow entrypoint
  618. //
  619. // Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow in DLL
  620. //
  621. // Returns:
  622. //
  623. // History: 11-Mar-94 BobDay Created
  624. //
  625. //----------------------------------------------------------------------------
  626. DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow )
  627. {
  628. HRESULT hresult;
  629. HRESULT (FAR PASCAL *lpfn)(void);
  630. thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
  631. lpfn = (HRESULT (FAR PASCAL *)(void))vpfnCanUnloadNow;
  632. hresult = (*lpfn)();
  633. return (DWORD)hresult;
  634. }
  635. //+---------------------------------------------------------------------------
  636. //
  637. // Function: QueryInterface16, public
  638. //
  639. // Synopsis: Calls QueryInterface on behalf of the 32-bit code
  640. //
  641. // Arguments: [punk] - Object
  642. // [riid] - IID
  643. // [ppv] - Interface return
  644. //
  645. // Returns: HRESULT
  646. //
  647. // History: 24-Mar-94 JohannP Created
  648. //
  649. //----------------------------------------------------------------------------
  650. DWORD __loadds FAR PASCAL QueryInterface16(IUnknown *punk,
  651. REFIID riid,
  652. void **ppv)
  653. {
  654. DWORD dwRet;
  655. thkAssert(punk != NULL);
  656. // There are shutdown cases where we will attempt to release objects
  657. // which no longer exist in the 16-bit world
  658. // According to CraigWi, in 16-bit OLE objects which had an
  659. // external reference were not cleaned up in CoUninitialize,
  660. // while in 32-bit OLE things are always cleaned up. This
  661. // means that apps which are leaking objects with external locks
  662. // (Word can in some situations) get Releases that they do not
  663. // expect, so protect against calling invalid objects
  664. if (!IsValidInterface(punk))
  665. {
  666. thkDebugOut((DEB_ERROR, "QueryInterface16(%p) - Object invalid\n",
  667. punk));
  668. return (DWORD)E_UNEXPECTED;
  669. }
  670. thkDebugOut((DEB_THUNKMGR, "In QueryInterface16(%p, %p, %p)\n",
  671. punk, &riid, ppv));
  672. dwRet = (DWORD)punk->QueryInterface(riid, ppv);
  673. // There are some apps (Works is one) that return an IOleItemContainer
  674. // as an IOleContainer but neglect to respond to IOleContainer
  675. // in their QueryInterface implementations
  676. // In that event, retry with IOleItemContainer. This is legal
  677. // to return as an IOleContainer since IOleItemContainer is
  678. // derived from IOleContainer
  679. // There are other derivation cases in the same vein
  680. if (dwRet == (DWORD)E_NOINTERFACE)
  681. {
  682. if (IsEqualIID(riid, IID_IOleContainer))
  683. {
  684. // Works has this problem
  685. dwRet = (DWORD)punk->QueryInterface(IID_IOleItemContainer, ppv);
  686. }
  687. else if (IsEqualIID(riid, IID_IPersist))
  688. {
  689. // According to the OLE 2.01 16-bit sources, Corel PhotoPaint
  690. // supports IPersistStorage but not IPersist. Try all persist
  691. // combinations.
  692. dwRet = (DWORD)punk->QueryInterface(IID_IPersistStorage, ppv);
  693. if (dwRet == (DWORD)E_NOINTERFACE)
  694. {
  695. dwRet = (DWORD)punk->QueryInterface(IID_IPersistFile, ppv);
  696. if (dwRet == (DWORD)E_NOINTERFACE)
  697. {
  698. dwRet = (DWORD)punk->QueryInterface(IID_IPersistStream,
  699. ppv);
  700. }
  701. }
  702. }
  703. }
  704. thkDebugOut((DEB_THUNKMGR,
  705. " >>IUnknowObj16:QueryInterface (%p):0x%08lx\n",
  706. *ppv, dwRet));
  707. return dwRet;
  708. }
  709. //+---------------------------------------------------------------------------
  710. //
  711. // Function: AddRef16, public
  712. //
  713. // Synopsis: Calls AddRef on behalf of the 32-bit code
  714. //
  715. // Arguments: [punk] - Object
  716. //
  717. // Returns: 16-bit call return
  718. //
  719. // History: 07-Jul-94 DrewB Created
  720. //
  721. //----------------------------------------------------------------------------
  722. DWORD __loadds FAR PASCAL AddRef16(IUnknown *punk)
  723. {
  724. // There are shutdown cases where we will attempt to release objects
  725. // which no longer exist in the 16-bit world
  726. // According to CraigWi, in 16-bit OLE objects which had an
  727. // external reference were not cleaned up in CoUninitialize,
  728. // while in 32-bit OLE things are always cleaned up. This
  729. // means that apps which are leaking objects with external locks
  730. // (Word can in some situations) get Releases that they do not
  731. // expect, so protect against calling invalid objects
  732. if (!IsValidInterface(punk))
  733. {
  734. thkDebugOut((DEB_ERROR, "AddRef16(%p) - Object invalid\n", punk));
  735. return 0;
  736. }
  737. return punk->AddRef();
  738. }
  739. //+---------------------------------------------------------------------------
  740. //
  741. // Function: Release16, public
  742. //
  743. // Synopsis: Calls Release on behalf of the 32-bit code
  744. //
  745. // Arguments: [punk] - Object
  746. //
  747. // Returns: 16-bit call return
  748. //
  749. // History: 07-Jul-94 DrewB Created
  750. //
  751. //----------------------------------------------------------------------------
  752. DWORD __loadds FAR PASCAL Release16(IUnknown *punk)
  753. {
  754. // There are shutdown cases where we will attempt to release objects
  755. // which no longer exist in the 16-bit world
  756. // According to CraigWi, in 16-bit OLE objects which had an
  757. // external reference were not cleaned up in CoUninitialize,
  758. // while in 32-bit OLE things are always cleaned up. This
  759. // means that apps which are leaking objects with external locks
  760. // (Word can in some situations) get Releases that they do not
  761. // expect, so protect against calling invalid objects
  762. if (!IsValidInterface(punk))
  763. {
  764. thkDebugOut((DEB_ERROR, "Release16(%p) - Object invalid\n", punk));
  765. return 0;
  766. }
  767. return punk->Release();
  768. }
  769. //+---------------------------------------------------------------------------
  770. //
  771. // Function: ReleaseStgMedium16, public
  772. //
  773. // Synopsis: Calls ReleaseStgMedium
  774. //
  775. // Arguments: [psm] - STGMEDIUM
  776. //
  777. // Returns: Appropriate status code
  778. //
  779. // History: 25-Apr-94 DrewB Created
  780. //
  781. //----------------------------------------------------------------------------
  782. DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm)
  783. {
  784. ReleaseStgMedium(psm);
  785. return 0;
  786. }
  787. //+---------------------------------------------------------------------------
  788. //
  789. // Function: CSm16ReleaseHandler routines, public
  790. //
  791. // Synopsis: Method implementations for CSm16ReleaseHandler
  792. //
  793. // History: 24-Apr-94 DrewB Created
  794. // 26-Mar-97 Gopalk Removed call on the proxy to 32-bit
  795. // punkForRelease as the proxy is not
  796. // created in the first place
  797. //
  798. //----------------------------------------------------------------------------
  799. STDMETHODIMP_(ULONG) Sm16RhAddRef(CSm16ReleaseHandler FAR *psrh)
  800. {
  801. return ++psrh->_cReferences;
  802. }
  803. STDMETHODIMP Sm16RhQI(CSm16ReleaseHandler FAR *psrh,
  804. REFIID riid,
  805. void FAR * FAR *ppv)
  806. {
  807. if ( IsEqualIID(riid,IID_IUnknown) )
  808. {
  809. *ppv = psrh;
  810. Sm16RhAddRef(psrh);
  811. return NOERROR;
  812. }
  813. else
  814. {
  815. thkDebugOut((DEB_WARN, "Not a QI for IUnknown\n"));
  816. *ppv = NULL;
  817. return ResultFromScode(E_NOINTERFACE);
  818. }
  819. }
  820. STDMETHODIMP_(ULONG) Sm16RhRelease(CSm16ReleaseHandler FAR *psrh)
  821. {
  822. STGMEDIUM *psm;
  823. METAFILEPICT *pmfp;
  824. HGLOBAL hg;
  825. if (--psrh->_cReferences != 0)
  826. {
  827. return psrh->_cReferences;
  828. }
  829. psm = &psrh->_sm16;
  830. switch(psm->tymed)
  831. {
  832. case TYMED_HGLOBAL:
  833. // Don't free this because copyback needs to occur in the
  834. // 32-bit world
  835. break;
  836. case TYMED_MFPICT:
  837. #ifndef _CHICAGO_
  838. // Win95 thunking shares HMETAFILEs between 16/32 so we don't
  839. // need to clean up our copy
  840. pmfp = (METAFILEPICT *)GlobalLock(psm->hGlobal);
  841. DeleteMetaFile(pmfp->hMF);
  842. GlobalUnlock(psm->hGlobal);
  843. #endif
  844. GlobalFree(psm->hGlobal);
  845. break;
  846. case TYMED_FILE:
  847. case TYMED_ISTREAM:
  848. case TYMED_ISTORAGE:
  849. // Handled by ReleaseStgMedium
  850. // 32-bit name handled by 32-bit part of processing
  851. break;
  852. case TYMED_GDI:
  853. case TYMED_NULL:
  854. // Nothing to release
  855. break;
  856. default:
  857. thkAssert(!"Unknown tymed in CSm16ReleaseHandler::Release");
  858. break;
  859. }
  860. // Continue call in 32-bits where 32-bit task allocations
  861. // and other 32-bit objects are cleaned up
  862. CallProcIn32( (DWORD)psrh, 0, 0,
  863. pfnCSm16ReleaseHandler_Release32, (1 << 2), CP32_NARGS);
  864. // Clean up this
  865. hg = LOWORD(GlobalHandle(HIWORD((unsigned long)psrh)));
  866. GlobalUnlock(hg);
  867. GlobalFree(hg);
  868. return 0;
  869. }
  870. DWORD Sm16RhVtbl[SMI_COUNT] =
  871. {
  872. (DWORD)Sm16RhQI,
  873. (DWORD)Sm16RhAddRef,
  874. (DWORD)Sm16RhRelease
  875. };
  876. //+---------------------------------------------------------------------------
  877. //
  878. // Function: StgMediumStreamHandler16
  879. //
  880. // Synopsis: Copies one stream to another
  881. //
  882. // Effects: Turns out that Excel does the wrong thing with STGMEDIUM's
  883. // when its GetDataHere() method is called. Instead of using
  884. // the provided stream, like it was supposed to, it creates its
  885. // own stream, and smashes the passed in streams pointer. This
  886. // appears to be happening on the Clipboard object for Excel.
  887. // To fix this, the thop function for STGMEDIUM input is going to
  888. // watch for changes to the stream pointer. If it changes, then
  889. // the 'app' (excel) has done something wrong.
  890. //
  891. // To recover from this, the thop will call this routine passing
  892. // the bogus stream and the stream that was supposed to be used.
  893. // This routine will do a pstmFrom->CopyTo(pstmTo), and then
  894. // release the 'bogus' stream pointer.
  895. //
  896. // Arguments: [pstmFrom] -- Stream to copy then release
  897. // [pstmTo] -- Destination stream
  898. //
  899. // History: 7-07-94 kevinro Created
  900. //
  901. // Notes:
  902. //
  903. //----------------------------------------------------------------------------
  904. DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom,
  905. IStream FAR *pstmTo)
  906. {
  907. HRESULT hresult;
  908. LARGE_INTEGER li;
  909. ULARGE_INTEGER uli;
  910. ULONG ul;
  911. thkDebugOut((DEB_ITRACE,
  912. "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p)\n",
  913. pstmFrom,pstmTo));
  914. //
  915. // Assume that the entire stream is the data set to be copied.
  916. // Seek to the start of the stream
  917. //
  918. ULISet32(li,0);
  919. hresult = pstmFrom->Seek(li,STREAM_SEEK_SET,NULL);
  920. if (hresult != NOERROR)
  921. {
  922. thkDebugOut((DEB_ITRACE,
  923. "StgMediumStreamHandler16 failed on seek %lx\n",hresult));
  924. goto exitRtn;
  925. }
  926. //
  927. // To copy the entire stream, specify the maximum size possible.
  928. //
  929. uli.LowPart = -1;
  930. uli.HighPart = -1;
  931. hresult = pstmFrom->CopyTo(pstmTo,uli,NULL,NULL);
  932. if (hresult != NOERROR)
  933. {
  934. thkDebugOut((DEB_ITRACE,
  935. "StgMediumStreamHandler16 failed CopyTo %lx\n",hresult));
  936. goto exitRtn;
  937. }
  938. exitRtn:
  939. //
  940. // In all cases, it is proper to release the pstmFrom, since we didn't
  941. // want it on the 32-bit side at all.
  942. //
  943. ul = pstmFrom->Release();
  944. if (ul != 0)
  945. {
  946. //
  947. // Whoops, we expected this stream pointer to go to zero. We can
  948. // only print a message, then let it leak.
  949. //
  950. thkDebugOut((DEB_ITRACE,
  951. "StgMediumStreamHandler16() Stream not released. ref=%lx\n",ul));
  952. }
  953. thkDebugOut((DEB_ITRACE,
  954. "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p) returns %lx\n",
  955. pstmFrom,pstmTo,hresult));
  956. return((DWORD)hresult);
  957. }
  958. //+---------------------------------------------------------------------------
  959. //
  960. // Function: TouchPointer16, public
  961. //
  962. // Synopsis: Touches a byte at the given pointer's address to
  963. // bring in not-present segments
  964. //
  965. // Arguments: [pb] - Pointer
  966. //
  967. // History: 25-Apr-94 DrewB Created
  968. //
  969. //----------------------------------------------------------------------------
  970. DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb)
  971. {
  972. BYTE b = 0;
  973. if (pb)
  974. {
  975. b = *pb;
  976. }
  977. #ifdef _CHICAGO_
  978. // On Win95, fix the memory block before returning to 32-bit code
  979. // to lock the segment in place. If we tried to do this in 32-bit
  980. // code we could be preempted before we successfully lock the memory
  981. GlobalFix(LOWORD(HIWORD((DWORD)pb)));
  982. #endif
  983. return b;
  984. }
  985. //+---------------------------------------------------------------------------
  986. //
  987. // Function: SetOwnerPublic16, public
  988. //
  989. // Synopsis: Sets a given 16-bit memory handle to be owned by nobody
  990. // (everybody)
  991. //
  992. // Arguments: [hmem] - 16-bit memory handle
  993. //
  994. // History: 13-Jul-94 BobDay Created
  995. //
  996. //----------------------------------------------------------------------------
  997. extern "C" void FAR PASCAL KERNEL_SetOwner( WORD hMem16, WORD wOwner );
  998. DWORD __loadds FAR PASCAL SetOwnerPublic16(DWORD hmem)
  999. {
  1000. KERNEL_SetOwner( (WORD)hmem, (WORD)-1 );
  1001. return 0;
  1002. }
  1003. //+---------------------------------------------------------------------------
  1004. //
  1005. // Function: WinExec16, public
  1006. //
  1007. // Synopsis: Routine to run an application on behalf of ole32.dll
  1008. //
  1009. // Arguments: [lpwes] - WinExec16 struct full of needed goodies
  1010. //
  1011. // Returns:
  1012. //
  1013. // History: 27-Jul-94 AlexT Created
  1014. //
  1015. //----------------------------------------------------------------------------
  1016. ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes )
  1017. {
  1018. ULONG ulResult;
  1019. thkDebugOut((DEB_ITRACE, "WinExec16(%s, %d)\n",
  1020. lpwes->vpCommandLine, lpwes->vusShow));
  1021. ulResult = (ULONG) WinExec((LPSTR)lpwes->vpCommandLine,
  1022. (UINT)lpwes->vusShow);
  1023. thkDebugOut((DEB_ITRACE, "WinExec returned %ld\n", ulResult));
  1024. return ulResult;
  1025. }
  1026. //+---------------------------------------------------------------------------
  1027. //
  1028. // Function: ConvertHr1632, public
  1029. //
  1030. // Synopsis: Converts a 16-bit HRESULT into a 32-bit HRESULT
  1031. //
  1032. // Arguments: [hr] - 16-bit HRESULT
  1033. //
  1034. // Returns: Appropriate status code
  1035. //
  1036. // History: 26-Sep-94 DrewB Created
  1037. //
  1038. // Notes: Delegates to 32-bit functions
  1039. //
  1040. //----------------------------------------------------------------------------
  1041. STDAPI ConvertHr1632(HRESULT hr)
  1042. {
  1043. return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0,
  1044. pfnConvertHr1632, 0, CP32_NARGS);
  1045. }
  1046. //+---------------------------------------------------------------------------
  1047. //
  1048. // Function: ConvertHr3216, public
  1049. //
  1050. // Synopsis: Converts a 32-bit HRESULT into a 16-bit HRESULT
  1051. //
  1052. // Arguments: [hr] - 32-bit HRESULT
  1053. //
  1054. // Returns: Appropriate status code
  1055. //
  1056. // History: 26-Sep-94 DrewB Created
  1057. //
  1058. // Notes: Delegates to 32-bit functions
  1059. //
  1060. //----------------------------------------------------------------------------
  1061. STDAPI ConvertHr3216(HRESULT hr)
  1062. {
  1063. return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0,
  1064. pfnConvertHr3216, 0, CP32_NARGS);
  1065. }
  1066. //+---------------------------------------------------------------------------
  1067. //
  1068. // Function: SSCallProc32, public
  1069. //
  1070. // Synopsis: Wrapper for CallProc32W which switches to a bigger stack
  1071. //
  1072. // Arguments: [dw1] - argumensts similar to CallProc32W
  1073. // [dw2]
  1074. // [dw3]
  1075. // [pfn32]
  1076. // [dwPtrTranslate]
  1077. // [dwArgCount]
  1078. //
  1079. // Returns: 32-bit call result
  1080. //
  1081. // History: 5-Dec-94 JohannP Created
  1082. //
  1083. // Note: this will be enabled as soon as I get the CallProc32WFix from
  1084. // Win95
  1085. //----------------------------------------------------------------------------
  1086. #ifdef _STACKSWITCHON16_
  1087. DWORD FAR PASCAL SSCallProc32(DWORD dw1, DWORD dw2, DWORD dw3,
  1088. LPVOID pfn32, DWORD dwPtrTranslate,
  1089. DWORD dwArgCount)
  1090. {
  1091. DWORD dwRet = 0;
  1092. // switch to the 32 bit stack
  1093. //
  1094. // return SSCall(24,SSF_BigStack, (LPVOID)CallProc32W, dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount);
  1095. thkDebugOut((DEB_ERROR, "SSCallProc32(dwArgCount:%x, dwPtrTranslate:%x, pfn32:%x, dw3:%x, dw2:%x, dw1:%x)\n",
  1096. dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1));
  1097. #if DBG == 1
  1098. if (fSSOn)
  1099. {
  1100. dwRet = SSCall(24,SSF_BigStack, (LPVOID)CallProc32WFix, dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1);
  1101. }
  1102. else
  1103. #endif // DBG==1
  1104. {
  1105. dwRet = CallProc32W(dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount);
  1106. }
  1107. return dwRet;
  1108. }
  1109. #endif // _STACKSWITCHON16_
  1110. //+-------------------------------------------------------------------------
  1111. //
  1112. // Function: AddAppCompatFlag
  1113. //
  1114. // Synopsis: calls into olethk32 to add an app compability flag.
  1115. //
  1116. // Effects:
  1117. //
  1118. // Arguments: [dwFlag] -- the flag to add
  1119. //
  1120. // Requires:
  1121. //
  1122. // Returns: void
  1123. //
  1124. // Signals:
  1125. //
  1126. // Modifies:
  1127. //
  1128. // Algorithm:
  1129. //
  1130. // History: dd-mmm-yy Author Comment
  1131. // 15-Mar-95 alexgo author
  1132. //
  1133. // Notes: this function is exported so that ole2.dll can also call it
  1134. //
  1135. //--------------------------------------------------------------------------
  1136. STDAPI_(void) AddAppCompatFlag( DWORD dwFlag )
  1137. {
  1138. CallProcIn32( (DWORD)dwFlag, 0, 0,
  1139. pfnThkAddAppCompatFlag, 0, CP32_NARGS);
  1140. }