windows-nt/Source/XPSP1/NT/com/ole32/olethunk/olethk32/apinot.cxx

1035 lines
28 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1994.
//
// File: apinot.cxx
//
// Contents: Implementation of non-API thunks
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
#include "headers.cxx"
#pragma hdrstop
#include <thunkapi.hxx>
#include <wownt32.h>
#include "olethk32.hxx"
#include "apinot.hxx"
#include "tlsthk.hxx"
//
// The following is a global static used by OLE32 to call back into
// this DLL. There is no static data associated with the static, so
// it merely defines a virtual interface that OLE32 can use.
//
OleThunkWOW g_thkOleThunkWOW;
//
// The following API is exported from WOW32.DLL. There is no global include
// file that it exists in yet.
//
#if defined(_CHICAGO_)
/* Not supported under Chicago yet. */
/* But it's probably not important anymore. */
#define WOWFreeMetafile(x) (0)
#else
extern "C" BOOL WINAPI WOWFreeMetafile( HANDLE h32 );
#endif
//+---------------------------------------------------------------------------
//
// Function: CoInitializeNot, public
//
// Synopsis: Thunks for the 16-bit applications call to CoInitialize
//
// Arguments: [lpmalloc] - Parameter from the 16-bit world
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) CoInitializeNot( LPMALLOC lpMalloc )
{
HRESULT hresult;
hresult = CoInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
return (DWORD)hresult;
}
//+---------------------------------------------------------------------------
//
// Function: OleInitializeNot, public
//
// Synopsis: Thunks for the 16-bit applications call to OleInitialize
//
// Arguments: [lpmalloc] - Parameter from the 16-bit world
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) OleInitializeNot( LPMALLOC lpMalloc )
{
HRESULT hresult;
hresult = OleInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
return (DWORD)hresult;
}
//+---------------------------------------------------------------------------
//
// Function: RegisterDelayedClassFactories
//
// Synopsis: This function is called to actually do the registration of
// the delayed class factories.
//
// Effects: When the application specific 'trigger' is hit
// (ie OleRegGetUserType for WordPerfect), this routine is
// called to actually do all of the delayed class factory
// registrations.
//
// Arguments: (none)
//
// Requires:
//
// Returns: nothing
//
// History: 4-18-95 kevinro Created
//
//----------------------------------------------------------------------------
void RegisterDelayedClassFactories()
{
thkDebugOut((DEB_ITRACE,
"_IN RegisterDelayedClassFactories()\n"));
PThreadData pdata;
IUnknown *punk;
HRESULT hr;
DelayedRegistrationTable *pTable = NULL;
DelayRegistration *pdelayed;
DWORD dwReg;
int i;
//
// Get the thread specific data and table to determine if there are
// any delayed registrations. If not, just call the real routine.
//
pdata = TlsThkGetData();
if (pdata == NULL)
{
goto exitRtn;
}
if ((pTable = pdata->pDelayedRegs) == NULL)
{
goto exitRtn;
}
//
//
//
for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
{
pdelayed = &(pTable->_Entries[i]);
if((pdelayed->_punk != NULL) && (pdelayed->_dwRealKey == 0))
{
hr = CoRegisterClassObject(pdelayed->_clsid,
pdelayed->_punk,
pdelayed->_dwClsContext,
pdelayed->_flags,
&(pdelayed->_dwRealKey));
if (FAILED(hr))
{
thkDebugOut((DEB_ERROR,
"RegisterDelayedClassFactory gets %x\n",hr));
}
}
}
exitRtn:
thkDebugOut((DEB_ITRACE,
"OUT RegisterDelayedClassFactories()\n"));
}
//+---------------------------------------------------------------------------
//
// Function: CoRevokeClassObjectNot
//
// Synopsis: Unregisters a class object that might have been delayed
//
// Effects: The 16-bit API CoRevokeClassObject has been directed to this
// routine. This routine will check the list of interfaces that
// have been registered, and will try to determine if the key
// needs to be translated.
//
// Arguments: [dwKey] -- Key to revoke
//
// History: 4-18-95 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CoRevokeClassObjectNot( DWORD dwKey)
{
thkDebugOut((DEB_ITRACE,
"_IN CoRevokeClassObjectNot(dwKey = %x)\n",
dwKey));
PThreadData pdata;
IUnknown *punk;
HRESULT hr;
DelayedRegistrationTable *pTable = NULL;
DWORD dwReg = ~dwKey;
//
// Get the thread specific data and table to determine if there are
// any delayed registrations. If not, just call the real routine.
//
pdata = TlsThkGetData();
if (pdata == NULL)
{
goto exitRtn;
}
if ((pTable = pdata->pDelayedRegs) == NULL)
{
goto exitRtn;
}
//
// the 'fake' key is really the bitwise not of the index
//
if ( dwReg >= MAX_DELAYED_REGISTRATIONS)
{
goto exitRtn;
}
if(pTable->_Entries[dwReg]._punk != NULL)
{
punk = pTable->_Entries[dwReg]._punk;
pTable->_Entries[dwReg]._punk = NULL;
dwKey = pTable->_Entries[dwReg]._dwRealKey;
pTable->_Entries[dwReg]._dwRealKey = 0;
//
// The class object table normally does an addref on the class factory.
// We are also holding an addref on the punk. Release it.
//
if (punk != NULL)
{
punk->Release();
//
// If the real key is zero, then we never did actually finish
// the registration. In this case, we return S_OK, because we
// are faking the app out anyway. This might happen if the app
// decides to shutdown for some reason without triggering the
// operation that causes us to register its class objects
//
if (dwKey == 0)
{
hr = S_OK;
goto exitNow;
}
}
}
exitRtn:
hr = CoRevokeClassObject(dwKey);
exitNow:
thkDebugOut((DEB_ITRACE,"OUT CoRevokeClassObjectNot():%x\n",hr));
return(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CoRegisterClassObjectDelayed
//
// Synopsis: Delay the registration of class objects. Some applications,
// such as Word Perfect 6.1, register their class objects then
// do peek message operations BEFORE they are fully initialized.
// This causes problems because we can call in and do
// CreateInstance calls before they are ready for them. This
// wonderful hack will delay the registration of class objects
// until someone calls RegisterClassObjectsNow(), which is
// called when we know it is safe.
//
// Novell knows about this hack, and promised not to change
// the 16-bit code on us.
//
// Effects: Store all of the registration information in an array, and
// return a special key value.
//
//
// Arguments: ( Same as CoRegisterClassObject)
//
// Requires: The associated routine CoUnregisterClassObjectDelayed needs
// to be called in the CoRevokeClassObject path to check to see
// if the key being passed in is a special key. That way we
// can translate the key before calling the real routine.
//
// The special key value is not of the key
//
// Returns: S_OK or E_UNEXPECTED
//
// History: 4-14-95 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CoRegisterClassObjectDelayed( REFCLSID refclsid, LPUNKNOWN punk,
DWORD dwClsContext, DWORD flags, DWORD *pdwReg)
{
thkDebugOut((DEB_ITRACE,"_IN CoRegisterClassObjectDelayed\n"));
PThreadData pdata;
int i;
DelayedRegistrationTable *pTable = NULL;
//
// Assume this is going to fail
//
HRESULT hr = E_UNEXPECTED;
*pdwReg = 0;
pdata = TlsThkGetData();
if (pdata == NULL)
{
goto exitRtn;
}
if ((pTable = pdata->pDelayedRegs) == NULL)
{
pTable = pdata->pDelayedRegs = new DelayedRegistrationTable();
}
if (pTable != NULL)
{
for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
{
if(pTable->_Entries[i]._punk == NULL)
{
pTable->_Entries[i]._punk = punk;
pTable->_Entries[i]._clsid = refclsid;
pTable->_Entries[i]._dwClsContext = dwClsContext;
pTable->_Entries[i]._flags = flags;
//
// The class object table normally does an
// addref on the class factory. We will hang on to this
// to keep the class factory and the 3216 proxy alive
//
punk->AddRef();
*pdwReg = ~i;
hr = S_OK;
break;
}
}
}
exitRtn:
thkDebugOut((DEB_ITRACE,"OUT CoRegisterClassObjectDelayed() : %x\n",hr));
return(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CoRegisterClassObjectNot, public
//
// Synopsis: Thunks for the 16-bit applications call CoRegisterClassObject
// Here we check for the registered class objects to set the
// thread's compatability bits.
//
// Arguments: [refclsid] - CLSID for the class to register
// [punk] - ClassFactory interface
// [dwClsContext] - Class context
// [flags] - flags
// [lpdwreg] - register
//
// Returns: Appropriate status code
//
// History: 18-Jul-94 BobDay Created
//
//----------------------------------------------------------------------------
EXTERN_C const CLSID CDECL CLSID_EXCEL5_WORKSHEET =
{ 0x020810, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
EXTERN_C const CLSID CDECL CLSID_WORD6_DOCUMENT =
{ 0x020900, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
EXTERN_C const CLSID CDECL CLSID_WPWIN61 =
{ 0x89FE3FE3, 0x9FF6, 0x101B, {0xB6, 0x78, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02}};
EXTERN_C const CLSID CDECL CLSID_WPWIN61_FILE =
{ 0x1395F281, 0x4326, 0x101b, {0x8B, 0x9A, 0xCE, 0x29, 0x3E, 0xF3, 0x84, 0x49}};
EXTERN_C const CLSID CDECL CLSID_IKITARO_130 =
{ 0x02B501, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
DEFINE_OLEGUID(CLSID_EXCEL5_WORKSHEET, 0x20810, 0, 0);
STDAPI_(DWORD) CoRegisterClassObjectNot( REFCLSID refclsid, LPUNKNOWN punk,
DWORD dwClsContext, DWORD flags,
LPDWORD lpdwreg )
{
//
// Excel didn't AddRef the IOleObjectClientSite returned from
// the IOleObject::GetClientSite method.
//
if ( IsEqualCLSID(refclsid,CLSID_EXCEL5_WORKSHEET) )
{
DWORD dw;
dw = TlsThkGetAppCompatFlags();
TlsThkSetAppCompatFlags(dw | OACF_CLIENTSITE_REF);
thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_CLIENTSITE_REF enabled\n"));
}
//
// WinWord didn't call OleSetMenuDescriptor(NULL) during
// IOleInPlaceFrame::RemoveMenus. We do it for them.
//
// Also WinWord thinks GDI objects like palettes and bitmaps can be
// transferred on HGLOBALs during GetData calls. In order to thunk
// them properly, we need to patch up the STGMEDIUMS given to use
// by word. This is controlled by OACF_USEGDI.
//
// YAWC: Word chokes and dies because it fails to disconnect some of its
// objects. During shutdown of a link, for example, cleaning up the stdid
// table causes WORD to fault.
//
else if ( IsEqualCLSID(refclsid,CLSID_WORD6_DOCUMENT) )
{
DWORD dw;
dw = TlsThkGetAppCompatFlags();
TlsThkSetAppCompatFlags(dw | OACF_RESETMENU | OACF_USEGDI | OACF_NO_UNINIT_CLEANUP);
thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_RESETMENU enabled\n"));
thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_USEGDI enabled\n"));
thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_NO_UNINIT_CLEANUP enabled\n"));
}
else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61) )
{
thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61)\n"));
return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
}
else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61_FILE) )
{
thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61_FILE)\n"));
return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
}
else if ( IsEqualCLSID(refclsid,CLSID_IKITARO_130) )
{
// Note: Ikitaro queries for IViewObject and uses it as IViewObject2
DWORD dw = TlsThkGetAppCompatFlags();
thkDebugOut((DEB_WARN,"Ikitaro hack triggered\n"));
TlsThkSetAppCompatFlags(dw | OACF_IVIEWOBJECT2);
}
return (DWORD)CoRegisterClassObject( refclsid, punk, dwClsContext,
flags, lpdwreg );
}
//+---------------------------------------------------------------------------
//
// Function: OleRegGetUserTypeNot
//
// Synopsis: Adds a hook for a WordPerfect hack. Check out the functions
// CoRegisterClassObjectDelayed and
// RegisterDelayedClassFactories for details. In essence, when
// this function is called for the WPWIN61 classID, we know
// that it is safe to register all of the delayed class objects.
// This determination was done by debugging Wordperfect. When
// they call this API, then are actually done initializing the
// internals of their app.
//
// Effects:
//
// History: 4-18-95 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI_(DWORD)
OleRegGetUserTypeNot(REFCLSID clsid,DWORD dwFormOfType,LPOLESTR *pszUserType)
{
//
// Wordperfect has a bug. When they call OleRegGetUserType for their
// classid, we know that it is safe to register their class objects for
// real.
//
// See CoRegisterClassObjectDelayed for details
//
if ( IsEqualCLSID(clsid,CLSID_WPWIN61) )
{
thkDebugOut((DEB_WARN,"Registering WordPerfects class objects\n"));
RegisterDelayedClassFactories();
}
return OleRegGetUserType(clsid,dwFormOfType,pszUserType);
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::LoadProcDll, public
//
// Synopsis: Callback function for 32-bit OLE to load a 16-bit DLL
//
// Arguments: [pszDllName] - Name of 16-bit DLL
// [lpvpfnGetClassObject] - returned 16:16 address of
// "DllGetClassObject"
// [lpvpfnCanUnloadNow] - returned 16:16 address of
// "DllCanUnloadNow"
// [lpvhmodule] - returned 16-bit hmodule
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
OleThunkWOW::LoadProcDll(
LPCTSTR pszDllName,
LPDWORD lpvpfnGetClassObject,
LPDWORD lpvpfnCanUnloadNow,
LPDWORD lpvhmodule
)
{
HRESULT hr;
UINT uiSize;
VPSTR vpstr16;
VPVOID vplpds16;
LOADPROCDLLSTRUCT UNALIGNED *lplpds16;
char string[256];
// Ensure that Interop is enabled
Win4Assert(gfIteropEnabled);
// Ensure that callbacks are allowed on this thread
Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
uiSize = lstrlen(pszDllName) + 1;
vpstr16 = STACKALLOC16(uiSize*sizeof(TCHAR));
if (vpstr16 == 0)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
#ifndef _CHICAGO_
hr = Convert_LPOLESTR_to_VPSTR(pszDllName, vpstr16,
uiSize, uiSize*sizeof(TCHAR));
#else
hr = Convert_LPSTR_to_VPSTR(pszDllName, vpstr16,
uiSize, uiSize*sizeof(TCHAR));
#endif
if (FAILED(hr))
{
goto EH_vpstr16;
}
vplpds16 = STACKALLOC16(sizeof(LOADPROCDLLSTRUCT));
if (vplpds16 == 0)
{
hr = E_OUTOFMEMORY;
goto EH_vpstr16;
}
lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
lplpds16->vpDllName = vpstr16;
lplpds16->vpfnGetClassObject = 0;
lplpds16->vpfnCanUnloadNow = 0;
lplpds16->vhmodule = 0;
RELVDMPTR(vplpds16);
hr = CallbackTo16( gdata16Data.fnLoadProcDll, vplpds16 );
if (SUCCEEDED(hr))
{
lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
*lpvpfnGetClassObject = lplpds16->vpfnGetClassObject;
*lpvpfnCanUnloadNow = lplpds16->vpfnCanUnloadNow;
*lpvhmodule = lplpds16->vhmodule;
RELVDMPTR(vplpds16);
#ifdef _CHICAGO_
thkDebugOut((DEB_WARN, "Loaded COM DLL: %s with HMODULE: 0x%x\n",
pszDllName, *lpvhmodule));
#else
thkDebugOut((DEB_WARN, "Loaded COM DLL: %ws with HMODULE: 0x%x\n",
pszDllName, *lpvhmodule));
#endif
}
else
{
hr = CO_E_DLLNOTFOUND;
}
STACKFREE16(vplpds16, sizeof(LOADPROCDLLSTRUCT));
EH_vpstr16:
STACKFREE16(vpstr16,uiSize*sizeof(TCHAR));
Exit:
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::UnloadProcDll, public
//
// Synopsis: Callback function for 32-bit OLE to unload a 16-bit DLL
//
// Arguments: [vhmodule] - 16-bit hmodule
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
OleThunkWOW::UnloadProcDll(
HMODULE vhmodule
)
{
HRESULT hr = S_OK;
// Ensure that Interop is enabled and callbacks are
// not allowed on this thread
if(gfIteropEnabled && TlsThkGetThkMgr()->AreCallbacksAllowed())
hr = CallbackTo16(gdata16Data.fnUnloadProcDll, HandleToUlong(vhmodule));
return(hr);
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::CallGetClassObject, public
//
// Synopsis: Callback function for 32-bit OLE to call 16-bit
// DllGetClassObject
//
// Arguments: [vpfnGetClassObject] - 16:16 address of DllGetClassObject
// [rclsid] - CLSID of object
// [riid] - IID of interface on object
// [ppv] - returned object interface
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
OleThunkWOW::CallGetClassObject(
DWORD vpfnGetClassObject,
REFCLSID rclsid,
REFIID riid,
LPVOID FAR *ppv
)
{
DWORD dwResult;
VPVOID vpcgcos16;
CALLGETCLASSOBJECTSTRUCT UNALIGNED *lpcgcos16;
VPVOID iface16;
IIDIDX iidx;
IUnknown *punkThis32;
CThkMgr *pThkMgr;
ThreadData *ptd;
// Ensure that Interop is enabled
Win4Assert(gfIteropEnabled);
// Ensure that callbacks are allowed on this thread
Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
ptd = TlsThkGetData();
if (ptd == NULL)
{
thkDebugOut((DEB_WARN, "WARNING: CallGetClassObject refused\n"));
dwResult = (DWORD)E_FAIL;
goto Exit;
}
pThkMgr = ptd->pCThkMgr;
vpcgcos16 = STACKALLOC16(sizeof(CALLGETCLASSOBJECTSTRUCT));
if (vpcgcos16 == 0)
{
dwResult = (DWORD)E_OUTOFMEMORY;
goto Exit;
}
lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
lpcgcos16->vpfnGetClassObject = vpfnGetClassObject;
lpcgcos16->clsid = rclsid;
lpcgcos16->iid = riid;
lpcgcos16->iface = 0;
RELVDMPTR(vpcgcos16);
dwResult = CallbackTo16( gdata16Data.fnCallGetClassObject, vpcgcos16 );
if ( SUCCEEDED(dwResult) )
{
lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
iface16 = lpcgcos16->iface;
iidx = IidToIidIdx(riid);
// We're on the way out creating a proxy so set the state
// appropriately
pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
// Get a 32-bit proxy object for the 16-bit object
punkThis32 = pThkMgr->FindProxy3216(NULL, iface16, NULL, iidx, FALSE, NULL);
pThkMgr->SetThkState(THKSTATE_NOCALL);
// Set the out param
*(IUnknown **)ppv = punkThis32;
// As this is an OUT parameter, release the actual 16-bit interface
// This could be the last release on the 16-bit interface, if the
// proxy was not successfully created
ReleaseOnObj16(iface16);
if(punkThis32 == NULL) {
dwResult = (DWORD)E_OUTOFMEMORY;
}
RELVDMPTR(vpcgcos16);
}
else { // need to map dwResult only for failure cases (see hmMappings)
dwResult = TransformHRESULT_1632( dwResult );
}
STACKFREE16(vpcgcos16, sizeof(CALLGETCLASSOBJECTSTRUCT));
Exit:
return dwResult;
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::CallCanUnloadNow, public
//
// Synopsis: Callback function for 32-bit OLE to call 16-bit
// CanUnloadNow
//
// Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow
//
// Returns: Appropriate status code
//
// History: 11-Mar-94 BobDay Created
//
//----------------------------------------------------------------------------
STDMETHODIMP OleThunkWOW::CallCanUnloadNow(
DWORD vpfnCanUnloadNow)
{
HRESULT hr = S_OK;
// Ensure that Interop is enabled and callbacks are
// not allowed on this thread
if(gfIteropEnabled && TlsThkGetThkMgr()->AreCallbacksAllowed())
hr = CallbackTo16(gdata16Data.fnCallCanUnloadNow, vpfnCanUnloadNow);
return(hr);
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::GetThunkManager, public
//
// Synopsis: Callback function for 32-bit OLE to retrieve the thunkmanager
//
// Arguments: [ppThkMgr] - Thunk manager return
//
// Returns: Appropriate status code
//
// History: 11-May-94 JohannP Created
//
//----------------------------------------------------------------------------
STDMETHODIMP OleThunkWOW::GetThunkManager(IThunkManager **ppThkMgr)
{
thkDebugOut((DEB_THUNKMGR, "%sIn OleThunkWOW::GetThunkManager\n",
NestingLevelString()));
thkAssert(ppThkMgr != NULL);
IUnknown *pUnk = TlsThkGetThkMgr();
thkAssert(pUnk && "Invalid Thunkmanager");
*ppThkMgr = (IThunkManager *)pUnk;
pUnk->AddRef();
thkDebugOut((DEB_THUNKMGR, "%sOut OleThunkWOW::GetThunkManager: (%p)\n",
NestingLevelString(), pUnk));
return NOERROR;
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::WinExec16, public
//
// Synopsis: Callback function for 32-bit OLE to run an application
//
// Arguments: [pszCommandLine] - command line for WinExec
// [usShow] - fShow for WinExec
//
// Returns: Appropriate status code
//
// History: 27-Jul-94 AlexT Created
//
//----------------------------------------------------------------------------
STDMETHODIMP OleThunkWOW::WinExec16(
LPCOLESTR pszCommandLine,
USHORT usShow
)
{
HRESULT hr;
UINT uiSize;
VPSTR vpstr16;
VPVOID vplpds16;
WINEXEC16STRUCT UNALIGNED *lpwes16;
ULONG ulRet;
// Ensure that Interop is enabled
Win4Assert(gfIteropEnabled);
// Ensure that callbacks are allowed on this thread
Win4Assert(TlsThkGetThkMgr()->AreCallbacksAllowed());
uiSize = lstrlenW(pszCommandLine) + 1;
vpstr16 = STACKALLOC16(uiSize*2);
if (vpstr16 == 0)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = Convert_LPOLESTR_to_VPSTR(pszCommandLine, vpstr16,
uiSize, uiSize*2);
if (FAILED(hr))
{
goto EH_vpstr16;
}
vplpds16 = STACKALLOC16(sizeof(WINEXEC16STRUCT));
if (vplpds16 == 0)
{
hr = E_OUTOFMEMORY;
goto EH_vpstr16;
}
lpwes16 = FIXVDMPTR(vplpds16, WINEXEC16STRUCT);
lpwes16->vpCommandLine = vpstr16;
lpwes16->vusShow = usShow;
RELVDMPTR(vplpds16);
ulRet = CallbackTo16( gdata16Data.fnWinExec16, vplpds16 );
thkDebugOut((DEB_ITRACE,
"CallbackTo16(WinExec16) returned %ld\n", ulRet));
// According to the Windows spec, return values greater than 31 indicate
// success.
if (ulRet > 31)
{
hr = S_OK;
}
else if (0 == ulRet)
{
// 0 indicates lack of some kind of resource
hr = E_OUTOFMEMORY;
}
else
{
hr = HRESULT_FROM_WIN32(ulRet);
}
STACKFREE16(vplpds16, sizeof(WINEXEC16STRUCT));
EH_vpstr16:
STACKFREE16(vpstr16, uiSize*2);
Exit:
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: OleThunkWOW::ConvertHwndToFullHwnd
//
// Synopsis: Converts a 16 bit HWND into a 32-bit HWND
//
// Effects: Since OLE32 doesn't directly link to WOW, this function allows
// the DDE layer to access the routine that maps 16 bit HWND to
// full 32-bit HWND's.
//
// Arguments: [hwnd] -- HWND to convert
//
// History: 8-03-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(HWND) OleThunkWOW::ConvertHwndToFullHwnd(HWND hwnd)
{
return(FULLHWND_32((USHORT)hwnd));
}
//+---------------------------------------------------------------------------
//
// Method: OleThunkWOW::FreeMetaFile
//
// Synopsis: Calls wow to delete a metafile that has memory reserved in
// the 16 bit address space
//
// Effects: Since OLE32 doesn't directly link to WOW, this function allows
// the DDE layer to access the routine in WOW
//
// Arguments: [hmf] -- HANDLE to delete
//
// History: 8-03-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(BOOL) OleThunkWOW::FreeMetaFile(HANDLE hmf)
{
return(WOWFreeMetafile(hmf));
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::YieldTask16, public
//
// Synopsis: Callback function for 32-bit OLE to yield
//
// History: 08-Aug-94 Ricksa Created
//
//----------------------------------------------------------------------------
STDMETHODIMP OleThunkWOW::YieldTask16(void)
{
WOWYield16();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: OleThunkWOW::DirectedYield, public
//
// Synopsis: Does a directed yield in the VDM.
//
// History: 08-Aug-94 Rickhi Created
//
//----------------------------------------------------------------------------
STDMETHODIMP OleThunkWOW::DirectedYield(DWORD dwCalleeTID)
{
WORD hTask16 = WOWHandle16((void *)dwCalleeTID, WOW_TYPE_HTASK);
thkDebugOut((DEB_ITRACE, "WOWDirectedYield16(%x)\n", hTask16));
WOWDirectedYield16(hTask16);
thkDebugOut((DEB_ITRACE, "WOWDirectedYield16() returned\n"));
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Method: OleThunkWOW::PrepareForCleanup
//
// Synopsis: Prepares OLETHK32 for OLE32.DLL's cleanup.
//
// Effects: It does this by taking all of the remaining 3216 proxies
// and marking them such that no callbacks into the 16-bit
// world are possible.
//
// Arguments: -none-
//
// History: 24-Aug-94 bobday Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(void) OleThunkWOW::PrepareForCleanup(void)
{
CThkMgr *pcthkmgr;
if ( TlsThkGetData() != NULL )
{
pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
//
// Tell the thkmgr to prepare for cleaning itself up
//
pcthkmgr->PrepareForCleanup();
}
}
//+---------------------------------------------------------------------------
//
// Method: OleThunkWOW::GetAppCompatibilityFlags
//
// Synopsis: Used to return the current THK app compatibility flags to
// OLE32.DLL
// Arguments: [void] --
//
// Requires:
//
// Returns: Flags defined in ih\thunkapi.hxx
//
// History: 1-11-96 kevinro Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(DWORD) OleThunkWOW::GetAppCompatibilityFlags(void)
{
return(TlsThkGetAppCompatFlags());
}