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.

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