|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: call32.cxx (16 bit target)
//
// Contents: Functions to call 32 bit dll in WOW
//
// Functions:
//
// History: 16-Dec-93 JohannP Created
//
//--------------------------------------------------------------------------
#include <headers.cxx>
#pragma hdrstop
#include <ole2ver.h>
#include <ole2sp.h>
#include <olecoll.h>
#include <map_kv.h>
#include "map_htsk.h"
#include "etask.hxx"
#include <call32.hxx>
#include <obj16.hxx>
#include <go1632pr.hxx>
#include <comlocal.hxx>
static LPVOID lpInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
static LPVOID lpSSInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
LPVOID lpIUnknownObj32; // Address of IUnknown methods handler
static LPVOID lpCallbackProcessing; // Address of CallbackProcessing_3216
static LPVOID pfnCSm16ReleaseHandler_Release32;
static LPVOID pfnConvertHr1632; // TranslateHRESULT_1632
static LPVOID pfnConvertHr3216; // TranslateHRESULT_3216
static LPVOID pfnThkAddAppCompatFlag; // Add an AppCompatibility flag
static DWORD hmodOLEThunkDLL; // Module handle of 32-bit OLE interop DLL
EXTERN_C LPVOID lpThkCallOutputFunctionsProc; // Address of ThkCallOutputFunctions in olethk32.dll
//
// Not used on Win95
//
#ifndef _CHICAGO_
static LPVOID pfnIntOpUninitialize; // Uninitialize function
#else
BOOL gfReleaseDLL = TRUE; #endif
DWORD __loadds FAR PASCAL CallStub16(LPCALLDATA pcd);
// Address of ThkInitialize() in 32-bits
static LPVOID lpThkInitializeProc; // Address of ThkUninitialize() in 32-bits
static LPVOID lpThkUninitializeProc;
BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue ); DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds ); DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule ); DWORD __loadds FAR PASCAL CallGetClassObject( LPCALLGETCLASSOBJECTSTRUCT lpcgcos ); DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow ); DWORD __loadds FAR PASCAL QueryInterface16(IUnknown FAR *punk, REFIID riid, void FAR * FAR *ppv); DWORD __loadds FAR PASCAL AddRef16(IUnknown FAR *punk); DWORD __loadds FAR PASCAL Release16(IUnknown FAR *punk); DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm); DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb); DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom, IStream FAR *pstmTo); DWORD __loadds FAR PASCAL SetOwnerPublic16( DWORD hMem16 ); ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes );
extern DWORD Sm16RhVtbl[SMI_COUNT];
// This DBG block allows assertion that the list is the same size
// as a DATA16
#if DBG == 1
DWORD gdata16[] = #else
DATA16 gdata16 = #endif
{ (DWORD)atfnProxy1632Vtbl, (DWORD)CallbackHandler, (DWORD)TaskAlloc, (DWORD)TaskFree, (DWORD)LoadProcDll, (DWORD)UnloadProcDll, (DWORD)CallGetClassObject, (DWORD)CallCanUnloadNow, (DWORD)QueryInterface16, (DWORD)AddRef16, (DWORD)Release16, (DWORD)ReleaseStgMedium16, (DWORD)Sm16RhVtbl, (DWORD)TouchPointer16, (DWORD)StgMediumStreamHandler16, (DWORD)CallStub16, (DWORD)SetOwnerPublic16, (DWORD)WinExec16 };
//+---------------------------------------------------------------------------
//
// Function: CallbackHandler
//
// Synopsis: Provides 16-bit address that will allow calling back into
// the 32-bit world's callback handler. See IViewObject::Draw
// lpfnContinue function parameter for the reasons for this
// function.
//
// Returns: BOOL
//
// History: 3-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue ) { BOOL fResult;
thkDebugOut((DEB_ITRACE, "CallbackHandler\n"));
fResult = (BOOL)CallProcIn32( dwContinue, 0, 0, lpCallbackProcessing, 0, CP32_NARGS);
return fResult; }
//+---------------------------------------------------------------------------
//
// Function: Call32Initialize, public
//
// Synopsis: Called once when compobj.dll gets loaded.
// Connects to the interop DLL on the 32-bit side and
// finds entry points
//
// Returns: BOOL
//
// History: 18-Feb-94 JohannP Created
//
// Notes: Called at library initialization time
//
//----------------------------------------------------------------------------
#ifdef _CHICAGO_
extern "C" BOOL FAR PASCAL SSInit( void ); extern "C" DWORD _cdecl SSCall(DWORD cbParamBytes, DWORD flags, LPVOID lpfnProcAddress, DWORD param1,...);
#define SSF_BigStack 1
#endif // _CHICAGO_
STDAPI_(BOOL) Call32Initialize(void) { LPVOID lpAddr; BOOL fRet; DWORD hr;
thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "In Call32Initialize\n"));
thkAssert(sizeof(gdata16) == sizeof(DATA16));
fRet = FALSE; do { // initialize the 32 bit stack
#ifdef _CHICAGO_
if (SSInit() == FALSE) { thkDebugOut((DEB_ERROR, "In Call32Initialize; SSInit failed.\n")); break; } #endif // _CHICAGO_
//
// Load the OLETHK32.DLL in WOW
//
hmodOLEThunkDLL = LoadLibraryEx32W("OLETHK32.DLL", 0, 0); if (hmodOLEThunkDLL == 0) { thkDebugOut((DEB_ERROR, "Call32Initialize; LoadLibary failed.\n")); break; }
//
// Get the 32-bit initalization routine
//
lpAddr = GetProcAddress32W(hmodOLEThunkDLL, "IntOpInitialize"); if (lpAddr == NULL) { thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IntOpInitialize failed.\n")); break; }
// Call the initialization routine and pass the 16-bit
// invocation and proxy setup routine pointers
// We want to keep these pointers in VDM form for Callback16
// so we do not have them mapped flat
if ((hr = CallProcIn32((DWORD)(LPDATA16)(&gdata16), 0, 0, lpAddr, 1 << 2, CP32_NARGS)) != NOERROR) { thkDebugOut((DEB_ERROR, "Call32Initialize; Call IntOpInitialize failed. hr = %x\n", hr)); break; }
//
// Get the address of the start of the 32-bit thunk interpreter
//
lpInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "InvokeOn32"); if (lpInvokeOn32Proc == NULL) { thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress InvokeOn32 failed.\n")); break; } #ifdef _CHICAGO_
lpSSInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "SSInvokeOn32"); if (lpSSInvokeOn32Proc == NULL) { thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress SSInvokeOn32 failed.\n")); break; } #endif
lpIUnknownObj32 = GetProcAddress32W(hmodOLEThunkDLL, "IUnknownObj32"); if (lpIUnknownObj32 == NULL) { thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IUnknowObj32 failed.\n")); break; }
// proc address to initialize the thunk manager for
// needs to be called for each apartment
lpThkInitializeProc = GetProcAddress32W(hmodOLEThunkDLL, "ThkMgrInitialize"); if (lpThkInitializeProc == NULL) { break; }
lpThkUninitializeProc = GetProcAddress32W(hmodOLEThunkDLL, "ThkMgrUninitialize"); if (lpThkUninitializeProc == NULL) { break; }
pfnCSm16ReleaseHandler_Release32 = GetProcAddress32W(hmodOLEThunkDLL, "CSm16ReleaseHandler_Release32"); if (pfnCSm16ReleaseHandler_Release32 == NULL) { break; }
//
// Get the address of the callback procedure for 32-bit callbacks
//
lpCallbackProcessing = GetProcAddress32W(hmodOLEThunkDLL, "CallbackProcessing_3216"); if ( lpCallbackProcessing == NULL ) { break; }
pfnConvertHr1632 = GetProcAddress32W(hmodOLEThunkDLL, "ConvertHr1632Thunk"); if (pfnConvertHr1632 == NULL) { break; }
pfnConvertHr3216 = GetProcAddress32W(hmodOLEThunkDLL, "ConvertHr3216Thunk"); if (pfnConvertHr3216 == NULL) { break; }
//
// pfnIntOpUninitialize is not used on Win95
//
#ifndef _CHICAGO_
pfnIntOpUninitialize = GetProcAddress32W(hmodOLEThunkDLL, "IntOpUninitialize"); if (pfnIntOpUninitialize == NULL) { break; } #endif
pfnThkAddAppCompatFlag = GetProcAddress32W(hmodOLEThunkDLL, "ThkAddAppCompatFlag");
if (pfnThkAddAppCompatFlag == NULL ) { break; }
#if DBG == 1
#ifndef _CHICAGO_
// BUGBUG: doesn't work on Chicago
lpThkCallOutputFunctionsProc = GetProcAddress32W(hmodOLEThunkDLL, "ThkCallOutputFunctions"); if (lpThkCallOutputFunctionsProc == NULL) { // Ignore error as stuff will go to debugger screen by default
thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress ThkCallOutputFunctions failed.\n")); } #endif // _CHICAGO_
#endif
fRet = TRUE; } while (FALSE);
if (!fRet && hmodOLEThunkDLL != 0) { FreeLibrary32W(hmodOLEThunkDLL); }
thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "Out Call32Initialize exit, %d\n", fRet)); return fRet; }
//+---------------------------------------------------------------------------
//
// Function: Call32Uninitialize, public
//
// Synopsis: Called once when compobj.dll gets unloaded.
// Disconnects to the interop DLL on the 32-bit side
//
// History: 13-Jul-94 BobDay Created
//
// Notes: Called at library WEP time
//
//----------------------------------------------------------------------------
STDAPI_(void) Call32Uninitialize(void) { //
// The notification is only sent on Windows/NT. On Win95, the 32-bit
// side has already been cleaned up at this point, so calling over to
// 32-bits is a really bad idea. We could fault.
//
#ifndef _CHICAGO_
// Notify olethk32 that the 16-bit half of interop is going away
if (pfnIntOpUninitialize != NULL) { CallProc32W(0, 0, 0, pfnIntOpUninitialize, 0, CP32_NARGS); } #endif
//
// Free OLETHK32.DLL
//
if ( CanReleaseDLL() && hmodOLEThunkDLL != 0 ) { FreeLibrary32W(hmodOLEThunkDLL); } }
//+---------------------------------------------------------------------------
//
// Function: CallThkUninitialize
//
// Synopsis: Uninitialize the thunk manager and the tls data
//
// History: 5-24-94 JohannP (Johann Posch) Created
//
// Notes: Is called after CoUnintialize returned.
//
//----------------------------------------------------------------------------
STDAPI_(void) CallThkMgrUninitialize(void) { thkAssert(lpThkUninitializeProc != NULL);
CallProc32W(0, 0, 0, lpThkUninitializeProc, 0, CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Function: CallThkInitialize
//
// Synopsis: Initializes the thunk manager and the tls data
//
// Returns: Appropriate status code
//
// History: 5-24-94 JohannP (Johann Posch) Created
//
// Notes: Called during CoInitialize.
//
//----------------------------------------------------------------------------
STDAPI CallThkMgrInitialize(void) { thkAssert(lpThkInitializeProc != NULL);
return (HRESULT)CallProc32W(0, 0, 0, lpThkInitializeProc, 0, CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Function: CallObjectInWOW, public
//
// Synopsis: Wrapper for CallProcIn32 which handles our particular
// form of call for thunked APIs and methods
//
// Arguments: [oid] - Object ID
// [dwMethod] - Method index
// [pvStack] - Beginning of stack in 16-bits
//
// Returns: 32-bit call result
//
// History: 18-Feb-94 JohannP Created
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) CallObjectInWOW(DWORD dwMethod, LPVOID pvStack) {
thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n")); thkAssert(lpInvokeOn32Proc != NULL);
#ifdef _CHICAGO_
// Note: only call if this process is still initialized
HTASK htask; Etask etask;
if (! ( LookupEtask(htask, etask) && (etask.m_htask == GetCurrentProcess()) ) ) { thkDebugOut((DEB_ITRACE, "CallObjectInWOW failed not ETask (%08lX)(0x%08lX, %p)\n", lpInvokeOn32Proc, dwMethod, pvStack)); return (DWORD)E_UNEXPECTED; } #endif
// If the stack pointer is NULL then pass along our own stack
// It won't be used but we need a valid pointer for CallProcIn32
// to work on
if (pvStack == NULL) { pvStack = PASCAL_STACK_PTR(dwMethod); }
thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n", lpInvokeOn32Proc, dwMethod, pvStack));
// Translate the stack pointer from 16:16 to flat 32
// The other user parameters aren't pointers
return CallProcIn32(0, dwMethod, (DWORD)pvStack, lpInvokeOn32Proc, (1 << 0), CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Method: SSCallObjectInWOW
//
// Synopsis:
//
// Arguments: [dwMetho] --
// [pvStack] --
//
// Returns:
//
// History: 1-24-95 JohannP (Johann Posch) Created
//
// Notes: Same functionality as CallObjectInWOW except
// not switching to 32 bit stack first.
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) SSCallObjectInWOW(DWORD dwMethod, LPVOID pvStack) { thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n")); thkAssert(lpInvokeOn32Proc != NULL);
// If the stack pointer is NULL then pass along our own stack
// It won't be used but we need a valid pointer for CallProcIn32
// to work on
if (pvStack == NULL) { pvStack = PASCAL_STACK_PTR(dwMethod); }
thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n", lpInvokeOn32Proc, dwMethod, pvStack));
// Translate the stack pointer from 16:16 to flat 32
// The other user parameters aren't pointers
return CallProcIn32(0, dwMethod, (DWORD)pvStack, lpSSInvokeOn32Proc, (1 << 0), CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Function: CallObjectInWOWCheckInit, public
//
// Synopsis: Performs CallObjectInWOW with guaranteed initialization
//
// Arguments: [oid] - Object ID
// [dwMethod] - Method index
// [pvStack] - Beginning of stack in 16-bits
//
// Returns: 32-bit call result
//
// History: 18-Feb-94 JohannP Created
//
// Notes: Since this function can return an error code from
// CoInitialize, it should only be used directly for
// functions which return HRESULTs
// Other functions should check the HRESULT and map
// it into an appropriate return value
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) CallObjectInWOWCheckInit(DWORD dwMethod, LPVOID pvStack) { Etask etask; HTASK htask; HRESULT hr;
thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckInit\n"));
if (!IsEtaskInit(htask, etask)) { hr = CoInitialize( NULL ); if (FAILED(hr)) { return (DWORD)hr; }
thkVerify(LookupEtask( htask, etask )); etask.m_inits = ETASK_FAKE_INIT; thkVerify(SetEtask(htask, etask)); }
return( CallObjectInWOW( dwMethod, pvStack) ); } //+---------------------------------------------------------------------------
//
// Function: CallObjectInWOWCheckThkMgr, public
//
// Synopsis: Performs CallObjectInWOW with guaranteed initialization
// of ThkMgr.
//
// Arguments: [oid] - Object ID
// [dwMethod] - Method index
// [pvStack] - Beginning of stack in 16-bits
//
// Returns: 32-bit call result
//
// History: 25-Aug-94 JohannP Created
//
// Notes: Since this function can return an error code from
// ThkMgrInitialize, it should only be used directly for
// functions which return HRESULTs
// Other functions should check the HRESULT and map
// it into an appropriate return value
// This function is used by Storage api's since
// they do not need compobj.
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) CallObjectInWOWCheckThkMgr(DWORD dwMethod, LPVOID pvStack) { Etask etask; HTASK htask; HRESULT hr;
thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckThkMgr\n"));
// Note: IsEtaskInit will fail until CoInitialize
// gets called.
// ThkMgrInitialize can be called mutliple time
// on the same apartment. This is inefficient but
// the simplest solution; there are only a few
// apps out there which use Storage api's without
// compobj and ole2.
if (!IsEtaskInit(htask, etask)) { // Note:
// Under Chicago 32-bit DLL's are loaded into a 16-bit apps private
// memory address space. (Under Daytona, 32-bit DLL's are loaded in
// common memory). This causes an abort as the logic assumes that
// OLETHK32.DLL is loaded at this point.
//
// So if not initialize, initialize the thunk layer now.
//
hr = CallThkMgrInitialize(); if (FAILED(hr)) { return (DWORD)hr; } }
return( CallObjectInWOW( dwMethod, pvStack) ); }
//+---------------------------------------------------------------------------
//
// Function: LoadProcDll, public
//
// Synopsis: Routine to load a 16-bit DLL and get the OLE entry points
//
// Arguments: [lplpds] - LoadProcDll struct full of needed goodies
//
// Returns:
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds ) { DWORD dwResult; HMODULE hmod16; LPDWORD lpdw;
thkDebugOut((DEB_ITRACE, "LoadProcDll\n"));
hmod16 = LoadLibrary( (LPSTR)lplpds->vpDllName );
if ( hmod16 < HINSTANCE_ERROR ) { return OLETHUNK_DLL16NOTFOUND; }
lplpds->vpfnGetClassObject = (DWORD)GetProcAddress( hmod16, "DllGetClassObject" ); lplpds->vpfnCanUnloadNow = (DWORD)GetProcAddress( hmod16, "DllCanUnloadNow" );
lplpds->vhmodule = (DWORD) hmod16;
return S_OK; }
//+---------------------------------------------------------------------------
//
// Function: UnloadProcDll, public
//
// Synopsis: Routine to unload a 16-bit DLL
//
// Arguments: [vhmodule] - hmodule to unload
//
// Returns:
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule ) { DWORD dwResult; HMODULE hmod16;
thkDebugOut((DEB_ITRACE, "UnloadProcDll\n"));
hmod16 = (HMODULE)vhmodule;
FreeLibrary( hmod16 );
return (DWORD)0; }
//+---------------------------------------------------------------------------
//
// Function: CallGetClassObject, public
//
// Synopsis: Routine to call 16-bit DLL's DllGetClassObject entrypoint
//
// Arguments: [lpcgcos] - CallGetClassObject struct full of needed goodies
//
// Returns:
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL CallGetClassObject( LPCALLGETCLASSOBJECTSTRUCT lpcgcos ) { HRESULT hresult; HRESULT (FAR PASCAL *lpfn)(CLSID &,IID &,LPVOID FAR *);
thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
lpfn = (HRESULT (FAR PASCAL *)(CLSID &,IID &,LPVOID FAR*)) lpcgcos->vpfnGetClassObject;
hresult = (*lpfn)( lpcgcos->clsid, lpcgcos->iid, (LPVOID FAR *)&lpcgcos->iface );
return (DWORD)hresult; }
//+---------------------------------------------------------------------------
//
// Function: CallCanUnloadNow, public
//
// Synopsis: Routine to call 16-bit DLL's DllCanUnloadNow entrypoint
//
// Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow in DLL
//
// Returns:
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow ) { HRESULT hresult; HRESULT (FAR PASCAL *lpfn)(void);
thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
lpfn = (HRESULT (FAR PASCAL *)(void))vpfnCanUnloadNow;
hresult = (*lpfn)();
return (DWORD)hresult; }
//+---------------------------------------------------------------------------
//
// Function: QueryInterface16, public
//
// Synopsis: Calls QueryInterface on behalf of the 32-bit code
//
// Arguments: [punk] - Object
// [riid] - IID
// [ppv] - Interface return
//
// Returns: HRESULT
//
// History: 24-Mar-94 JohannP Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL QueryInterface16(IUnknown *punk, REFIID riid, void **ppv) { DWORD dwRet;
thkAssert(punk != NULL);
// There are shutdown cases where we will attempt to release objects
// which no longer exist in the 16-bit world
// According to CraigWi, in 16-bit OLE objects which had an
// external reference were not cleaned up in CoUninitialize,
// while in 32-bit OLE things are always cleaned up. This
// means that apps which are leaking objects with external locks
// (Word can in some situations) get Releases that they do not
// expect, so protect against calling invalid objects
if (!IsValidInterface(punk)) { thkDebugOut((DEB_ERROR, "QueryInterface16(%p) - Object invalid\n", punk)); return (DWORD)E_UNEXPECTED; }
thkDebugOut((DEB_THUNKMGR, "In QueryInterface16(%p, %p, %p)\n", punk, &riid, ppv));
dwRet = (DWORD)punk->QueryInterface(riid, ppv);
// There are some apps (Works is one) that return an IOleItemContainer
// as an IOleContainer but neglect to respond to IOleContainer
// in their QueryInterface implementations
// In that event, retry with IOleItemContainer. This is legal
// to return as an IOleContainer since IOleItemContainer is
// derived from IOleContainer
// There are other derivation cases in the same vein
if (dwRet == (DWORD)E_NOINTERFACE) { if (IsEqualIID(riid, IID_IOleContainer)) { // Works has this problem
dwRet = (DWORD)punk->QueryInterface(IID_IOleItemContainer, ppv); } else if (IsEqualIID(riid, IID_IPersist)) { // According to the OLE 2.01 16-bit sources, Corel PhotoPaint
// supports IPersistStorage but not IPersist. Try all persist
// combinations.
dwRet = (DWORD)punk->QueryInterface(IID_IPersistStorage, ppv); if (dwRet == (DWORD)E_NOINTERFACE) { dwRet = (DWORD)punk->QueryInterface(IID_IPersistFile, ppv); if (dwRet == (DWORD)E_NOINTERFACE) { dwRet = (DWORD)punk->QueryInterface(IID_IPersistStream, ppv); } } } }
thkDebugOut((DEB_THUNKMGR, " >>IUnknowObj16:QueryInterface (%p):0x%08lx\n", *ppv, dwRet));
return dwRet; }
//+---------------------------------------------------------------------------
//
// Function: AddRef16, public
//
// Synopsis: Calls AddRef on behalf of the 32-bit code
//
// Arguments: [punk] - Object
//
// Returns: 16-bit call return
//
// History: 07-Jul-94 DrewB Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL AddRef16(IUnknown *punk) { // There are shutdown cases where we will attempt to release objects
// which no longer exist in the 16-bit world
// According to CraigWi, in 16-bit OLE objects which had an
// external reference were not cleaned up in CoUninitialize,
// while in 32-bit OLE things are always cleaned up. This
// means that apps which are leaking objects with external locks
// (Word can in some situations) get Releases that they do not
// expect, so protect against calling invalid objects
if (!IsValidInterface(punk)) { thkDebugOut((DEB_ERROR, "AddRef16(%p) - Object invalid\n", punk)); return 0; }
return punk->AddRef(); }
//+---------------------------------------------------------------------------
//
// Function: Release16, public
//
// Synopsis: Calls Release on behalf of the 32-bit code
//
// Arguments: [punk] - Object
//
// Returns: 16-bit call return
//
// History: 07-Jul-94 DrewB Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL Release16(IUnknown *punk) { // There are shutdown cases where we will attempt to release objects
// which no longer exist in the 16-bit world
// According to CraigWi, in 16-bit OLE objects which had an
// external reference were not cleaned up in CoUninitialize,
// while in 32-bit OLE things are always cleaned up. This
// means that apps which are leaking objects with external locks
// (Word can in some situations) get Releases that they do not
// expect, so protect against calling invalid objects
if (!IsValidInterface(punk)) { thkDebugOut((DEB_ERROR, "Release16(%p) - Object invalid\n", punk)); return 0; }
return punk->Release(); }
//+---------------------------------------------------------------------------
//
// Function: ReleaseStgMedium16, public
//
// Synopsis: Calls ReleaseStgMedium
//
// Arguments: [psm] - STGMEDIUM
//
// Returns: Appropriate status code
//
// History: 25-Apr-94 DrewB Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm) { ReleaseStgMedium(psm); return 0; }
//+---------------------------------------------------------------------------
//
// Function: CSm16ReleaseHandler routines, public
//
// Synopsis: Method implementations for CSm16ReleaseHandler
//
// History: 24-Apr-94 DrewB Created
// 26-Mar-97 Gopalk Removed call on the proxy to 32-bit
// punkForRelease as the proxy is not
// created in the first place
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) Sm16RhAddRef(CSm16ReleaseHandler FAR *psrh) { return ++psrh->_cReferences; }
STDMETHODIMP Sm16RhQI(CSm16ReleaseHandler FAR *psrh, REFIID riid, void FAR * FAR *ppv) { if ( IsEqualIID(riid,IID_IUnknown) ) { *ppv = psrh; Sm16RhAddRef(psrh); return NOERROR; } else { thkDebugOut((DEB_WARN, "Not a QI for IUnknown\n")); *ppv = NULL; return ResultFromScode(E_NOINTERFACE); } }
STDMETHODIMP_(ULONG) Sm16RhRelease(CSm16ReleaseHandler FAR *psrh) { STGMEDIUM *psm; METAFILEPICT *pmfp; HGLOBAL hg;
if (--psrh->_cReferences != 0) { return psrh->_cReferences; }
psm = &psrh->_sm16; switch(psm->tymed) { case TYMED_HGLOBAL: // Don't free this because copyback needs to occur in the
// 32-bit world
break;
case TYMED_MFPICT: #ifndef _CHICAGO_
// Win95 thunking shares HMETAFILEs between 16/32 so we don't
// need to clean up our copy
pmfp = (METAFILEPICT *)GlobalLock(psm->hGlobal); DeleteMetaFile(pmfp->hMF); GlobalUnlock(psm->hGlobal); #endif
GlobalFree(psm->hGlobal); break;
case TYMED_FILE: case TYMED_ISTREAM: case TYMED_ISTORAGE: // Handled by ReleaseStgMedium
// 32-bit name handled by 32-bit part of processing
break;
case TYMED_GDI: case TYMED_NULL: // Nothing to release
break;
default: thkAssert(!"Unknown tymed in CSm16ReleaseHandler::Release"); break; }
// Continue call in 32-bits where 32-bit task allocations
// and other 32-bit objects are cleaned up
CallProcIn32( (DWORD)psrh, 0, 0, pfnCSm16ReleaseHandler_Release32, (1 << 2), CP32_NARGS);
// Clean up this
hg = LOWORD(GlobalHandle(HIWORD((unsigned long)psrh))); GlobalUnlock(hg); GlobalFree(hg);
return 0; }
DWORD Sm16RhVtbl[SMI_COUNT] = { (DWORD)Sm16RhQI, (DWORD)Sm16RhAddRef, (DWORD)Sm16RhRelease };
//+---------------------------------------------------------------------------
//
// Function: StgMediumStreamHandler16
//
// Synopsis: Copies one stream to another
//
// Effects: Turns out that Excel does the wrong thing with STGMEDIUM's
// when its GetDataHere() method is called. Instead of using
// the provided stream, like it was supposed to, it creates its
// own stream, and smashes the passed in streams pointer. This
// appears to be happening on the Clipboard object for Excel.
// To fix this, the thop function for STGMEDIUM input is going to
// watch for changes to the stream pointer. If it changes, then
// the 'app' (excel) has done something wrong.
//
// To recover from this, the thop will call this routine passing
// the bogus stream and the stream that was supposed to be used.
// This routine will do a pstmFrom->CopyTo(pstmTo), and then
// release the 'bogus' stream pointer.
//
// Arguments: [pstmFrom] -- Stream to copy then release
// [pstmTo] -- Destination stream
//
// History: 7-07-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom, IStream FAR *pstmTo) { HRESULT hresult; LARGE_INTEGER li; ULARGE_INTEGER uli; ULONG ul;
thkDebugOut((DEB_ITRACE, "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p)\n", pstmFrom,pstmTo));
//
// Assume that the entire stream is the data set to be copied.
// Seek to the start of the stream
//
ULISet32(li,0); hresult = pstmFrom->Seek(li,STREAM_SEEK_SET,NULL); if (hresult != NOERROR) { thkDebugOut((DEB_ITRACE, "StgMediumStreamHandler16 failed on seek %lx\n",hresult)); goto exitRtn; }
//
// To copy the entire stream, specify the maximum size possible.
//
uli.LowPart = -1; uli.HighPart = -1; hresult = pstmFrom->CopyTo(pstmTo,uli,NULL,NULL); if (hresult != NOERROR) { thkDebugOut((DEB_ITRACE, "StgMediumStreamHandler16 failed CopyTo %lx\n",hresult)); goto exitRtn; }
exitRtn: //
// In all cases, it is proper to release the pstmFrom, since we didn't
// want it on the 32-bit side at all.
//
ul = pstmFrom->Release();
if (ul != 0) { //
// Whoops, we expected this stream pointer to go to zero. We can
// only print a message, then let it leak.
//
thkDebugOut((DEB_ITRACE, "StgMediumStreamHandler16() Stream not released. ref=%lx\n",ul)); }
thkDebugOut((DEB_ITRACE, "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p) returns %lx\n", pstmFrom,pstmTo,hresult));
return((DWORD)hresult);
}
//+---------------------------------------------------------------------------
//
// Function: TouchPointer16, public
//
// Synopsis: Touches a byte at the given pointer's address to
// bring in not-present segments
//
// Arguments: [pb] - Pointer
//
// History: 25-Apr-94 DrewB Created
//
//----------------------------------------------------------------------------
DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb) { BYTE b = 0;
if (pb) { b = *pb; }
#ifdef _CHICAGO_
// On Win95, fix the memory block before returning to 32-bit code
// to lock the segment in place. If we tried to do this in 32-bit
// code we could be preempted before we successfully lock the memory
GlobalFix(LOWORD(HIWORD((DWORD)pb))); #endif
return b; }
//+---------------------------------------------------------------------------
//
// Function: SetOwnerPublic16, public
//
// Synopsis: Sets a given 16-bit memory handle to be owned by nobody
// (everybody)
//
// Arguments: [hmem] - 16-bit memory handle
//
// History: 13-Jul-94 BobDay Created
//
//----------------------------------------------------------------------------
extern "C" void FAR PASCAL KERNEL_SetOwner( WORD hMem16, WORD wOwner );
DWORD __loadds FAR PASCAL SetOwnerPublic16(DWORD hmem) { KERNEL_SetOwner( (WORD)hmem, (WORD)-1 );
return 0; }
//+---------------------------------------------------------------------------
//
// Function: WinExec16, public
//
// Synopsis: Routine to run an application on behalf of ole32.dll
//
// Arguments: [lpwes] - WinExec16 struct full of needed goodies
//
// Returns:
//
// History: 27-Jul-94 AlexT Created
//
//----------------------------------------------------------------------------
ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes ) { ULONG ulResult;
thkDebugOut((DEB_ITRACE, "WinExec16(%s, %d)\n", lpwes->vpCommandLine, lpwes->vusShow));
ulResult = (ULONG) WinExec((LPSTR)lpwes->vpCommandLine, (UINT)lpwes->vusShow); thkDebugOut((DEB_ITRACE, "WinExec returned %ld\n", ulResult));
return ulResult; }
//+---------------------------------------------------------------------------
//
// Function: ConvertHr1632, public
//
// Synopsis: Converts a 16-bit HRESULT into a 32-bit HRESULT
//
// Arguments: [hr] - 16-bit HRESULT
//
// Returns: Appropriate status code
//
// History: 26-Sep-94 DrewB Created
//
// Notes: Delegates to 32-bit functions
//
//----------------------------------------------------------------------------
STDAPI ConvertHr1632(HRESULT hr) { return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0, pfnConvertHr1632, 0, CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Function: ConvertHr3216, public
//
// Synopsis: Converts a 32-bit HRESULT into a 16-bit HRESULT
//
// Arguments: [hr] - 32-bit HRESULT
//
// Returns: Appropriate status code
//
// History: 26-Sep-94 DrewB Created
//
// Notes: Delegates to 32-bit functions
//
//----------------------------------------------------------------------------
STDAPI ConvertHr3216(HRESULT hr) { return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0, pfnConvertHr3216, 0, CP32_NARGS); }
//+---------------------------------------------------------------------------
//
// Function: SSCallProc32, public
//
// Synopsis: Wrapper for CallProc32W which switches to a bigger stack
//
// Arguments: [dw1] - argumensts similar to CallProc32W
// [dw2]
// [dw3]
// [pfn32]
// [dwPtrTranslate]
// [dwArgCount]
//
// Returns: 32-bit call result
//
// History: 5-Dec-94 JohannP Created
//
// Note: this will be enabled as soon as I get the CallProc32WFix from
// Win95
//----------------------------------------------------------------------------
#ifdef _STACKSWITCHON16_
DWORD FAR PASCAL SSCallProc32(DWORD dw1, DWORD dw2, DWORD dw3, LPVOID pfn32, DWORD dwPtrTranslate, DWORD dwArgCount) { DWORD dwRet = 0; // switch to the 32 bit stack
//
// return SSCall(24,SSF_BigStack, (LPVOID)CallProc32W, dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount);
thkDebugOut((DEB_ERROR, "SSCallProc32(dwArgCount:%x, dwPtrTranslate:%x, pfn32:%x, dw3:%x, dw2:%x, dw1:%x)\n", dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1)); #if DBG == 1
if (fSSOn) { dwRet = SSCall(24,SSF_BigStack, (LPVOID)CallProc32WFix, dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1); } else #endif // DBG==1
{ dwRet = CallProc32W(dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount); }
return dwRet; } #endif // _STACKSWITCHON16_
//+-------------------------------------------------------------------------
//
// Function: AddAppCompatFlag
//
// Synopsis: calls into olethk32 to add an app compability flag.
//
// Effects:
//
// Arguments: [dwFlag] -- the flag to add
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 15-Mar-95 alexgo author
//
// Notes: this function is exported so that ole2.dll can also call it
//
//--------------------------------------------------------------------------
STDAPI_(void) AddAppCompatFlag( DWORD dwFlag ) { CallProcIn32( (DWORD)dwFlag, 0, 0, pfnThkAddAppCompatFlag, 0, CP32_NARGS); }
|