summaryrefslogtreecommitdiffstats
path: root/private/ole32/olethunk/olethk32
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole32/olethunk/olethk32
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ole32/olethunk/olethk32')
-rw-r--r--private/ole32/olethunk/olethk32/alias.cxx405
-rw-r--r--private/ole32/olethunk/olethk32/alias.hxx163
-rw-r--r--private/ole32/olethunk/olethk32/apinot.cxx990
-rw-r--r--private/ole32/olethunk/olethk32/apinot.hxx25
-rw-r--r--private/ole32/olethunk/olethk32/cthkmgr.cxx3031
-rw-r--r--private/ole32/olethunk/olethk32/cthkmgr.hxx243
-rw-r--r--private/ole32/olethunk/olethk32/daytona/makefile6
-rw-r--r--private/ole32/olethunk/olethk32/daytona/olethk32.def27
-rw-r--r--private/ole32/olethunk/olethk32/daytona/sources103
-rw-r--r--private/ole32/olethunk/olethk32/dbgapi.cxx127
-rw-r--r--private/ole32/olethunk/olethk32/dbgint.cxx682
-rw-r--r--private/ole32/olethunk/olethk32/dbginv.hxx26
-rw-r--r--private/ole32/olethunk/olethk32/dbgitbl.cxx82
-rw-r--r--private/ole32/olethunk/olethk32/dirs40
-rw-r--r--private/ole32/olethunk/olethk32/dllentry.cxx56
-rw-r--r--private/ole32/olethunk/olethk32/fntomthd.cxx2082
-rw-r--r--private/ole32/olethunk/olethk32/freelist.cxx468
-rw-r--r--private/ole32/olethunk/olethk32/freelist.hxx65
-rw-r--r--private/ole32/olethunk/olethk32/headers.cxx59
-rw-r--r--private/ole32/olethunk/olethk32/heap.cxx63
-rw-r--r--private/ole32/olethunk/olethk32/ichannel.cxx49
-rw-r--r--private/ole32/olethunk/olethk32/iidtothi.cxx79
-rw-r--r--private/ole32/olethunk/olethk32/inv16.cxx608
-rw-r--r--private/ole32/olethunk/olethk32/inv16.hxx21
-rw-r--r--private/ole32/olethunk/olethk32/inv32.cxx496
-rw-r--r--private/ole32/olethunk/olethk32/map_dwp.h66
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.cxx540
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.h116
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.hxx114
-rw-r--r--private/ole32/olethunk/olethk32/mmodel.cxx232
-rw-r--r--private/ole32/olethunk/olethk32/mmodel.hxx88
-rw-r--r--private/ole32/olethunk/olethk32/nest.hxx32
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.cxx616
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.hxx31
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.rc14
-rw-r--r--private/ole32/olethunk/olethk32/plex.cxx45
-rw-r--r--private/ole32/olethunk/olethk32/plex.h30
-rw-r--r--private/ole32/olethunk/olethk32/stalloc.cxx397
-rw-r--r--private/ole32/olethunk/olethk32/stalloc.hxx113
-rw-r--r--private/ole32/olethunk/olethk32/struct16.hxx91
-rw-r--r--private/ole32/olethunk/olethk32/tc1632.cxx323
-rw-r--r--private/ole32/olethunk/olethk32/the.hxx21
-rw-r--r--private/ole32/olethunk/olethk32/thi.hxx73
-rw-r--r--private/ole32/olethunk/olethk32/thkmgr.cxx536
-rw-r--r--private/ole32/olethunk/olethk32/thkmgr.hxx40
-rw-r--r--private/ole32/olethunk/olethk32/thop.hxx241
-rw-r--r--private/ole32/olethunk/olethk32/thop16.cxx4114
-rw-r--r--private/ole32/olethunk/olethk32/thop32.cxx3959
-rw-r--r--private/ole32/olethunk/olethk32/thopapi.hxx37
-rw-r--r--private/ole32/olethunk/olethk32/thopiint.cxx83
-rw-r--r--private/ole32/olethunk/olethk32/thopint.hxx39
-rw-r--r--private/ole32/olethunk/olethk32/thopsapi.cxx427
-rw-r--r--private/ole32/olethunk/olethk32/thopsint.cxx1313
-rw-r--r--private/ole32/olethunk/olethk32/thoputil.cxx4547
-rw-r--r--private/ole32/olethunk/olethk32/thoputil.hxx216
-rw-r--r--private/ole32/olethunk/olethk32/thtblapi.cxx125
-rw-r--r--private/ole32/olethunk/olethk32/thtblint.cxx508
-rw-r--r--private/ole32/olethunk/olethk32/tlsthk.cxx171
-rw-r--r--private/ole32/olethunk/olethk32/tlsthk.hxx85
-rw-r--r--private/ole32/olethunk/olethk32/vtblapi.cxx123
-rw-r--r--private/ole32/olethunk/olethk32/vtblifn.cxx766
-rw-r--r--private/ole32/olethunk/olethk32/vtblint.cxx678
62 files changed, 30946 insertions, 0 deletions
diff --git a/private/ole32/olethunk/olethk32/alias.cxx b/private/ole32/olethunk/olethk32/alias.cxx
new file mode 100644
index 000000000..0f60dd989
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/alias.cxx
@@ -0,0 +1,405 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: alias.cxx
+//
+// Contents: Alias implementations
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::CAliasBlock, public
+//
+// Synopsis: Constructor
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CAliasBlock::CAliasBlock(ALIAS aliasBase,
+ CAliasBlock *pabNext)
+{
+ _aliasBase = aliasBase;
+ _iFilled = 0;
+ _pabNext = pabNext;
+
+ // Since INVALID_VALUE is a DWORD we can't directly memset it,
+ // but we'd like to use memset so assert that it's a known value
+ // and go ahead
+ thkAssert(INVALID_VALUE == 0);
+ memset(_dwValues, 0, sizeof(_dwValues));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::ValueAlias, public
+//
+// Synopsis: Find the alias for a value
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliasBlock::ValueAlias(DWORD dwValue)
+{
+ int i;
+ DWORD *pdw;
+
+ thkAssert(dwValue != INVALID_VALUE);
+
+#if DBG == 1
+ CheckFree();
+#endif
+
+ if (_iFilled == 0)
+ {
+ return INVALID_ALIAS;
+ }
+
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw == dwValue)
+ {
+ return IndexAlias(i);
+ }
+
+ pdw++;
+ }
+
+ return INVALID_ALIAS;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::AddValue, public
+//
+// Synopsis: Adds a new value
+//
+// Arguments: [dwValue] - New value
+//
+// Returns: Alias for block or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Duplicates are not allowed
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliasBlock::AddValue(DWORD dwValue)
+{
+ int i;
+ DWORD *pdw;
+
+ thkAssert(dwValue != INVALID_VALUE);
+
+#if DBG == 1
+ CheckFree();
+#endif
+
+ if (_iFilled == ALIAS_BLOCK_SIZE)
+ {
+ return INVALID_ALIAS;
+ }
+
+ // Check for duplicates
+ thkAssert(ValueAlias(dwValue) == INVALID_ALIAS);
+
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw == INVALID_VALUE)
+ {
+ break;
+ }
+
+ pdw++;
+ }
+
+ thkAssert(i < ALIAS_BLOCK_SIZE);
+
+ _iFilled++;
+ _dwValues[i] = dwValue;
+
+ return IndexAlias(i);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::CheckFree, public debug
+//
+// Synopsis: Checks to make sure that _iFilled is correct
+//
+// History: 30-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CAliasBlock::CheckFree(void)
+{
+ int i, iFilled;
+ DWORD *pdw;
+
+ iFilled = 0;
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw != INVALID_VALUE)
+ {
+ iFilled++;
+ }
+
+ pdw++;
+ }
+
+ thkAssert(iFilled == _iFilled);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::~CAliases, public
+//
+// Synopsis: Destructor
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CAliases::~CAliases(void)
+{
+ CAliasBlock *pab;
+
+ while (_pabAliases)
+ {
+ pab = _pabAliases->GetNext();
+ //
+ // The first alias block added to the list is a static one. We
+ // cannot call the heap to deallocate it.
+ //
+ if (_pabAliases != &_abStatic)
+ {
+ delete _pabAliases;
+ }
+
+ _pabAliases = pab;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliases::AliasValue, public
+//
+// Synopsis: Returns the value for an alias
+//
+// Arguments: [alias] - Alias
+//
+// Returns: Value
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Alias must be valid
+//
+//----------------------------------------------------------------------------
+
+DWORD CAliases::AliasValue(ALIAS alias)
+{
+ CAliasBlock *pab;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ return pab->AliasValue(alias);
+ }
+ }
+
+ thkAssert(!"Invalid alias in CAliases::AliasValue");
+
+ return 0xffffffff;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::ValueAlias, public
+//
+// Synopsis: Returns the alias for a value
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliases::ValueAlias(DWORD dwValue)
+{
+ CAliasBlock *pab;
+ ALIAS alias;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ alias = pab->ValueAlias(dwValue);
+ if (alias != INVALID_ALIAS)
+ {
+ return alias;
+ }
+ }
+
+ return INVALID_ALIAS;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::AddValue, public
+//
+// Synopsis: Adds a value and returns its alias
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliases::AddValue(DWORD dwValue)
+{
+ CAliasBlock *pab;
+ ALIAS alias;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ alias = pab->AddValue(dwValue);
+ if (alias != INVALID_ALIAS)
+ {
+ return alias;
+ }
+ }
+
+ if ((long)_aliasBase+ALIAS_BLOCK_SIZE >= INVALID_ALIAS)
+ {
+ return INVALID_ALIAS;
+ }
+
+ pab = new CAliasBlock(_aliasBase+ALIAS_BLOCK_SIZE, _pabAliases);
+ if (pab == NULL)
+ {
+ return INVALID_ALIAS;
+ }
+
+ _aliasBase += ALIAS_BLOCK_SIZE;
+ _pabAliases = pab;
+
+ alias = pab->AddValue(dwValue);
+
+ thkAssert(alias != INVALID_ALIAS);
+
+ return alias;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::RemoveAlias, public
+//
+// Synopsis: Removes an alias
+//
+// Arguments: [alias] - Alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::RemoveAlias(ALIAS alias)
+{
+ CAliasBlock *pab, *pabPrev;
+
+ pabPrev = NULL;
+ for (pab = _pabAliases; pab; pabPrev = pab, pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ pab->RemoveAlias(alias);
+
+ if (pab->AliasesFilled() == 0)
+ {
+ DeleteBlock(pab, pabPrev);
+ }
+
+ return;
+ }
+ }
+
+ thkAssert(!"Invalid alias in CAliases::RemoveAlias");
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::SetValue, public
+//
+// Synopsis: Sets the value for an alias
+//
+// Arguments: [alias] - Alias
+// [dwValue] - Value
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::SetValue(ALIAS alias, DWORD dwValue)
+{
+ CAliasBlock *pab;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ pab->SetValue(alias, dwValue);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliases::DeleteBlock, private
+//
+// Synopsis: Deletes an alias block if it's not the static block
+//
+// Arguments: [pab] - Alias block
+// [pabPrev] - Previous alias block
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::DeleteBlock(CAliasBlock *pab, CAliasBlock *pabPrev)
+{
+ if (pab == &_abStatic)
+ {
+ return;
+ }
+
+ if (pabPrev)
+ {
+ pabPrev->SetNext(pab->GetNext());
+ }
+ else
+ {
+ _pabAliases = pab->GetNext();
+ }
+
+ delete pab;
+}
diff --git a/private/ole32/olethunk/olethk32/alias.hxx b/private/ole32/olethunk/olethk32/alias.hxx
new file mode 100644
index 000000000..0718e84b9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/alias.hxx
@@ -0,0 +1,163 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: alias.hxx
+//
+// Classes: CAliasBlock
+// CAliases
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ALIAS_HXX__
+#define __ALIAS_HXX__
+
+// Number of alias slots to allocate in a chunk
+#define ALIAS_BLOCK_SIZE 64
+
+typedef WORD ALIAS;
+#define INVALID_ALIAS ((ALIAS)0xffff)
+
+// Aliases should not be zero because this causes error detection problems
+#define INITIAL_ALIAS ((ALIAS)1)
+
+// Values cannot be zero, this allows us to detect free slots in the
+// value array
+#define INVALID_VALUE ((DWORD)0)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAliasBlock (ab)
+//
+// Purpose: A block of values indexed by alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CAliasBlock
+{
+public:
+ CAliasBlock(ALIAS aliasBase,
+ CAliasBlock *pabNext);
+
+ BOOL ContainsAlias(ALIAS alias)
+ {
+ return alias >= _aliasBase && alias < _aliasBase+ALIAS_BLOCK_SIZE;
+ }
+ DWORD AliasValue(ALIAS alias)
+ {
+ thkAssert(!IsFree(alias));
+
+ return _dwValues[AliasIndex(alias)];
+ }
+ void RemoveAlias(ALIAS alias)
+ {
+ thkAssert(!IsFree(alias));
+#if DBG == 1
+ CheckFree();
+#endif
+ thkAssert(_iFilled > 0);
+
+ _iFilled--;
+ _dwValues[AliasIndex(alias)] = INVALID_VALUE;
+ }
+ void SetValue(ALIAS alias, DWORD dwValue)
+ {
+ thkAssert(!IsFree(alias));
+ thkAssert(dwValue != INVALID_VALUE);
+
+ _dwValues[AliasIndex(alias)] = dwValue;
+ }
+
+ ALIAS ValueAlias(DWORD dwValue);
+ ALIAS AddValue(DWORD dwValue);
+
+ CAliasBlock *GetNext(void)
+ {
+ return _pabNext;
+ }
+ void SetNext(CAliasBlock *pab)
+ {
+ _pabNext = pab;
+ }
+ int AliasesFilled(void)
+ {
+ return _iFilled;
+ }
+
+#if DBG == 1
+ BOOL IsFree(ALIAS alias)
+ {
+ return _dwValues[AliasIndex(alias)] == INVALID_VALUE;
+ }
+#endif
+
+private:
+ int AliasIndex(ALIAS alias)
+ {
+ thkAssert(ContainsAlias(alias));
+
+ return (int)(alias-_aliasBase);
+ }
+ ALIAS IndexAlias(int iIndex)
+ {
+ thkAssert(iIndex >= 0 && iIndex < ALIAS_BLOCK_SIZE);
+
+ return (ALIAS)(iIndex+_aliasBase);
+ }
+
+#if DBG == 1
+ void CheckFree(void);
+#endif
+
+ ALIAS _aliasBase;
+ int _iFilled;
+ DWORD _dwValues[ALIAS_BLOCK_SIZE];
+ CAliasBlock *_pabNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAliases (aliases)
+//
+// Purpose: Maintains a set of aliases for values
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Values must be unique
+//
+//----------------------------------------------------------------------------
+
+class CAliases
+{
+public:
+ CAliases(void)
+ : _abStatic(INITIAL_ALIAS, NULL)
+ {
+ // Start alias list with the static block
+ _pabAliases = &_abStatic;
+
+ // The static block takes the first block of aliases
+ _aliasBase = INITIAL_ALIAS+ALIAS_BLOCK_SIZE;
+ }
+ ~CAliases(void);
+
+ DWORD AliasValue(ALIAS alias);
+ ALIAS ValueAlias(DWORD dwValue);
+ ALIAS AddValue(DWORD dwValue);
+ void RemoveAlias(ALIAS alias);
+ void SetValue(ALIAS alias, DWORD dwValue);
+
+private:
+ void DeleteBlock(CAliasBlock *pab, CAliasBlock *pabPrev);
+
+ CAliasBlock _abStatic;
+ CAliasBlock *_pabAliases;
+ ALIAS _aliasBase;
+};
+
+#endif // #ifndef __ALIAS_HXX__
diff --git a/private/ole32/olethunk/olethk32/apinot.cxx b/private/ole32/olethunk/olethk32/apinot.cxx
new file mode 100644
index 000000000..de850d67e
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/apinot.cxx
@@ -0,0 +1,990 @@
+//+---------------------------------------------------------------------------
+//
+// 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_)
+#define WOWFreeMetafile(x) (0) /* BUGBUGCHICAGO - Not supported under Chicago yet. */
+#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;
+
+ 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);
+ }
+ 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(
+ DWORD vhmodule
+)
+{
+ return CallbackTo16( gdata16Data.fnUnloadProcDll, vhmodule );
+}
+
+//+---------------------------------------------------------------------------
+//
+// 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;
+
+ 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, iidx, NULL);
+
+ pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ // Set the out param
+ *(IUnknown **)ppv = punkThis32;
+
+ if (punkThis32 == NULL)
+ {
+ // Release the class object we just retrieved
+ ReleaseOnObj16(iface16);
+
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+
+ RELVDMPTR(vpcgcos16);
+ }
+
+ 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)
+{
+ return CallbackTo16( gdata16Data.fnCallCanUnloadNow, vpfnCanUnloadNow );
+}
+
+//+---------------------------------------------------------------------------
+//
+// 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;
+
+ 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());
+}
diff --git a/private/ole32/olethunk/olethk32/apinot.hxx b/private/ole32/olethunk/olethk32/apinot.hxx
new file mode 100644
index 000000000..be02e1e45
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/apinot.hxx
@@ -0,0 +1,25 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: apinot.hxx
+//
+// Contents: Function header for thunks which are not direct APIs
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __APINOT_HXX__
+#define __APINOT_HXX__
+
+STDAPI_(DWORD) OleRegGetUserTypeNot(REFCLSID clsid,DWORD dwFormOfType,LPOLESTR *pszUserType);
+STDAPI_(DWORD) CoInitializeNot( LPMALLOC lpMalloc );
+STDAPI_(DWORD) OleInitializeNot( LPMALLOC lpMalloc );
+STDAPI_(DWORD) CoRegisterClassObjectNot( REFCLSID refclsid, LPUNKNOWN punk,
+ DWORD dwClsContext, DWORD flags,
+ LPDWORD lpdwreg );
+STDAPI CoRevokeClassObjectNot( DWORD dwKey );
+
+#endif // #ifndef __APINOT_HXX__
diff --git a/private/ole32/olethunk/olethk32/cthkmgr.cxx b/private/ole32/olethunk/olethk32/cthkmgr.cxx
new file mode 100644
index 000000000..1753c56c4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/cthkmgr.cxx
@@ -0,0 +1,3031 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cthkmgr.cxx
+//
+// Contents: cthunkmanager for an apartment
+//
+// Classes: CThkMgr derived from IThunkManager
+//
+// Functions:
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include "headers.cxx"
+#pragma hdrstop
+#include <olepfn.hxx>
+#if DBG == 1
+BOOL fDebugDump = FALSE;
+#define DBG_DUMP(x) if (fDebugDump) { x; }
+#else
+#define DBG_DUMP(x)
+#endif
+
+#define PprxNull(pprx) ((pprx).dwPtrVal = 0)
+#define PprxIsNull(pprx) ((pprx).dwPtrVal == 0)
+#define Pprx16(vpv) PROXYPTR((DWORD)vpv, PPRX_16)
+#define Pprx32(pto) PROXYPTR((DWORD)pto, PPRX_32)
+
+//+---------------------------------------------------------------------------
+//
+// Function: ResolvePprx, public
+//
+// Synopsis: Converts a PROXYPTR to a CProxy *
+//
+// Arguments: [ppprx] - PROXYPTR
+//
+// Returns: Pointer or NULL
+//
+// History: 15-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CProxy *ResolvePprx(PROXYPTR *ppprx)
+{
+ if (ppprx->wType == PPRX_32)
+ {
+ return (CProxy *)ppprx->dwPtrVal;
+ }
+ else
+ {
+ // Get a pointer to all of the proxy rather than just the CProxy part
+ return FIXVDMPTR(ppprx->dwPtrVal, THUNK1632OBJ);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleasePprx, public
+//
+// Synopsis: Releases a resolved PROXYPTR
+//
+// Arguments: [ppprx] - PROXYPTR
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void ReleasePprx(PROXYPTR *ppprx)
+{
+ if (ppprx->wType == PPRX_16)
+ {
+ RELVDMPTR(ppprx->dwPtrVal);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::NewHolder, public
+//
+// Synopsis: Creates a new proxy holder
+//
+// Arguments: [dwFlags] - Flags
+//
+// Returns: Holder or NULL
+//
+// History: 16-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+PROXYHOLDER *CThkMgr::NewHolder(DWORD dwFlags)
+{
+ PROXYHOLDER *pph;
+
+ thkDebugOut((DEB_THUNKMGR, "In CThkMgr::NewHolder(0x%X)\n",
+ dwFlags));
+
+ pph = (PROXYHOLDER *)flHolderFreeList.AllocElement();
+ if (pph == NULL)
+ {
+ goto Exit;
+ }
+
+ pph->dwFlags = dwFlags;
+
+ // Start out without any listed proxies
+ pph->cProxies = 0;
+ PprxNull(pph->pprxProxies);
+
+ // Add to list of holders
+ pph->pphNext = _pphHolders;
+ _pphHolders = pph;
+
+ Exit:
+ thkDebugOut((DEB_THUNKMGR, "Out CThkMgr::NewHolder => %p\n",
+ pph));
+
+ return pph;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::AddProxyToHolder, public
+//
+// Synopsis: Adds a new proxy to a holder
+//
+// Arguments: [pph] - Holder
+// [pprxReal] - Proxy
+// [pprx] - Abstract pointer
+//
+// History: 07-Jul-94 DrewB Extracted
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::AddProxyToHolder(PROXYHOLDER *pph,CProxy *pprxReal,
+ PROXYPTR &pprx)
+{
+ thkDebugOut((DEB_THUNKMGR, "In AddProxyToHolder(%p, %p) cProxies %d\n",
+ pph, pprx.dwPtrVal, pph->cProxies));
+
+ thkAssert(ResolvePprx(&pprx) == pprxReal &&
+ (ReleasePprx(&pprx), TRUE));
+
+ // Bump count of held proxies
+ AddRefHolder(pph);
+
+ // Add proxy into list of object proxies
+ thkAssert(PprxIsNull(pprxReal->pprxObject));
+ pprxReal->pprxObject = pph->pprxProxies;
+ pph->pprxProxies = pprx;
+
+ thkAssert(pprxReal->pphHolder == NULL);
+ pprxReal->pphHolder = pph;
+
+ thkDebugOut((DEB_THUNKMGR, "out AddProxyToHolder(%p, %p) cProxies %d\n",
+ pph, pprx.dwPtrVal, pph->cProxies));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::AddRefHolder, public
+//
+// Synopsis: Increments the proxy count for a holder
+//
+// Arguments: [pph] - Holder
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::AddRefHolder(PROXYHOLDER *pph)
+{
+ pph->cProxies++;
+
+ thkDebugOut((DEB_THUNKMGR, "AddRefHolder(%p) cProxies %d\n",
+ pph, pph->cProxies));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseHolder, public
+//
+// Synopsis: Releases a proxy reference on the holder
+// Cleans up the holder if it was the last reference
+//
+// Arguments: [pph] - Holder
+//
+// History: 06-21-94 JohannP Created ReleaseAggregateProxies
+// 07-Jul-94 DrewB Modified
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::ReleaseHolder(PROXYHOLDER *pph)
+{
+ PROXYHOLDER *pphTmp, *pphPrev;
+
+ thkDebugOut((DEB_THUNKMGR, "ReleaseHolder(%p) pre cProxies %d\n",
+ pph, pph->cProxies));
+
+ thkAssert(pph->cProxies > 0);
+
+ // Decrement the holder's proxy count
+ pph->cProxies--;
+
+ if (pph->cProxies == 0)
+ {
+ CProxy *pprxReal;
+ PROXYPTR pprx, pprxNext;
+
+ // All interfaces for the object have been freed so we can
+ // clean up the object
+
+ pprx = pph->pprxProxies;
+ while (!PprxIsNull(pprx))
+ {
+ pprxReal = ResolvePprx(&pprx);
+ pprxNext = pprxReal->pprxObject;
+
+ thkAssert(pprxReal->cRefLocal == 0);
+ thkAssert(pprxReal->pphHolder == pph);
+
+ if (pprx.wType == PPRX_16)
+ {
+ // Releases pointer
+ RemoveProxy1632((VPVOID)pprx.dwPtrVal,
+ (THUNK1632OBJ *)pprxReal);
+ }
+ else
+ {
+ RemoveProxy3216((THUNK3216OBJ *)pprxReal);
+ }
+
+ pprx = pprxNext;
+ }
+
+ // Remove holder from list
+
+ pphPrev = NULL;
+ for (pphTmp = _pphHolders;
+ pphTmp && pphTmp != pph;
+ pphPrev = pphTmp, pphTmp = pphTmp->pphNext)
+ {
+ NULL;
+ }
+
+ // If we didn't find the holder in the holder list then our
+ // list is trashed
+ thkAssert(pphTmp == pph);
+
+ if (pphPrev == NULL)
+ {
+ _pphHolders = pph->pphNext;
+ }
+ else
+ {
+ pphPrev->pphNext = pph->pphNext;
+ }
+
+ flHolderFreeList.FreeElement((DWORD)pph);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::Create
+//
+// Synopsis: static member - creates complete thunkmanager
+//
+// Arguments: [void] --
+//
+// Returns: pointer to cthkmgr
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CThkMgr *CThkMgr::Create(void)
+{
+ CThkMgr *pcthkmgr = NULL;
+ CMapDwordPtr *pPT1632 = new CMapDwordPtr(MEMCTX_TASK);
+ CMapDwordPtr *pPT3216 = new CMapDwordPtr(MEMCTX_TASK);
+
+ if ( (pPT1632 != NULL)
+ && (pPT3216 != NULL)
+ && (pcthkmgr = new CThkMgr( pPT1632, pPT3216 )) )
+ {
+ // install the new thunkmanager
+ TlsThkSetThkMgr(pcthkmgr);
+ }
+ else
+ {
+ if (pPT1632)
+ {
+ delete pPT1632;
+ }
+ if (pPT3216)
+ {
+ delete pPT3216;
+ }
+ }
+ return pcthkmgr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CThkMgr
+//
+// Synopsis: private constructor - called by Create
+//
+// Arguments: [pPT1632] -- 16/32 proxy table
+// [pPT3216] -- 32/16 proxy table
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+CThkMgr::CThkMgr(CMapDwordPtr *pPT1632,
+ CMapDwordPtr *pPT3216)
+
+{
+ _cRefs = 1;
+ _thkstate = THKSTATE_NOCALL;
+ _piidnode = NULL;
+
+ _pProxyTbl1632 = pPT1632;
+ _pProxyTbl3216 = pPT3216;
+
+ _pphHolders = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::~CThkMgr
+//
+// Synopsis: destructor
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+CThkMgr::~CThkMgr()
+{
+ PROXYHOLDER *pph;
+ PIIDNODE pin;
+
+ thkDebugOut((DEB_ITRACE, "_IN CThkMgr::~CThkMgr()\n"));
+
+ RemoveAllProxies();
+ delete _pProxyTbl1632;
+ delete _pProxyTbl3216;
+
+ // Clean up IID requests
+#if DBG == 1
+ if (_piidnode != NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: IID requests active at shutdown\n"));
+ }
+#endif
+
+ while (_piidnode != NULL)
+ {
+ pin = _piidnode->pNextNode;
+
+ thkDebugOut((DEB_IWARN, "IID request leak: %p {%s}\n",
+ _piidnode, IidOrInterfaceString(_piidnode->piid)));
+
+ flRequestFreeList.FreeElement((DWORD)_piidnode);
+
+ _piidnode = pin;
+ }
+
+#if DBG == 1
+ if (_pphHolders != NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Proxy holders active at shutdown\n"));
+ }
+#endif
+
+ // Clean up any proxy holders
+ while (_pphHolders)
+ {
+ pph = _pphHolders->pphNext;
+
+ thkDebugOut((DEB_IWARN, "Proxy holder leak: %p {%d, 0x%X}\n",
+ _pphHolders, _pphHolders->cProxies,
+ _pphHolders->dwFlags));
+
+ flHolderFreeList.FreeElement((DWORD)_pphHolders);
+
+ _pphHolders = pph;
+ }
+ thkDebugOut((DEB_ITRACE, "OUT CThkMgr::~CThkMgr()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveAllProxies, public
+//
+// Synopsis: Removes all live proxies from the proxy tables
+//
+// History: 01-Dec-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveAllProxies(void)
+{
+ POSITION pos;
+ DWORD dwKey;
+ VPVOID vpv;
+
+ thkDebugOut((DEB_ITRACE, "_IN CThkMgr::RemoveAllProxies()\n"));
+
+ // Make sure that we disable 3216 proxies first to guard against calling
+ // back into 16 bit land.
+
+#if DBG == 1
+ DWORD dwCount;
+
+ dwCount = _pProxyTbl3216->GetCount();
+
+ if (dwCount > 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: %d 3216 proxies left\n", dwCount));
+ }
+#endif
+
+ // delete the 3216 proxy table
+ while (pos = _pProxyTbl3216->GetStartPosition())
+ {
+ THUNK3216OBJ *pto3216;
+
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ thkDebugOut((DEB_IWARN, "3216: %p {%d,%d, %p, %p} %s\n",
+ pto3216, pto3216->cRefLocal, pto3216->cRef,
+ pto3216->vpvThis16, pto3216->pphHolder,
+ IidIdxString(pto3216->iidx)));
+
+ pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
+
+ RemoveProxy3216(pto3216);
+ }
+
+#if DBG == 1
+ dwCount = _pProxyTbl1632->GetCount();
+
+ if (dwCount > 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: %d 1632 proxies left\n", dwCount));
+ }
+#endif
+
+ // delete the 1632 proxy table
+ while (pos = _pProxyTbl1632->GetStartPosition())
+ {
+ THUNK1632OBJ *pto1632;
+
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
+
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+
+#if DBG == 1
+ thkDebugOut((DEB_IWARN, "1632: %p {%d,%d, %p, %p} %s\n",
+ vpv, pto1632->cRefLocal, pto1632->cRef,
+ pto1632->punkThis32, pto1632->pphHolder,
+ IidIdxString(pto1632->iidx)));
+#endif
+ //
+ // Determine if this is a 'special' object that we know we want
+ // to release. If it is, then remove all of the references this
+ // proxy has on it.
+ //
+ if (CoQueryReleaseObject(pto1632->punkThis32) == NOERROR)
+ {
+ thkDebugOut((DEB_WARN,
+ "1632: %p is recognized Releasing object %d times\n",
+ pto1632->punkThis32,pto1632->cRef));
+
+ while (pto1632->cRef)
+ {
+ IUnknown *punk;
+
+ pto1632->cRef--;
+ punk = pto1632->punkThis32;
+
+ RELVDMPTR(vpv);
+
+ if (punk->Release() == 0)
+ {
+ break;
+ }
+
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ }
+ }
+
+ // Releases pointer
+ RemoveProxy1632(vpv, pto1632);
+ }
+
+ thkDebugOut((DEB_ITRACE, "OUT CThkMgr::RemoveAllProxies()\n"));
+}
+
+// *** IUnknown methods ***
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterface
+//
+// Synopsis: QueryInterface on the thunkmanager itself
+//
+// Arguments: [riid] -- IID of interface to return
+// [ppvObj] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CThkMgr::QueryInterface (REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsBadWritePtr(ppvObj, sizeof(void *)))
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppvObj = NULL;
+
+ // There is no IID_IThunkManager because nobody needs it
+
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = (IUnknown *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Methode: CThkMgr::AddRef
+//
+// Synopsis: Adds a reference
+//
+// Returns: New ref count
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CThkMgr::AddRef ()
+{
+ InterlockedIncrement( &_cRefs );
+ return _cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Methode: CThkMgr::Release
+//
+// Synopsis: Releases a reference
+//
+// Returns: New ref count
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CThkMgr::Release()
+{
+ if (InterlockedDecrement( &_cRefs ) == 0)
+ {
+
+ return 0;
+ }
+ return _cRefs;
+}
+
+// *** IThunkManager methods ***
+//
+//
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsIIDRequested
+//
+// Synopsis: checks if given refiid was requested by WOW
+//
+// Arguments: [riid] -- refiid
+//
+// Returns: true if requested by 16 bit
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_ (BOOL) CThkMgr::IsIIDRequested(REFIID riid)
+{
+ PIIDNODE piidnode = _piidnode;
+ BOOL fRet = FALSE;
+
+ while (piidnode)
+ {
+ if (*piidnode->piid == riid)
+ {
+ fRet = TRUE;
+ break;
+ }
+
+ piidnode = piidnode->pNextNode;
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "IsIIDRequested(%s) => %d\n",
+ GuidString(&riid), fRet));
+
+ return fRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::IsCustom3216Proxy, public
+//
+// Synopsis: Attempts to identify the given IUnknown as a 32->16 proxy
+// and also checks whether it is a thunked interface or not
+//
+// Arguments: [punk] - Object
+//
+// Returns: BOOL
+//
+// History: 11-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CThkMgr::IsCustom3216Proxy(IUnknown *punk,
+ REFIID riid)
+{
+ return !IsIIDSupported(riid) && IsProxy3216(punk) != 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsIIDSupported
+//
+// Synopsis: Return whether the given interface is thunked or not
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: BOOL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL CThkMgr::IsIIDSupported(REFIID riid)
+{
+ return IIDIDX_IS_INDEX(IidToIidIdx(riid));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddIIDRequest
+//
+// Synopsis: adds the refiid to the request list
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: true on success
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL CThkMgr::AddIIDRequest(REFIID riid)
+{
+ PIIDNODE piidnode = _piidnode;
+
+ thkAssert(!IsIIDSupported(riid));
+
+ // create a new node and add at front
+ piidnode = (PIIDNODE)flRequestFreeList.AllocElement();
+ if (piidnode == NULL)
+ {
+ return FALSE;
+ }
+
+ piidnode->pNextNode = _piidnode;
+ _piidnode = piidnode;
+
+ // IID requests are only valid for the lifetime of the call that
+ // requested a custom interface, so there's no need to copy
+ // the IID's memory since it must remain valid for the same time
+ // period
+ piidnode->piid = (IID *)&riid;
+
+ thkDebugOut((DEB_THUNKMGR, "AddIIDRequest(%s)\n", GuidString(&riid)));
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::RemoveIIDRequest
+//
+// Synopsis: removes a request for the request list
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: true on success
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::RemoveIIDRequest(REFIID riid)
+{
+ PIIDNODE piidnode;
+ PIIDNODE pinPrev;
+
+ thkAssert(!IsIIDSupported(riid));
+
+ pinPrev = NULL;
+ piidnode = _piidnode;
+ while (piidnode)
+ {
+ if (*piidnode->piid == riid)
+ {
+ break;
+ }
+
+ pinPrev = piidnode;
+ piidnode = piidnode->pNextNode;
+ }
+
+ thkAssert(piidnode != NULL && "RemoveIIDRequest: IID not found");
+
+ thkDebugOut((DEB_THUNKMGR, "RemoveIIDRequest(%s)\n", GuidString(&riid)));
+
+ if (pinPrev == NULL)
+ {
+ _piidnode = piidnode->pNextNode;
+ }
+ else
+ {
+ pinPrev->pNextNode = piidnode->pNextNode;
+ }
+
+ flRequestFreeList.FreeElement((DWORD)piidnode);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CanGetNewProxy1632
+//
+// Synopsis: Preallocates proxy memory
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// Returns: vpv pointer if proxy is available, fails otherwise
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::CanGetNewProxy1632(IIDIDX iidx)
+{
+ VPVOID vpv;
+ THUNK1632OBJ UNALIGNED *pto;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy1632(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ // Allocate proxy memory
+ vpv = (VPVOID)flFreeList16.AllocElement();
+ if (vpv == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Failed to allocate memory "
+ "for 16-bit proxies\n"));
+ goto Exit;
+ }
+
+ // Add custom interface request if necessary
+ if (vpv && IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
+ {
+ flFreeList16.FreeElement( (DWORD)vpv );
+ vpv = 0;
+ }
+ }
+
+ // Set up the preallocated proxy as a temporary proxy so that
+ // we can hand it out for nested callbacks
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkAssert(pto != NULL);
+
+ pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
+ pto->cRefLocal = 0;
+ pto->cRef = 0;
+ pto->iidx = iidx;
+ pto->punkThis32 = NULL;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_TEMPORARY;
+#if DBG == 1
+ // Deliberately make this an invalid proxy. We want it to be used
+ // in as few places as possible
+ pto->dwSignature = PSIG1632TEMP;
+#endif
+
+ RELVDMPTR(vpv);
+
+ Exit:
+ thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy1632: %p\n",
+ NestingLevelString(), vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeNewProxy1632
+//
+// Synopsis: frees unused preallocated proxies
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::FreeNewProxy1632(VPVOID vpv, IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy1632(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ thkAssert(vpv != 0);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // remove the request for the unknown interface
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+#if DBG == 1
+ // Ensure that we're not getting rid of a temporary proxy that's
+ // in use
+ THUNK1632OBJ UNALIGNED *pto;
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ if (pto->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
+ }
+ RELVDMPTR(vpv);
+#endif
+
+ // add element to free list
+ flFreeList16.FreeElement( (DWORD)vpv );
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy1632\n",
+ NestingLevelString()));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsProxy1632
+//
+// Synopsis: checks if given object is an 16/32 object
+//
+// Arguments: [vpvObj16] -- Object to check
+//
+// Returns: 32-bit object being proxied or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::IsProxy1632(VPVOID vpvObj16)
+{
+ VPVOID vpvProxy;
+ DWORD dwKey;
+ POSITION pos;
+ THUNK1632OBJ UNALIGNED *pto;
+ THUNKINFO ti;
+
+ // First check and see if the vtable pointer is the one for
+ // 16-bit proxies. If it's not, this can't be a proxy
+ // Since we don't know anything about this pointer, we need
+ // to do safe translation
+ pto = (THUNK1632OBJ UNALIGNED *)
+ GetReadPtr16(&ti, vpvObj16, sizeof(THUNK1632OBJ));
+ if (pto != NULL && pto->pfnVtbl == gdata16Data.atfnProxy1632Vtbl)
+ {
+ // The proxy may be freed memory or just random memory which
+ // happens to have the right value, so make sure that it's
+ // a proxy by looking it up in the proxy table
+
+ pos = _pProxyTbl1632->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey,
+ (void FAR* FAR&) vpvProxy);
+ if (vpvProxy == vpvObj16)
+ {
+ RELVDMPTR(vpvObj16);
+ return (IUnknown *)dwKey;
+ }
+ }
+
+ // Check to see if we're returning no for what we think is
+ // a valid proxy
+ // It's possible for this to occur if somebody made a copy
+ // of a proxy's memory, but in general this assert should
+ // be extremely unlikely
+ thkAssert(pto->dwSignature != PSIG1632);
+ }
+
+ if (pto != NULL)
+ {
+ RELVDMPTR(vpvObj16);
+ }
+
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindProxy1632
+//
+// Synopsis: retrieves a 16/32 object (most cases proxy) for a given
+// 32 bit IUnknown, it can be a real object -> shortcut
+//
+// Arguments: [vpvPrealloc] -- preallocated proxy
+// [punkThis32] -- 32 bit object to be proxied
+// [iidx] - Interface index or IID
+// [pfst] - Return what kind of object was found
+//
+// Returns: 16/32 object (proxy or real object)
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::FindProxy1632(VPVOID vpvPrealloc,
+ IUnknown *punkThis32,
+ IIDIDX iidx,
+ DWORD *pfst)
+{
+ THUNK1632OBJ UNALIGNED *pto;
+ VPVOID vpv;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy1632(%p, %p, %s)\n",
+ NestingLevelString(), vpvPrealloc, punkThis32,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkThis32 != NULL);
+
+#if DBG == 1
+ // Ensure that we're not reusing a temporary proxy that's in use
+ if (vpvPrealloc)
+ {
+ pto = FIXVDMPTR(vpvPrealloc, THUNK1632OBJ);
+ if (pto->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
+ }
+ RELVDMPTR(vpvPrealloc);
+ }
+#endif
+
+ // If we preallocated a proxy with an IID then a request was added
+ // in CanGetNewProxy. Clean it up now
+ if (vpvPrealloc != 0 && IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ // Check the proxy table for an existing proxy for the given object pointer
+ // the 32 bit pointer is the key to the 16/32 proxy
+ vpv = LookupProxy1632(punkThis32);
+ if (vpv != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 found existing proxy,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // We found an existing proxy, so reuse it
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+
+ // If a proxy's refcount is zero, it must be part of an aggregate
+ thkAssert(pto->cRefLocal > 0 ||
+ (pto->pphHolder != NULL &&
+ (pto->pphHolder->dwFlags & PH_AGGREGATE) != 0));
+
+ //Note: IIDIDXs are related to interfaces in our tables
+ // we have our table organized such that more derived
+ // interfaces are higher than less derived
+ // * Custom interfaces will have an IID rather than an index
+ // and will never be promoted above IUnknown in the
+ // below statement (johannp)
+ if (IIDIDX_IS_INDEX(iidx) &&
+ IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx))
+ {
+ // 16-bit proxy vtables are all the same so there's no
+ // need to manipulate the vtable pointer here as we
+ // do in the 32-bit case
+
+ pto->iidx = iidx;
+ }
+
+ RELVDMPTR(vpv);
+
+ // AddRef the proxy we found since we're passing out a new reference
+ AddRefProxy1632(vpv);
+
+ if (pfst)
+ {
+ *pfst = FST_USED_EXISTING;
+ }
+
+ goto Exit;
+ }
+
+ // Check and see whether the object we're supposed to proxy is
+ // actually a proxy itself
+ if ( (vpv = IsProxy3216(punkThis32)) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 shortcut proxy,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // We've discovered that the object that we're supposed to
+ // proxy is actually a proxy itself. In that case, we can
+ // avoid creating a full-circle proxy chain by returning
+ // the real pointer rather than creating a new proxy
+ //
+ // If we're shortcutting proxies for in parameters, we
+ // don't need to manipulate the reference count
+ // In the out parameter case, though, we're actually transferring
+ // ownership so we need to AddRef the real object and clean
+ // up the proxy we shortcut around
+ if (IsOutParamObj())
+ {
+ THKSTATE thkstate;
+
+ // We want to temporarily suspend our out state since
+ // we want this AddRef to really occur if it comes
+ // back to a proxy
+ thkstate = GetThkState();
+ SetThkState(THKSTATE_NOCALL);
+
+ AddRefOnObj16(vpv);
+
+ SetThkState(thkstate);
+
+ // Release the ignored proxy
+ // This avoids leaking proxies in round-trip calls
+ // where nobody holds a pointer to the proxy
+ ReleaseProxy3216((THUNK3216OBJ *)punkThis32);
+ }
+
+ if (pfst)
+ {
+ *pfst = FST_SHORTCUT;
+ }
+
+ goto Exit;
+ }
+
+ // We didn't find an existing proxy and the object to be proxied
+ // is a real object so we need to fill out a new proxy for it
+ // We might have a preallocated proxy provided; if we don't
+ // we need to go to the free list and get a new one
+
+ if (vpvPrealloc != NULL)
+ {
+ vpv = vpvPrealloc;
+
+ // If we successfully created a proxy using the preallocated
+ // proxy, mark the preallocated proxy as used so it's not cleaned up
+ vpvPrealloc = NULL;
+ }
+ else
+ {
+ vpv = (VPVOID)flFreeList16.AllocElement();
+ }
+
+ if (vpv != NULL)
+ {
+ // Put the new proxy in the proxy list
+ if (!_pProxyTbl1632->SetAt((DWORD)punkThis32, (void *&)vpv))
+ {
+ // Note that we can put vpv on the free list even it's
+ // the preallocated proxy since that's what the prealloc
+ // cleanup does
+ flFreeList16.FreeElement(vpv);
+
+ vpv = NULL;
+ goto Exit;
+ }
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // We're creating a proxy for a custom interface
+ // so just hand out an IUnknown
+ iidx = INDEX_IIDIDX(THI_IUnknown);
+ }
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkAssert(pto != NULL);
+
+ pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
+ pto->cRefLocal = 1;
+ pto->cRef = (IsOutParamObj()) ? 1 : 0;
+ pto->iidx = iidx;
+ pto->punkThis32 = punkThis32;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_NORMAL;
+
+#if DBG == 1
+ pto->dwSignature = PSIG1632;
+#endif
+
+ RELVDMPTR(vpv);
+
+ if (pfst)
+ {
+ *pfst = FST_CREATED_NEW;
+ }
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 added new proxy, %s (%p)->%p (%d,%d)\n",
+ NestingLevelString(),
+ inInterfaceNames[pto->iidx].pszInterface,
+ punkThis32, vpv,
+ pto->cRefLocal, pto->cRef));
+ }
+
+ Exit:
+ // If we didn't use the preallocated proxy for some reason
+ // then put it back on the free list
+ if (vpvPrealloc != NULL)
+ {
+ flFreeList16.FreeElement( (DWORD)vpvPrealloc );
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy1632: (%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindAggregate1632
+//
+// Synopsis: retrieves an aggregate for 1632 with the given cntrl. unknown
+//
+// Arguments: [vpvPrealloc] - Preallocated proxy or NULL
+// [punkOuter3216] -- the controlling unknown
+// [punkThis32] -- the 32 bit interface - key
+// [iidx] -- Index or IID of interface
+//
+// Returns: 16/32 proxy object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::FindAggregate1632(VPVOID vpvPrealloc,
+ IUnknown *punkOuter3216,
+ IUnknown *punkThis32,
+ IIDIDX iidx)
+{
+ THUNK1632OBJ UNALIGNED *pto1632;
+ VPVOID vpv;
+ DWORD fst;
+ BOOL fMarkPUnk1632 = FALSE;
+
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sIn FindAggregate1632(%p, %p, %p, %s)\n",
+ NestingLevelString(), vpvPrealloc, punkOuter3216, punkThis32,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkOuter3216 != NULL && punkThis32 != NULL);
+
+ // Get back an object for the object to be proxied
+ // This may be a proxy or a real object from a shortcut
+ vpv = FindProxy1632(vpvPrealloc, punkThis32, iidx, &fst);
+ if (vpv == 0)
+ {
+ goto Exit;
+ }
+
+ // If we got an object and it's not a proxy, we're done
+ // There's nothing we can do since we can't link a real object to
+ // a holder; we can only hope that things work out right
+ if (fst & FST_OBJECT_STATUS)
+ {
+ goto Exit;
+ }
+
+ // Otherwise, we need to set up a holder for whatever proxies we
+ // have
+
+ THUNK3216OBJ *ptoUnkOuter3216;
+ PROXYHOLDER *pph;
+ VPVOID vpvProxiedUnkOuter3216;
+
+ // Determine whether the outer unknown is a proxy or not
+ vpvProxiedUnkOuter3216 = IsProxy3216(punkOuter3216);
+
+ // This cast is only valid if vpvProxiedUnkOuter3216 is non-NULL
+ ptoUnkOuter3216 = (THUNK3216OBJ *)punkOuter3216;
+
+ if (vpvProxiedUnkOuter3216 != 0 && ptoUnkOuter3216->pphHolder != NULL)
+ {
+ // Use the existing holder if there is one
+ pph = ptoUnkOuter3216->pphHolder;
+ }
+ else
+ {
+ // Create a new holder
+ pph = NewHolder(PH_AGGREGATE);
+ if (pph == NULL)
+ {
+ FreeProxy1632(punkThis32);
+ vpv = NULL;
+ goto Exit;
+ }
+
+ // If the outer unknown is a proxy we know its holder hasn't
+ // been set, so add it to the holder we created
+ if (vpvProxiedUnkOuter3216 != 0)
+ {
+ AddProxyToHolder(pph, ptoUnkOuter3216, Pprx32(ptoUnkOuter3216));
+ // Mark the pUnkOuter3216 as such; needed for aggregation rules
+ thkDebugOut((DEB_THUNKMGR,
+ "%s FindAggregate1632,(%p)->%p marked as pUnkOuter3216\n",
+ NestingLevelString(), ptoUnkOuter3216,Pprx32(ptoUnkOuter3216) ));
+ ptoUnkOuter3216->grfFlags |= PROXYFLAG_PUNKOUTER;
+ fMarkPUnk1632 = TRUE;
+ }
+ }
+
+ thkAssert(vpvProxiedUnkOuter3216 == 0 || ptoUnkOuter3216->pphHolder == pph);
+
+ // Add the new interface to the holder
+ // Since this proxy was just created, we know its holder
+ // hasn't been set yet
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ AddProxyToHolder(pph, pto1632, Pprx16(vpv));
+ if (fMarkPUnk1632)
+ {
+ pto1632->grfFlags |= PROXYFLAG_PUNK;
+ thkDebugOut((DEB_THUNKMGR,
+ "%s FindAggregate1632,(%p)->%p marked as pUnk1632\n",
+ NestingLevelString(), punkThis32, vpv));
+ }
+
+ RELVDMPTR(vpv);
+
+ Exit:
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut FindAggregate1632,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterfaceProxy1632
+//
+// Synopsis: QueryInterface on 32 bit object
+//
+// Arguments: [vpvThis16] -- Proxy
+// [refiid] -- IID
+// [ppv] -- new object (proxy or real object) for queried
+// interface
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE CThkMgr::QueryInterfaceProxy1632(VPVOID vpvThis16,
+ REFIID refiidIn,
+ LPVOID *ppv)
+{
+ SCODE scRet;
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ THUNK1632OBJ UNALIGNED *ptoProxy;
+ VPVOID vpvProxy;
+ IIDIDX iidx;
+ IUnknown *punk32, *punkThis32;
+ DWORD fst;
+ BOOL fNotSupported = FALSE;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+ thkAssert(ptoThis != NULL);
+
+ // Don't validate temporary proxies
+ // We need to support temporary proxies in this method since
+ // Corel Draw 5.0 QI's on a temporary proxy
+ //
+ // BUGBUG - There are many potential problems with object identity,
+ // for example QI'ing where the return is the same object as the
+ // souce. Since the source is temporary it doesn't exist in the
+ // tables so identity will be broken. Of course, this won't cause
+ // any regressions for apps which don't use temporary proxies,
+ // so I think this is acceptable
+ if ((ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ DebugValidateProxy1632(vpvThis16);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy1632 on "
+ "temporary %s proxy\n", IidIdxString(ptoThis->iidx)));
+ }
+
+ *ppv = NULL;
+ // Note: Ikitaro queries for IViewObject and uses it as IViewObject2
+ REFIID refiid = ( (TlsThkGetAppCompatFlags() & OACF_IVIEWOBJECT2) && IsEqualIID(refiidIn, IID_IViewObject))
+ ? IID_IViewObject2 : refiidIn;
+
+#if DBG==1
+ if ( (TlsThkGetAppCompatFlags() & OACF_IVIEWOBJECT2)
+ && IsEqualIID(refiidIn, IID_IViewObject))
+ {
+ thkDebugOut((DEB_WARN,"Ikitaro: return IViewObject2 instead IViewObject\n"));
+ }
+#endif // DBG==1
+
+ iidx = IidToIidIdx(refiid);
+
+ // see if this a supported interface
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if (!AddIIDRequest(refiid))
+ {
+ RELVDMPTR(vpvThis16);
+ return E_OUTOFMEMORY;
+ }
+ fNotSupported = TRUE;
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy1632: unknown iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+ }
+
+ // We force the object we're QI'ing to have a holder so that
+ // all objects have object refcounting. This should only be
+ // necessary for aggregation but it seems that some apps rely
+ // on all objects having aggregation-like refcounting qualities
+ // BobDay identified PowerPoint as one
+ // We only want to do this in cases where we've identified it's
+ // necessary, which presently is only for
+ // IDataObject
+ // so we only do it then
+
+ if (ptoThis->pphHolder == NULL &&
+ (ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0 &&
+ IsEqualIID(refiid, IID_IDataObject))
+ {
+ PROXYHOLDER *pph;
+
+ pph = NewHolder(PH_NONAGGREGATE);
+ if (pph == NULL)
+ {
+ RELVDMPTR(vpvThis16);
+ scRet = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ AddProxyToHolder(pph, ptoThis, Pprx16(vpvThis16));
+
+ // It's not necessary to clean this up if later calls fail
+ // since it doesn't alter the lifetime of the proxy if there's
+ // only one proxy for the holder
+ }
+
+ if (ptoThis->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ punkThis32 = *(IUnknown **)ptoThis->punkThis32;
+ }
+ else
+ {
+ punkThis32 = ptoThis->punkThis32;
+ }
+
+ RELVDMPTR(vpvThis16);
+
+ if (punkThis32 == NULL)
+ {
+ scRet = E_NOINTERFACE;
+ goto Exit;
+ }
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy1632: on iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ scRet = punkThis32->QueryInterface(refiid, (void **)&punk32);
+
+ if (FAILED(scRet))
+ {
+ goto Exit;
+ }
+
+ SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ vpvProxy = FindProxy1632(NULL, punk32, iidx, &fst);
+ if (vpvProxy == NULL)
+ {
+ // we were unable to create a proxy for the new interface so
+ // clean up the interface and quit
+
+ punk32->Release();
+
+ scRet = E_OUTOFMEMORY;
+ goto ResetState;
+ }
+
+ if (fNotSupported && !(fst & FST_SHORTCUT))
+ {
+ // proxy of unknow interface can not be promoted
+ // clean up the interface and quit
+
+ ReleaseProxy1632(vpvProxy);
+
+ scRet = E_NOINTERFACE;
+ goto ResetState;
+ }
+
+
+ *ppv = (LPVOID)vpvProxy;
+
+ // If we're returning a proxy, we need to make sure that
+ // it is listed in the proxy holder for this object
+ if (fst & FST_PROXY_STATUS)
+ {
+ // We are returning a proxy. If its holder isn't set,
+ // add it to the holder of the object that was QI'ed
+
+ // Reconvert 16:16 pointer since calls may have caused
+ // nested calls and flat remapping
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ ptoProxy = FIXVDMPTR(vpvProxy, THUNK1632OBJ);
+ if (ptoProxy->pphHolder == NULL)
+ {
+ if (ptoThis->pphHolder != NULL)
+ {
+ AddProxyToHolder(ptoThis->pphHolder, ptoProxy,
+ Pprx16(vpvProxy));
+ }
+ }
+ else if (ptoThis->pphHolder == NULL &&
+ (ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ // ptoThis may not have a holder because it was produced
+ // by a non-QI method such as IOleItemContainer::GetObject
+ // If we find that an interface returned by it does
+ // have a holder, hook it up to the holder
+
+ // It shouldn't be necessary to do anything unusual with
+ // local references even if ptoThis is really part of an
+ // aggregate since ptoThis must have been produced by
+ // a method where aggregation can't be assumed and all
+ // references must be released on ptoThis itself
+ AddProxyToHolder(ptoProxy->pphHolder, ptoThis,
+ Pprx16(vpvThis16));
+ }
+
+#if DBG == 1
+ // It's possible for holders to not match because of the above
+ // case with interfaces being returned from non-QI methods
+ // The lifetime for such interfaces must be defined by
+ // strong references, though, so it's not catastrophic
+ // Still, we'd like to be aware of such mismatches just in case
+ if (ptoProxy->pphHolder != ptoThis->pphHolder)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy1632: "
+ "this %p has holder %p, proxy %p has holder %p\n",
+ vpvThis16, ptoThis->pphHolder,
+ vpvProxy, ptoProxy->pphHolder));
+ }
+#endif
+
+ RELVDMPTR(vpvThis16);
+ RELVDMPTR(vpvProxy);
+ }
+
+ ResetState:
+ SetThkState(THKSTATE_NOCALL);
+
+ Exit:
+ // Clean up our custom interface request if there is one
+ if (IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(refiid);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceProxy1632(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), vpvThis16, *ppv, scRet));
+
+ return scRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::LocalAddRefProxy, public
+//
+// Synopsis: Increment a proxy's local refcount
+//
+// Arguments: [pprx] - Proxy
+//
+// History: 02-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::LocalAddRefProxy(CProxy *pprx)
+{
+ pprx->cRefLocal++;
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s LocalAddRefProxy1632 <%08lX> RefCounts: %d,%d\n",
+ NestingLevelString(),
+ pprx, pprx->cRefLocal, pprx->cRef ));
+
+ // Check for proxies rising from the dead
+
+ // If we're not part of an aggregate our refcount shouldn't be
+ // one or lower. If it is we're reviving a dead proxy which won't
+ // be in the proxy list and this could cause problems
+ //
+ // Note: With the new proxy stabilization code this can and does
+ // happen so this is only a debug out
+#if DBG == 1
+ if (!(pprx->cRefLocal > 1 ||
+ (pprx->pphHolder != NULL &&
+ (pprx->pphHolder->dwFlags & PH_AGGREGATE) != 0)))
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Proxy %p unlisted with refs %d,%d\n",
+ pprx, pprx->cRefLocal, pprx->cRef));
+ }
+#endif
+
+ if (pprx->cRefLocal == 1)
+ {
+ // We just resurrected a proxy with a zero refcount,
+ // so increment its holder's proxy count since it
+ // was decremented when the proxy released to zero
+ if (pprx->pphHolder != NULL)
+ {
+ AddRefHolder(pprx->pphHolder);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::LockProxy, public
+//
+// Synopsis: Locks a proxy so that it can't be freed
+//
+// Arguments: [pprx] - Proxy
+//
+// History: 11-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::LockProxy(CProxy *pprx)
+{
+ pprx->grfFlags |= PROXYFLAG_LOCKED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddRefProxy1632
+//
+// Synopsis: addrefs proxy object - delegate call on to real object
+//
+// Arguments: [vpvThis16] -- 16/32 proxy
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes: AddRef rules
+// * cRef is the addref passed on to the real object
+// * cRefLocal is the addref collected locally
+// - the refcount can be 0 if the object was created as on in-param
+//----------------------------------------------------------------------------
+DWORD CThkMgr::AddRefProxy1632(VPVOID vpvThis16)
+{
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ BOOL fAggregate;
+ LONG cRef;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy1632(vpvThis16);
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s AddRefProxy1632 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ vpvThis16, ptoThis->cRefLocal, ptoThis->cRef ));
+
+ // Always increment the proxy local refcount
+ LocalAddRefProxy(ptoThis);
+
+ // Aggregations rely on all reference counts being forwarded on
+ // to the controlling unknown. Therefore, if we have a proxy
+ // that is part of an aggregate, we must ensure that the proxy
+ // doesn't collect references locally. If it did, they would
+ // not be passed on to the controlling unknown (via the real object)
+ // and the controlling unknown's refcount would be too low
+ if (ptoThis->pphHolder == NULL)
+ {
+ fAggregate = FALSE;
+ }
+ else
+ {
+ fAggregate = (ptoThis->pphHolder->dwFlags & PH_AGGREGATE) != 0;
+ }
+
+ if (IsOutParamObj())
+ {
+ // If we're on the way out we're assuming that the object
+ // given to us has its own reference so we bump cRef to
+ // indicate that but we don't call the real object
+ ptoThis->cRef++;
+ }
+ else if (ptoThis->cRef == 0 || fAggregate)
+ {
+ DWORD dwRet;
+ IUnknown *punk;
+
+ // It's also necessary to pass on real references when the
+ // ref count is zero. This handles the case where an
+ // in parameter, created as 1,0, is AddRef'ed after
+ // its creation, in which case the reference needs to
+ // be passed on to the real object so that the proxy has
+ // at least one real reference since it will stay alive
+ ptoThis->cRef++;
+ punk = ptoThis->punkThis32;
+ RELVDMPTR(vpvThis16);
+ dwRet = punk->AddRef();
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s AddRefProxy1632: AddRef called on (%p):%ld\n",
+ NestingLevelString(), punk, dwRet));
+
+ // Reconvert 16:16 pointer since real AddRef may have caused
+ // nested calls and flat remapping
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+ }
+ else
+ {
+ // Just a local addref
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy1632(%p), (%ld,%ld)\n",
+ NestingLevelString(), vpvThis16,
+ ptoThis->cRefLocal, ptoThis->cRef));
+
+ cRef = ptoThis->cRefLocal;
+ RELVDMPTR(vpvThis16);
+
+ return cRef;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseProxy1632
+//
+// Synopsis: release on 16/32 proxy - delegate call on to real object
+//
+// Arguments: [vpvThis16] -- proxy
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::ReleaseProxy1632(VPVOID vpvThis16)
+{
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ PROXYHOLDER *pph;
+ LONG cRef, cRefLocal;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy1632(vpvThis16);
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ // There are cases where releasing the real object causes
+ // an entire object to go away so the proxy is gone after
+ // that call. Fortunately these cases only occur when
+ // cRef == cRefLocal == 0, so we can avoid problems by
+ // copying them locally
+
+ cRef = ptoThis->cRef;
+ cRefLocal = ptoThis->cRefLocal;
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s ReleaseProxy1632 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ vpvThis16, ptoThis->cRefLocal, ptoThis->cRef ));
+
+
+ if (cRef <= 0 && cRefLocal == cRef)
+ {
+ thkDebugOut((DEB_ERROR, "ERROR: ReleaseProxy1632(%p) cRef: %d; cRef: %d\n",
+ vpvThis16, ptoThis->cRef, ptoThis->cRefLocal));
+
+ goto Done;
+ }
+
+ // If our local refcount is the same as the count of references
+ // that we've passed on to the object, then we need to pass
+ // on this release to the real object
+ if (ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ DWORD dwRet;
+ IUnknown *punk;
+
+#if DBG == 1
+ // We'd like to assert this but some apps (Works is one)
+ // release an aggregated object too many times through one
+ // interface. The overall aggregate refcount is ok, though,
+ // so this doesn't cause a problem
+
+ // thkAssert(ptoThis->cRef > 0);
+
+ if (ptoThis->cRef <= 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy1632(%p) cRef: %d\n",
+ vpvThis16, ptoThis->cRef));
+ }
+#endif
+
+ // Use local cRef here for safety
+ if (cRef > 0)
+ {
+ // Decrement cRef after making the real call to ensure that
+ // the proxy lives throughout the call
+ --ptoThis->cRef;
+ }
+
+
+
+ punk = ptoThis->punkThis32;
+ RELVDMPTR(vpvThis16);
+
+ // check if this is an pUnk proxy in an aggregation
+ // if so mark the pUnkOuter for cleanup
+ if (ptoThis->grfFlags & PROXYFLAG_PUNK)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy1632: Release called on (%p)->%p\n",
+ NestingLevelString(), punk, vpvThis16));
+ pph = ptoThis->pphHolder;
+ pph->dwFlags |= PH_AGGREGATE_RELEASE;
+ }
+
+ // Decremente cRefLocal to prevent loops in release
+ --ptoThis->cRefLocal;
+
+ dwRet = punk->Release();
+
+ // Refresh pointer
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ // Increment cRefLocal after making the real call to ensure that
+ // the proxy lives throughout the call
+ ++ptoThis->cRefLocal;
+
+ // rese the aggreagation flag
+ if (ptoThis->grfFlags & PROXYFLAG_PUNK)
+ {
+ pph = ptoThis->pphHolder;
+ pph->dwFlags &= !PH_AGGREGATE_RELEASE;
+ }
+
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy1632: Release called on (%p):%ld \n",
+ NestingLevelString(), ptoThis->punkThis32, dwRet));
+ }
+
+ // Now that we've handled the real object's refcount, decrement
+ // the proxy's refcount and clean it up if necessary
+ // We need to use the local cRefLocal in case the proxy has gone away
+
+#if DBG == 1
+ // We'd like to assert this but some apps (Works is one)
+ // release an aggregated object too many times through one
+ // interface. The overall aggregate refcount is ok, though,
+ // so this doesn't cause a problem
+
+ thkAssert(cRefLocal > 0);
+
+ if (cRefLocal <= 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy1632(%p) cRefLocal: %d\n",
+ vpvThis16, cRefLocal));
+ }
+#endif
+
+ if (cRefLocal <= 0)
+ {
+ ptoThis = NULL;
+ }
+ else if (--ptoThis->cRefLocal == 0)
+ {
+
+ // Proxies that have no outer unknown can be cleaned
+ // up immediately. If they do have an outer unknown then
+ // they must live as long as the entire object lives,
+ // so we don't clean them up here. They'll be cleaned up
+ // when the object dies
+
+ pph = ptoThis->pphHolder;
+ if (pph)
+ {
+ // If this proxy isn't part of an aggregate, remove it
+ // from the proxy list so it can't be reused
+ // The only thing this proxy will be good for is
+ // calling through
+ if ((pph->dwFlags & PH_AGGREGATE) == 0)
+ {
+ _pProxyTbl1632->RemoveKey((DWORD)ptoThis->punkThis32);
+ }
+
+ RELVDMPTR(vpvThis16);
+
+ // We have a holder, so notify it that one of its
+ // proxies just died
+ // This can cause cleanup of all proxies if the
+ // holder releases to zero
+ ReleaseHolder(pph);
+ }
+ else
+ {
+ // We don't have a holder so we can clean up this proxy
+ // immediately
+
+ // Releases pointer
+ RemoveProxy1632(vpvThis16, ptoThis);
+ }
+
+ ptoThis = NULL;
+
+ DBG_DUMP(DebugDump1632());
+ }
+
+Done:
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy1632(%p) => %d,%d\n",
+ NestingLevelString(), vpvThis16,
+ ptoThis ? ptoThis->cRefLocal : 0,
+ ptoThis ? ptoThis->cRef : 0));
+
+ if (ptoThis)
+ {
+ cRef = ptoThis->cRefLocal;
+ RELVDMPTR(vpvThis16);
+ }
+ else
+ {
+ cRef = 0;
+ }
+
+ return cRef;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeProxy1632
+//
+// Synopsis: frees object for given pUnk (key)
+//
+// Arguments: [punkThis32] -- 32 bit unknown - key
+//
+// Returns: Refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::FreeProxy1632(IUnknown *punkThis32)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeProxy1632(%p)\n",
+ NestingLevelString(), punkThis32));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkThis32 != NULL && "FreeProxy1632: invalid object pointer.");
+
+ DWORD dwRet = 0;
+ VPVOID vpv;
+
+ vpv = LookupProxy1632(punkThis32);
+ if (vpv != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFreeProxy1632(%p) found existing proxy %p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // punkThis32 is a proxy and not a real object, so release it
+ dwRet = ReleaseProxy1632(vpv);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeProxy1632(%p):%ld \n",
+ NestingLevelString(), punkThis32, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveProxy1632, public
+//
+// Synopsis: Destroys the given proxy
+//
+// Arguments: [vpv] - 16-bit proxy pointer
+// [pto] - Flat proxy pointer
+//
+// History: 11-Aug-94 DrewB Created
+//
+// Notes: Unfixes fixed pointer passed in
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveProxy1632(VPVOID vpv, THUNK1632OBJ *pto)
+{
+ _pProxyTbl1632->RemoveKey((DWORD)pto->punkThis32);
+
+ if ((pto->grfFlags & PROXYFLAG_LOCKED) == 0)
+ {
+#if DBG == 1
+ pto->dwSignature = PSIG1632DEAD;
+#endif
+
+ RELVDMPTR(vpv);
+
+#if DBG == 1
+ if (!fSaveProxy)
+#endif
+ {
+ flFreeList16.FreeElement((DWORD)vpv);
+ }
+ }
+ else
+ {
+ RELVDMPTR(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CanGetNewProxy3216
+//
+// Synopsis: checks if new proxy is available
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// Returns: Preallocated proxy or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+THUNK3216OBJ *CThkMgr::CanGetNewProxy3216(IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy3216(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ LPVOID pvoid;
+
+ pvoid = (LPVOID)flFreeList32.AllocElement();
+ if ( pvoid == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: CThkMgr::CanGetNewProxy3216, "
+ "AllocElement failed\n"));
+ return NULL;
+ }
+
+ // check if the proxy is requested for a no-thop-interface
+ if (pvoid && IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
+ {
+ flFreeList32.FreeElement( (DWORD)pvoid );
+ pvoid = NULL;
+ }
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy3216: %p \n",
+ NestingLevelString(), pvoid));
+
+ return (THUNK3216OBJ *)pvoid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeNewProxy3216
+//
+// Synopsis: frees previous reserved proxy
+//
+// Arguments: [pto] - Proxy
+// [iidx] - Custom interface or known index
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::FreeNewProxy3216(THUNK3216OBJ *pto, IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy3216(%p, %s)\n",
+ NestingLevelString(), pto, IidIdxString(iidx)));
+
+ thkAssert(pto != NULL);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ thkAssert(pto != NULL);
+ flFreeList32.FreeElement( (DWORD)pto );
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy3216\n",
+ NestingLevelString()));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsProxy3216
+//
+// Synopsis: checks if the given object is a 32/16 proxy
+//
+// Arguments: [punk] -- punk of 32 bit object
+//
+// Returns: Object being proxied or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::IsProxy3216(IUnknown *punk)
+{
+ LPVOID pvVtbl, pvFn;
+ THUNK3216OBJ *pto3216;
+
+ // First check the initial entry in the vtable
+ // If it's not QueryInterfaceProxy3216 then this can't possibly
+ // be a 32/16 proxy
+ pvVtbl = *(void **)punk;
+ pvFn = *(void **)pvVtbl;
+ if (pvFn == ::QueryInterfaceProxy3216)
+ {
+ DWORD dwKey;
+ POSITION pos;
+
+ // This object has a proxy's vtable but it may be dead, copied
+ // or coincidentally correct random memory, so look for it in
+ // the table
+
+ pos = _pProxyTbl3216->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ if (pto3216 == (THUNK3216OBJ *)punk)
+ {
+ return (VPVOID)dwKey;
+ }
+ }
+
+ // Check to see if we're returning no for what we think is
+ // a valid proxy
+ // It's possible for this to occur but it's very unlikely
+ thkAssert(pto3216->dwSignature != PSIG3216);
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindProxy3216
+//
+// Synopsis: retrieves a 32/16 proxy
+//
+// Arguments: [ptoPrealloc] - Preallocated proxy or NULL
+// [vpvThis16] -- 16 bit object (key)
+// [iidx] - Custom interface or known index
+// [pfst] - Status return
+//
+// Returns: pointer to 32/16 proxy or real object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::FindProxy3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvThis16,
+ IIDIDX iidx,
+ DWORD *pfst)
+{
+ IUnknown *punk;
+ THUNK3216OBJ *pto;
+ THKSTATE thkstate;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy3216(%p, %p, %s)\n",
+ NestingLevelString(), ptoPrealloc, vpvThis16,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(vpvThis16 != 0);
+
+ // If we preallocated a proxy with an IID then a request was added
+ // in CanGetNewProxy. Clean it up now
+ if (ptoPrealloc != 0 && IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ thkstate = GetThkState();
+
+ // Check and see whether a proxy already exists for this object
+ pto = LookupProxy3216(vpvThis16);
+ if (pto != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 found existing proxy,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, pto));
+
+ // If a proxy's refcount is zero, it must be part of an aggregate
+ thkAssert(pto->cRefLocal > 0 ||
+ (pto->pphHolder != NULL &&
+ (pto->pphHolder->dwFlags & PH_AGGREGATE) != 0));
+
+ // We found an existing proxy, so use it
+ punk = (IUnknown *)pto;
+
+ // Check and see whether we need to promote the proxy
+ // This occurs in derivation situations where a less-specialized
+ // proxy already exists for the given object. For example,
+ // we might already have an IPersist proxy for this object when
+ // we're looking up IPersistFile. In such cases, we promote
+ // the proxy to the most derived interface
+ if (IIDIDX_IS_INDEX(iidx) &&
+ IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx))
+ {
+ pto->pfnVtbl =
+ (DWORD)athopiInterfaceThopis[IIDIDX_INDEX(iidx)].pt3216fn;
+ pto->iidx = iidx;
+ }
+
+ // AddRef the proxy we found since we're passing out a reference
+ AddRefProxy3216(pto);
+
+ if (pfst)
+ {
+ *pfst = FST_USED_EXISTING;
+ }
+
+ goto Exit;
+ }
+
+ // Check and see whether the object to be proxied is in fact a
+ // proxy itself. If it is, we can just return the real object
+ // rather than creating chains of proxies
+ if ( ( punk = IsProxy1632(vpvThis16)) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 shortcut proxy,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, punk));
+
+ // In the out parameter case, we are transferring ownership
+ // so we need to AddRef the thing we're returning
+ // Since we're shortcutting around a proxy we lose a reference
+ // to the proxy so release it
+ if (IsOutParamObj())
+ {
+ // vpvThis16 is a pointer to a proxy
+ // addref the real object and release the proxy
+
+ // We want to temporarily suspend our out state since
+ // we want this AddRef to really occur if it comes back
+ // to a proxy
+ SetThkState(THKSTATE_NOCALL);
+
+ punk->AddRef();
+
+ SetThkState(thkstate);
+
+ // Excel lands here with one too few addrefs so don't release
+ if (thkstate != THKSTATE_INVOKETHKOUT16_CLIENTSITE)
+ {
+ ReleaseProxy1632(vpvThis16);
+ }
+ }
+
+ if (pfst)
+ {
+ *pfst = FST_SHORTCUT;
+ }
+
+ goto Exit;
+ }
+
+ // We didn't find an existing proxy or shortcut so we need
+ // to create a new proxy for the given object
+ // We use preallocated memory if possible, otherwise we
+ // get a new proxy from the free list
+
+ if (ptoPrealloc != NULL)
+ {
+ pto = ptoPrealloc;
+
+ // Since we're using the preallocated proxy, mark it as used
+ // so we don't clean it up later
+ ptoPrealloc = NULL;
+ }
+ else
+ {
+ pto = (THUNK3216OBJ *)flFreeList32.AllocElement();
+ }
+
+ if (pto != NULL)
+ {
+ // Put the new proxy in the proxy table
+ if (!_pProxyTbl3216->SetAt(vpvThis16, pto))
+ {
+ // Note that we can put the new proxy back on the free
+ // list even if it's the preallocated proxy because
+ // that's what the prealloc cleanup does
+ flFreeList32.FreeElement((DWORD)pto);
+
+ pto = NULL;
+ goto Exit;
+ }
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // give out IUnknown for custom interfaces
+ iidx = INDEX_IIDIDX(THI_IUnknown);
+ }
+
+ punk = (IUnknown *)pto;
+
+ pto->pfnVtbl = (DWORD)athopiInterfaceThopis[iidx].pt3216fn;
+ pto->cRefLocal = 1;
+ pto->cRef = (IsOutParamObj()) ? 1 : 0;
+ pto->iidx = iidx;
+ pto->vpvThis16 = vpvThis16;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_NORMAL;
+
+
+#if DBG == 1
+ pto->dwSignature = PSIG3216;
+#endif
+
+ if (pfst)
+ {
+ *pfst = FST_CREATED_NEW;
+ }
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 created new proxy, %s (%p)->%p:(%d,%d)\n",
+ NestingLevelString(),
+ inInterfaceNames[pto->iidx].pszInterface,
+ vpvThis16, pto, pto->cRefLocal, pto->cRef));
+
+ }
+
+ Exit:
+ //
+ // If we are succeeding punk will not be NULL. Then do this hack for Excel
+ //
+ if ( punk != NULL && thkstate == THKSTATE_INVOKETHKOUT16_CLIENTSITE )
+ {
+ SetThkState(THKSTATE_NOCALL);
+ //
+ // Excel 5.0a has a bug where it doesn't addref the proxy
+ // that it returns from the IOleObject::GetClientSite call
+ // this means that we can't release the proxy or we'd kill it
+ // prematurely.
+ //
+ thkDebugOut((DEB_WARN, "FindProxy1632: "
+ "Addrefing proxy for compatability\n"));
+ AddRefOnObj16( vpvThis16 );
+
+ SetThkState(thkstate);
+ }
+
+ // If we haven't used the preallocated proxy, return it to the freelist
+ if (ptoPrealloc)
+ {
+ flFreeList32.FreeElement( (DWORD)ptoPrealloc );
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy3216: (%p)->%p\n",
+ NestingLevelString(), vpvThis16, punk));
+
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindAggregate3216
+//
+// Synopsis: finds/creates an aggregate
+//
+// Arguments: [ptoPrealloc] - Preallocated proxy or NULL
+// [vpvOuter16] -- controlling unknown
+// [vpvThis16] -- 16 bit object (key)
+// [iidx] - IID or index of interface
+//
+// Returns: 32/16 proxy object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::FindAggregate3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvOuter16,
+ VPVOID vpvThis16,
+ IIDIDX iidx)
+{
+ THUNK3216OBJ *pto3216;
+ IUnknown *punk;
+ DWORD fst;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindAggregate3216(%p, %p, %p, %s)\n",
+ NestingLevelString(), ptoPrealloc, vpvOuter16,
+ vpvThis16, IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(vpvThis16 != NULL && vpvOuter16 != NULL);
+
+ // Get back an object for the object to be proxied
+ // This may be a proxy or a real object from a shortcut
+ punk = FindProxy3216(ptoPrealloc, vpvThis16, iidx, &fst);
+ if (punk == NULL)
+ {
+ goto Exit;
+ }
+
+ // If we got an object and it's not a proxy, we're done
+ // There's nothing we can do since we can't link a real object to
+ // a holder; we can only hope that things work out right
+ if (fst & FST_OBJECT_STATUS)
+ {
+ goto Exit;
+ }
+
+ // Otherwise, we need to set up a holder for whatever proxies we
+ // have
+
+ THUNK1632OBJ UNALIGNED *pto1632;
+ PROXYHOLDER *pph;
+ IUnknown *punkProxiedObject;
+
+ // We know punk is a proxy
+ pto3216 = (THUNK3216OBJ *)punk;
+
+ // Determine whether the outer unknown is a proxy or not
+ punkProxiedObject = IsProxy1632(vpvOuter16);
+
+ // Get the proxy pointer if it is
+ if (punkProxiedObject != 0)
+ {
+ pto1632 = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
+ }
+
+ if (punkProxiedObject != 0 && pto1632->pphHolder != NULL)
+ {
+ // Use the existing holder if there is one
+ pph = pto1632->pphHolder;
+ }
+ else
+ {
+ // Create a new holder
+ pph = NewHolder(PH_AGGREGATE);
+ if (pph == NULL)
+ {
+ FreeProxy3216(vpvThis16);
+ punk = NULL;
+ goto Exit;
+ }
+
+ // If the outer unknown is a proxy we know its holder hasn't
+ // been set, so add it to the holder we created
+ if (punkProxiedObject != 0)
+ {
+ AddProxyToHolder(pph, pto1632, Pprx16(vpvOuter16));
+ }
+ }
+
+ thkAssert(punkProxiedObject == 0 || pto1632->pphHolder == pph);
+
+ // Add the new interface to the holder
+ // Since this proxy was just created, we know its holder
+ // hasn't been set yet
+ AddProxyToHolder(pph, pto3216, Pprx32(pto3216));
+
+ Exit:
+ if (punkProxiedObject != 0)
+ {
+ RELVDMPTR(vpvOuter16);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindAggregate3216,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, pto3216));
+
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterfaceProxy3216
+//
+// Synopsis: QueryInterface on the given proxy
+//
+// Arguments: [ptoThis] -- proxy object
+// [refiid] -- interface
+// [ppv] -- out parameter
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE CThkMgr::QueryInterfaceProxy3216(THUNK3216OBJ *ptoThis,
+ REFIID refiid,
+ LPVOID *ppv)
+{
+ SCODE scRet;
+ IUnknown *punkProxy;
+ VPVOID vpvUnk;
+ DWORD fst;
+
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ *ppv = NULL;
+
+ IIDIDX iidx = IidToIidIdx(refiid);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if (!AddIIDRequest(refiid))
+ {
+ return E_OUTOFMEMORY;
+ }
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy3216: unknown iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ }
+
+ // We force the object we're QI'ing to have a holder so that
+ // all objects have object refcounting. This should only be
+ // necessary for aggregation but it seems that some apps rely
+ // on all objects having aggregation-like refcounting qualities
+ // BobDay identified PowerPoint as one
+ // We only want to do this in cases where we've identified it's
+ // necessary, which presently is only for
+ // IDataObject
+ // so we only do it then
+
+ if (ptoThis->pphHolder == NULL && IsEqualIID(refiid, IID_IDataObject))
+ {
+ PROXYHOLDER *pph;
+
+ pph = NewHolder(PH_NONAGGREGATE);
+ if (pph == NULL)
+ {
+ scRet = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ AddProxyToHolder(pph, ptoThis, Pprx32(ptoThis));
+
+ // It's not necessary to clean this up if later calls fail
+ // since it doesn't alter the lifetime of the proxy if there's
+ // only one proxy for the holder
+ }
+
+ // see if the interface is supported
+ scRet = QueryInterfaceOnObj16(ptoThis->vpvThis16, refiid,
+ (void **)&vpvUnk);
+ if (FAILED(scRet))
+ {
+ goto Exit;
+ }
+
+ if (NULL == vpvUnk)
+ {
+ // Although it is invalid, an app can return NULL for the
+ // output interface and NOERROR for the result on a QueryInterface.
+ // Corel draw has this behavior. Anyway, we nullify these errors
+ // here.
+ scRet = E_NOINTERFACE;
+ goto Exit;
+ }
+
+ SetThkState(THKSTATE_INVOKETHKOUT32);
+
+ punkProxy = FindProxy3216(NULL, vpvUnk, iidx, &fst);
+ if (punkProxy == NULL)
+ {
+ // We were unable to create a proxy for the new interface so
+ // clean up the interface and quit
+
+ ReleaseOnObj16(vpvUnk);
+
+ scRet = E_OUTOFMEMORY;
+ goto ResetState;
+ }
+
+ *ppv = punkProxy;
+
+ // If we're returning a proxy, we need to make sure that
+ // it is listed in the proxy holder for this object
+ if (fst & FST_PROXY_STATUS)
+ {
+ THUNK3216OBJ *ptoProxy;
+
+ // We are returning a proxy. If its holder isn't set,
+ // add it to the holder of the object that was QI'ed
+
+ ptoProxy = (THUNK3216OBJ *)punkProxy;
+ if (ptoProxy->pphHolder == NULL)
+ {
+ if (ptoThis->pphHolder != NULL)
+ {
+ AddProxyToHolder(ptoThis->pphHolder, ptoProxy,
+ Pprx32(ptoProxy));
+ }
+ }
+ else if (ptoThis->pphHolder == NULL)
+ {
+ // ptoThis may not have a holder because it was produced
+ // by a non-QI method such as IOleItemContainer::GetObject
+ // If we find that an interface returned by it does
+ // have a holder, hook it up to the holder
+
+ // It shouldn't be necessary to do anything unusual with
+ // local references even if ptoThis is really part of an
+ // aggregate since ptoThis must have been produced by
+ // a method where aggregation can't be assumed and all
+ // references must be released on ptoThis itself
+ AddProxyToHolder(ptoProxy->pphHolder, ptoThis,
+ Pprx32(ptoThis));
+ }
+
+#if DBG == 1
+ // It's possible for holders to not match because of the above
+ // case with interfaces being returned from non-QI methods
+ // The lifetime for such interfaces must be defined by
+ // strong references, though, so it's not catastrophic
+ // Still, we'd like to be aware of such mismatches just in case
+ if (ptoProxy->pphHolder != ptoThis->pphHolder)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy3216: "
+ "this %p has holder %p, proxy %p has holder %p\n",
+ ptoThis, ptoThis->pphHolder,
+ ptoProxy, ptoProxy->pphHolder));
+ }
+#endif
+ }
+
+ ResetState:
+ SetThkState(THKSTATE_NOCALL);
+
+ Exit:
+ // Clean up our custom interface request if necessary
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ RemoveIIDRequest(refiid);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceProxy3216(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), ptoThis, *ppv, scRet));
+
+ return scRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddRefProxy3216
+//
+// Synopsis: addref on the given object - can addref the real object
+//
+// Arguments: [ptoThis] -- proxy object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::AddRefProxy3216(THUNK3216OBJ *ptoThis)
+{
+ PROXYHOLDER *pph;
+ BOOL fAggregate;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s AddRefProxy3216 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ ptoThis, ptoThis->cRefLocal, ptoThis->cRef ));
+
+
+ pph = ptoThis->pphHolder;
+ if (pph && (pph->dwFlags & PH_AGGREGATE_RELEASE))
+ {
+ // we are about to call release on pUnkOuter
+ // Release on PUnk was called and addref or release
+ // calls to pUnkOuter are not supposted to be passed
+ // on any more
+ thkDebugOut((DEB_THUNKMGR, "%s About to addref pUnkOuter3216(%p)\n",
+ NestingLevelString(), ptoThis));
+
+ goto Exit;
+ }
+
+ // Always increment the proxy local refcount
+ LocalAddRefProxy(ptoThis);
+
+ // Aggregations rely on all reference counts being forwarded on
+ // to the controlling unknown. Therefore, if we have a proxy
+ // that is part of an aggregate, we must ensure that the proxy
+ // doesn't collect references locally. If it did, they would
+ // not be passed on to the controlling unknown (via the real object)
+ // and the controlling unknown's refcount would be too low
+ if (ptoThis->pphHolder == NULL)
+ {
+ fAggregate = FALSE;
+ }
+ else
+ {
+ fAggregate = (ptoThis->pphHolder->dwFlags & PH_AGGREGATE) != 0;
+ }
+
+ if (IsOutParamObj())
+ {
+ // If we're on the way out we're assuming that the object
+ // given to us has its own reference so we bump cRef to
+ // indicate that but we don't call the real object
+ ptoThis->cRef++;
+ }
+ else if (ptoThis->cRef == 0 || fAggregate)
+ {
+ DWORD dwRet;
+
+ // It's also necessary to pass on real references when the
+ // ref count is zero. This handles the case where an
+ // in parameter, created as 1,0, is AddRef'ed after
+ // its creation, in which case the reference needs to
+ // be passed on to the real object so that the proxy has
+ // at least one real reference since it will stay alive
+ ptoThis->cRef++;
+ dwRet = AddRefOnObj16(ptoThis->vpvThis16);
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s AddRefProxy3216: AddRef called on (%p):%ld\n",
+ NestingLevelString(), ptoThis->vpvThis16, dwRet));
+ }
+ else
+ {
+ // Local-only AddRef
+ }
+
+Exit:
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy3216(%p),(%ld,%ld)\n",
+ NestingLevelString(), ptoThis, ptoThis->cRefLocal,
+ ptoThis->cRef));
+
+ return ptoThis->cRefLocal;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseProxy3216
+//
+// Synopsis: release on the proxy or aggregate
+//
+// Arguments: [ptoThis] -- proxy object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::ReleaseProxy3216(THUNK3216OBJ *ptoThis)
+{
+ PROXYHOLDER *pph;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s ReleaseProxy3216 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ ptoThis, ptoThis->cRefLocal, ptoThis->cRef ));
+
+ pph = ptoThis->pphHolder;
+ if (pph && (pph->dwFlags & PH_AGGREGATE_RELEASE))
+ {
+ // we are about to call release on pUnkOuter
+ // Release on PUnk was called and addref and
+ // release calls to pUnkOuter are not supposted
+ // to be passed on any more
+ thkDebugOut((DEB_THUNKMGR, "%s About to release pUnkOuter3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ thkDebugOut((DEB_THUNKMGR, "%s ReleaseProxy3216 pUnkOuter stop passing releases on(%p) => %ld,%ld\n",
+ NestingLevelString(), ptoThis,
+ ptoThis ? ptoThis->cRefLocal : 0 ,
+ ptoThis ? ptoThis->cRef : 0));
+
+ if (ptoThis->cRef == 0 && ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ goto Done;
+ }
+ }
+
+
+ // If our local refcount is the same as the count of references
+ // that we've passed on to the object, then we need to pass
+ // on this release to the real object
+ if (ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ DWORD dwRet;
+
+ thkAssert(ptoThis->cRef > 0);
+
+ dwRet = ReleaseOnObj16(ptoThis->vpvThis16);
+
+ // Decrement cRef after making the real call to ensure that
+ // the proxy lives throughout the call
+ --ptoThis->cRef;
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy3216: Release called on (%p):%ld \n",
+ NestingLevelString(), ptoThis->vpvThis16, dwRet));
+ }
+
+ // Now that we've handled the real object's refcount, decrement
+ // the proxy's refcount and clean it up if necessary
+ thkAssert(ptoThis->cRefLocal > 0);
+ if (--ptoThis->cRefLocal == 0)
+ {
+ // Proxies that have no outer unknown can be cleaned
+ // up immediately. If they do have an outer unknown then
+ // they must live as long as the entire object lives,
+ // so we don't clean them up here. They'll be cleaned up
+ // when the object dies
+
+ if (ptoThis->pphHolder)
+ {
+ // If this proxy isn't part of an aggregate, remove it
+ // from the proxy list so it can't be reused
+ // The only thing this proxy will be good for is
+ // calling through
+ if ((ptoThis->pphHolder->dwFlags & PH_AGGREGATE) == 0)
+ {
+ _pProxyTbl3216->RemoveKey((DWORD)ptoThis->vpvThis16);
+ }
+
+ // We have a holder, so notify it that one of its
+ // proxies just died
+ // This can cause cleanup of all proxies if the
+ // holder releases to zero
+ ReleaseHolder(ptoThis->pphHolder);
+ }
+ else
+ {
+ // We don't have a holder so we can clean up this proxy
+ // immediately
+
+ RemoveProxy3216(ptoThis);
+ }
+
+ ptoThis = NULL;
+
+ DBG_DUMP(DebugDump3216());
+ }
+Done:
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy3216(%p) => %ld,%ld\n",
+ NestingLevelString(), ptoThis,
+ ptoThis ? ptoThis->cRefLocal : 0 ,
+ ptoThis ? ptoThis->cRef : 0));
+
+ return ptoThis ? ptoThis->cRefLocal : 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::ReleaseUnreferencedProxy3216, public
+//
+// Synopsis: Releases a proxy in the special case where the proxy
+// was created for a non-addrefed object
+//
+// Arguments: [ptoThis] - 32/16 proxy
+//
+// History: 11-Jul-94 DrewB Created
+//
+// Notes: Needed to clean up proxies from DebugServerQueryInterface
+// in DebugServerRelease
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::ReleaseUnreferencedProxy3216(THUNK3216OBJ *ptoThis)
+{
+ thkAssert(IsProxy3216((IUnknown *)ptoThis) != 0);
+
+ // Since the object is non-addref'ed, we have to be careful
+ // to ensure that the ReleaseProxy call doesn't end up releasing
+ // the real object, so we force cRef to be different from
+ // cRefLocal. We know that DebugServerQueryInterface gave the
+ // proxy a cRef because it's an out parameter, so we should
+ // always be able to decrement cRef and achieve the desired
+ // effect
+
+ thkAssert(ptoThis->cRef > 0);
+ ptoThis->cRef--;
+
+ // Now release the proxy to clean it up
+ // If it was addref'ed, this will just remove a local reference
+ // If it wasn't, this will clean up the proxy
+ // In both cases, no Release should occur on the real object
+
+ thkAssert(ptoThis->cRefLocal != ptoThis->cRef);
+
+ ReleaseProxy3216(ptoThis);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeProxy3216
+//
+// Synopsis: releases the object for the given vpUnk16 (key)
+//
+// Arguments: [vpvObj16] - Proxy or object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::FreeProxy3216(VPVOID vpvObj16)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeProxy3216(%p)\n",
+ NestingLevelString(), vpvObj16));
+
+ DWORD dwRet = 0;
+ THUNK3216OBJ *pto;
+
+ thkAssert(vpvObj16 != 0);
+
+ // get the object by the 16 bit this pointer
+ pto = LookupProxy3216(vpvObj16);
+ if (pto != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR, "%sFreeProxy3216(%p) "
+ "found existing proxy %p\n",
+ NestingLevelString(), vpvObj16, pto));
+
+ dwRet = ReleaseProxy3216(pto);
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeProxy3216(%p):%ld \n",
+ NestingLevelString(), vpvObj16, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveProxy3216, public
+//
+// Synopsis: Destroys the given proxy
+//
+// Arguments: [pto] - Flat proxy pointer
+//
+// History: 11-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveProxy3216(THUNK3216OBJ *pto)
+{
+ _pProxyTbl3216->RemoveKey((DWORD)pto->vpvThis16);
+
+ if ((pto->grfFlags & PROXYFLAG_LOCKED) == 0)
+ {
+#if DBG == 1
+ pto->dwSignature = PSIG3216DEAD;
+ if (!fSaveProxy)
+#endif
+ {
+ flFreeList32.FreeElement((DWORD)pto);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::PrepareForCleanup, public
+//
+// Synopsis: Marks the 3216 Proxies so that OLE32 cannot call them.
+//
+// Arguments: -none-
+//
+// History: 24-Aug-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::PrepareForCleanup( void )
+{
+ POSITION pos;
+ DWORD dwKey;
+ THUNK3216OBJ *pto3216;
+
+ //
+ // CODEWORK: OLE32 should be setup so that it doesn't callback while the
+ // thread is detaching. Then this function becomes obsolete.
+ //
+
+ // delete the 3216 proxy table
+ pos = _pProxyTbl3216->GetStartPosition();
+
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ thkDebugOut((DEB_IWARN, "Preparing 3216 Proxy for cleanup: "
+ "%08lX %08lX %s\n",
+ pto3216,
+ pto3216->vpvThis16,
+ IidIdxString(pto3216->iidx)));
+
+ pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
+ }
+}
+
+#if DBG == 1
+void CThkMgr::DebugDump3216()
+{
+ THUNK3216OBJ *pto3216;
+ DWORD dwKey;
+ POSITION pos;
+
+ thkDebugOut((DEB_THUNKMGR, "%s DebugDump3216\n",NestingLevelString()));
+
+ pos = _pProxyTbl3216->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+ thkDebugOut((DEB_THUNKMGR,
+ "%s Proxy3216:Key:%p->%p, (%s) (%d,%d)\n",
+ NestingLevelString(), dwKey, pto3216,
+ IidIdxString(pto3216->iidx), pto3216->cRefLocal,
+ pto3216->cRef));
+ }
+}
+
+
+void CThkMgr::DebugDump1632()
+{
+ THUNK1632OBJ UNALIGNED *pto1632;
+ DWORD dwKey;
+ VPVOID vpv;
+ POSITION pos;
+
+ thkDebugOut((DEB_THUNKMGR, "%s DebugDump1632\n",NestingLevelString()));
+
+ pos = _pProxyTbl1632->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkDebugOut((DEB_THUNKMGR,
+ "%s Proxy1632:key:%p->%p, (%s) (%d,%d)\n",
+ NestingLevelString(), dwKey, pto1632,
+ IidIdxString(pto1632->iidx), pto1632->cRefLocal,
+ pto1632->cRef));
+ RELVDMPTR(vpv);
+ }
+}
+#endif
diff --git a/private/ole32/olethunk/olethk32/cthkmgr.hxx b/private/ole32/olethunk/olethk32/cthkmgr.hxx
new file mode 100644
index 000000000..affb7a206
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/cthkmgr.hxx
@@ -0,0 +1,243 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cthkmgr.hxx
+//
+// Contents: CThkMgr deklaration
+//
+// Classes: CThkMgr
+//
+// Functions:
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CTHKMGR_HXX__
+#define __CTHKMGR_HXX__
+
+//
+// Describes a request for a custom interface
+//
+typedef struct tagIIDNODE IIDNODE, *PIIDNODE;
+struct tagIIDNODE
+{
+ IID *piid;
+ PIIDNODE pNextNode;
+};
+
+//
+// state of thunk call - before or after the 32 or 16 bit call
+//
+typedef enum
+{
+ THKSTATE_NOCALL = 0x0000,
+ THKSTATE_INVOKETHKIN32 = 0x0001,
+ THKSTATE_INVOKETHKOUT32 = 0x0002,
+ THKSTATE_INVOKETHKIN16 = 0x0004,
+ THKSTATE_INVOKETHKOUT16 = 0x0008,
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE = 0x0010
+} THKSTATE;
+
+#define THKSTATE_OUT (THKSTATE_INVOKETHKOUT32 | THKSTATE_INVOKETHKOUT16 | \
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CThkMgr ()
+//
+// Purpose:
+//
+// Interface: QueryInterface --
+// AddRef --
+// Release --
+// IsIIDRequested --
+// SetThkState --
+// IsIIDSupported --
+// AddIIDRequest --
+// RemoveIIDRequest --
+// ResetThkState --
+// GetThkState --
+// IsOutParamObj --
+// IsProxy1632 --
+// FreeProxy1632 --
+// QueryInterfaceProxy1632 --
+// AddRefProxy1632 --
+// ReleaseProxy1632 --
+// IsProxy3216 --
+// FreeProxy3216 --
+// QueryInterfaceProxy3216 --
+// AddRefProxy3216 --
+// ReleaseProxy3216 --
+// PrepareForCleanup --
+// DebugDump3216 --
+// Create --
+// ~CThkMgr --
+// CThkMgr --
+// _cRefs --
+// _thkstate --
+// _pProxyTbl3216 --
+// _pProxyTbl1632 --
+// _pCFL1632 --
+// _pCFL3216 --
+// _piidnode --
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+// Returns from FindProxy
+#define FST_CREATED_NEW 1
+#define FST_USED_EXISTING 2
+#define FST_SHORTCUT 4
+
+#define FST_PROXY_STATUS (FST_CREATED_NEW | FST_USED_EXISTING)
+#define FST_OBJECT_STATUS (FST_SHORTCUT)
+
+class CThkMgr : public IThunkManager
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IThunkManager methods ***
+ STDMETHOD_(BOOL, IsIIDRequested) (THIS_ REFIID riid);
+ STDMETHOD_(BOOL, IsCustom3216Proxy) (THIS_ IUnknown *punk,
+ REFIID riid);
+
+ // private methods
+ THKSTATE GetThkState(void)
+ {
+ return _thkstate;
+ };
+ void SetThkState(THKSTATE thkstate)
+ {
+ _thkstate = thkstate;
+ };
+ BOOL IsOutParamObj(void)
+ {
+ return (_thkstate & THKSTATE_OUT) != 0;
+ }
+
+ BOOL IsIIDSupported (REFIID riid);
+ BOOL AddIIDRequest (REFIID riid);
+ void RemoveIIDRequest (REFIID riid);
+
+ void LocalAddRefProxy(CProxy *pprx);
+ void LockProxy(CProxy *pprx);
+
+ VPVOID CanGetNewProxy1632(IIDIDX iidx);
+ void FreeNewProxy1632(VPVOID vpv, IIDIDX iidx);
+
+ IUnknown *IsProxy1632(VPVOID vpvObj16);
+ VPVOID LookupProxy1632(IUnknown *punkThis32)
+ {
+ VPVOID vpv;
+
+ if (_pProxyTbl1632->Lookup((DWORD)punkThis32, (void*&)vpv))
+ {
+ return vpv;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ VPVOID FindProxy1632(VPVOID vpvPrealloc,
+ IUnknown *punkThis32,
+ IIDIDX iidx,
+ DWORD *pfst);
+ VPVOID FindAggregate1632(VPVOID vpvPrealloc,
+ IUnknown *punkOuter32,
+ IUnknown *punkThis32,
+ IIDIDX iidx);
+ DWORD FreeProxy1632(IUnknown *pUnk32);
+ void RemoveProxy1632(VPVOID vpv, THUNK1632OBJ *pto);
+
+ SCODE QueryInterfaceProxy1632(VPVOID vpvThis16,
+ REFIID refiid,
+ LPVOID *ppv);
+ DWORD AddRefProxy1632(VPVOID vpvThis16);
+ DWORD ReleaseProxy1632(VPVOID vpvThis16);
+
+ THUNK3216OBJ *CanGetNewProxy3216(IIDIDX iidx);
+ void FreeNewProxy3216(THUNK3216OBJ *ptoProxy, IIDIDX iidx);
+
+ VPVOID IsProxy3216(IUnknown *punkObj);
+ THUNK3216OBJ *LookupProxy3216(VPVOID vpvObj16)
+ {
+ THUNK3216OBJ *pto;
+
+ if (_pProxyTbl3216->Lookup((DWORD)vpvObj16, (void *&)pto))
+ {
+ return pto;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ IUnknown *FindProxy3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvThis16,
+ IIDIDX iidx,
+ DWORD *pfst);
+ IUnknown *FindAggregate3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvOuter16,
+ VPVOID vpvThis16,
+ IIDIDX iidx);
+ DWORD FreeProxy3216(VPVOID vpUnk16);
+ void RemoveProxy3216(THUNK3216OBJ *pto);
+
+ SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto,
+ REFIID refiid,
+ LPVOID *ppv);
+ DWORD AddRefProxy3216(THUNK3216OBJ *pto);
+ DWORD ReleaseProxy3216(THUNK3216OBJ *pto);
+ void ReleaseUnreferencedProxy3216(THUNK3216OBJ *pto);
+
+ void PrepareForCleanup( void );
+
+#if DBG == 1
+ void DebugDump1632(void);
+ void DebugDump3216(void);
+#endif
+
+ void RemoveAllProxies(void);
+
+ // creation
+ static CThkMgr * Create(void);
+ ~CThkMgr();
+
+private:
+ CThkMgr(CMapDwordPtr *pPT1632, CMapDwordPtr *pPT3216);
+
+ LONG _cRefs;
+ THKSTATE _thkstate;
+
+ CMapDwordPtr *_pProxyTbl3216;
+ CMapDwordPtr *_pProxyTbl1632;
+
+ // list of requested iids
+ PIIDNODE _piidnode;
+
+ // List of proxy holders for controlling unknowns
+ PROXYHOLDER *_pphHolders;
+
+ // Holder manipulation routines
+ void ReleaseHolder(PROXYHOLDER *pph);
+ inline void AddRefHolder(PROXYHOLDER *pph);
+ void AddProxyToHolder(PROXYHOLDER *pph,
+ CProxy *pprxReal,
+ PROXYPTR &pprx);
+ PROXYHOLDER *NewHolder(DWORD dwFlags);
+};
+
+#endif // ifndef __CTHKMGR_HXX__
diff --git a/private/ole32/olethunk/olethk32/daytona/makefile b/private/ole32/olethunk/olethk32/daytona/makefile
new file mode 100644
index 000000000..734e18727
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the subcomponents of NTOS.
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/olethk32/daytona/olethk32.def b/private/ole32/olethunk/olethk32/daytona/olethk32.def
new file mode 100644
index 000000000..722e5dbdc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/olethk32.def
@@ -0,0 +1,27 @@
+#ifdef FLAT
+
+LIBRARY OLETHK32
+
+DESCRIPTION '32-bit Ole 2.0 Interoperability Code'
+
+EXPORTS
+ InvokeOn32 @3
+ IntOpInitialize @4
+ CallbackProcessing_3216 @5
+ IUnknownObj32 @6
+ CSm16ReleaseHandler_Release32 @8
+ ThkMgrInitialize @9
+ ThkMgrUninitialize @10
+ TransformHRESULT_1632 @11
+ TransformHRESULT_3216 @12
+ ConvertObjDescriptor @13
+ ConvertHr1632Thunk @14
+ ConvertHr3216Thunk @15
+ IntOpUninitialize @16
+ ThkAddAppCompatFlag @18
+#if DBG == 1
+ ThkCallOutputFunctions @19
+#endif
+
+#endif // FLAT
+
diff --git a/private/ole32/olethunk/olethk32/daytona/sources b/private/ole32/olethunk/olethk32/daytona/sources
new file mode 100644
index 000000000..d838f82b5
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/sources
@@ -0,0 +1,103 @@
+!IF 0
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Standard definitions file for olethk32.dll, the OLE 2.0 interoperability
+ 32-bit thunk handler.
+
+Author:
+
+ Bob Day (bobday) 18-Feb-1994
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+# ..\..\com\coll\daytona\obj\*\coll.lib
+
+!ENDIF
+
+MAJORCOMP=cairole
+MINORCOMP=interop
+
+TARGETNAME=olethk32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntvdm.lib \
+ $(BASEDIR)\public\sdk\lib\*\oemuni.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\wow32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ ..\..\..\common\cruntime\daytona\obj\*\cruntime.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+INCLUDES=..\.; \
+ $(BASEDIR)\public\sdk\inc; \
+ ..\..\h; \
+ ..\..\..\ih;
+
+
+#
+# 0x6000000 should be fairly safe even though it is in usermode address range.
+# This DLL should only be loaded by WOW and since WOW doesn't normally load any
+# usermode DLLs, we can get away with loading it wherever we want. Feel free
+# to move it about if you really understand coffbase.txt. -BobDay
+#
+DLLBASE=0x6000000
+DLLENTRY=DllEntryPoint
+DLLDEF=obj\*\olethk32.def
+
+C_DEFINES=$(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE
+
+!IF $(386)
+USE_NOLIBS=1
+!ELSE
+USE_CRTDLL=1
+!ENDIF
+
+SOURCES=\
+ ..\dllentry.cxx \
+ ..\tlsthk.cxx \
+ ..\thkmgr.cxx \
+ ..\freelist.cxx \
+ ..\cthkmgr.cxx \
+ ..\olethk32.cxx \
+ ..\inv16.cxx \
+ ..\inv32.cxx \
+ ..\thoputil.cxx \
+ ..\thop16.cxx \
+ ..\thop32.cxx \
+ ..\thopiint.cxx \
+ ..\tc1632.cxx \
+ ..\thtblapi.cxx \
+ ..\vtblapi.cxx \
+ ..\iidtothi.cxx \
+ ..\dbgapi.cxx \
+ ..\dbgitbl.cxx \
+ ..\map_kv.cxx \
+ ..\plex.cxx \
+ ..\apinot.cxx \
+ ..\olethk32.rc \
+ ..\alias.cxx \
+ ..\mmodel.cxx \
+ ..\stalloc.cxx \
+ ..\heap.cxx
+
+PRECOMPILED_INCLUDE=..\headers.cxx
+PRECOMPILED_PCH=headers.pch
+PRECOMPILED_OBJ=headers.obj
diff --git a/private/ole32/olethunk/olethk32/dbgapi.cxx b/private/ole32/olethunk/olethk32/dbgapi.cxx
new file mode 100644
index 000000000..f69ec776c
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgapi.cxx
@@ -0,0 +1,127 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#if DBG == 1
+
+char *apszApiNames[] =
+{
+ "CoInitialize"
+, "CoUninitialize"
+, "CoGetClassObject"
+, "CoRegisterClassObject"
+, "CoRevokeClassObject"
+, "CoMarshalInterface"
+, "CoUnmarshalInterface"
+, "CoReleaseMarshalData"
+, "CoDisconnectObject"
+, "CoLockObjectExternal"
+, "CoGetStandardMarshal"
+, "CoIsHandlerConnected"
+, "CoFreeAllLibraries"
+, "CoFreeUnusedLibraries"
+, "CoCreateInstance"
+, "CLSIDFromString"
+, "CoIsOle1Class"
+, "ProgIDFromCLSID"
+, "CLSIDFromProgID"
+, "CoCreateGuid"
+, "CoFileTimeToDosDateTime"
+, "CoDosDateTimeToFileTime"
+, "CoFileTimeNow"
+, "CoRegisterMessageFilter"
+, "CoGetTreatAsClass"
+, "CoTreatAsClass"
+, "DllGetClassObject"
+, "StgCreateDocfile"
+, "StgCreateDocfileOnILockBytes"
+, "StgOpenStorage"
+, "StgOpenStorageOnILockBytes"
+, "StgIsStorageFile"
+, "StgIsStorageILockBytes"
+, "StgSetTimes"
+, "CreateDataAdviseHolder"
+, "CreateDataCache"
+, "BindMoniker"
+, "MkParseDisplayName"
+, "MonikerRelativePathTo"
+, "MonikerCommonPrefixWith"
+, "CreateBindCtx"
+, "CreateGenericComposite"
+, "GetClassFile"
+, "CreateFileMoniker"
+, "CreateItemMoniker"
+, "CreateAntiMoniker"
+, "CreatePointerMoniker"
+, "GetRunningObjectTable"
+, "ReadClassStg"
+, "WriteClassStg"
+, "ReadClassStm"
+, "WriteClassStm"
+, "WriteFmtUserTypeStg"
+, "ReadFmtUserTypeStg"
+, "OleInitialize"
+, "OleUninitialize"
+, "OleQueryLinkFromData"
+, "OleQueryCreateFromData"
+, "OleCreate"
+, "OleCreateFromData"
+, "OleCreateLinkFromData"
+, "OleCreateStaticFromData"
+, "OleCreateLink"
+, "OleCreateLinkToFile"
+, "OleCreateFromFile"
+, "OleLoad"
+, "OleSave"
+, "OleLoadFromStream"
+, "OleSaveToStream"
+, "OleSetContainedObject"
+, "OleNoteObjectVisible"
+, "RegisterDragDrop"
+, "RevokeDragDrop"
+, "DoDragDrop"
+, "OleSetClipboard"
+, "OleGetClipboard"
+, "OleFlushClipboard"
+, "OleIsCurrentClipboard"
+, "OleCreateMenuDescriptor"
+, "OleSetMenuDescriptor"
+, "OleDestroyMenuDescriptor"
+, "OleDraw"
+, "OleRun"
+, "OleIsRunning"
+, "OleLockRunning"
+, "CreateOleAdviseHolder"
+, "OleCreateDefaultHandler"
+, "OleCreateEmbeddingHelper"
+, "OleRegGetUserType"
+, "OleRegGetMiscStatus"
+, "OleRegEnumFormatEtc"
+, "OleRegEnumVerbs"
+, "OleConvertIStorageToOLESTREAM"
+, "OleConvertOLESTREAMToIStorage"
+, "OleConvertIStorageToOLESTREAMEx"
+, "OleConvertOLESTREAMToIStorageEx"
+, "OleDoAutoConvert"
+, "OleGetAutoConvert"
+, "OleSetAutoConvert"
+, "GetConvertStg"
+, "SetConvertStg"
+, "ReadOleStg"
+, "WriteOleStg"
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dbgint.cxx b/private/ole32/olethunk/olethk32/dbgint.cxx
new file mode 100644
index 000000000..5dd572448
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgint.cxx
@@ -0,0 +1,682 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+char *apszIUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+};
+char *apszIClassFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateInstance"
+, "LockServer"
+};
+char *apszIMarshalNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetUnmarshalClass"
+, "GetMarshalSizeMax"
+, "MarshalInterface"
+, "UnmarshalInterface"
+, "ReleaseMarshalData"
+, "DisconnectObject"
+};
+char *apszIStdMarshalInfoNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassForHandler"
+};
+char *apszIMessageFilterNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "HandleInComingCall"
+, "RetryRejectedCall"
+, "MessagePending"
+};
+char *apszIExternalConnectionNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "AddConnection"
+, "ReleaseConnection"
+};
+char *apszIEnumStringNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATSTGNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszILockBytesNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ReadAt"
+, "WriteAt"
+, "Flush"
+, "SetSize"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+};
+char *apszIStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Read"
+, "Write"
+, "Seek"
+, "SetSize"
+, "CopyTo"
+, "Commit"
+, "Revert"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+, "Clone"
+};
+char *apszIStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateStream"
+, "OpenStream"
+, "CreateStorage"
+, "OpenStorage"
+, "CopyTo"
+, "MoveElementTo"
+, "Commit"
+, "Revert"
+, "EnumElements"
+, "DestroyElement"
+, "RenameElement"
+, "SetElementTimes"
+, "SetClass"
+, "SetStateBits"
+, "Stat"
+};
+char *apszIRootStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SwitchToFile"
+};
+char *apszIEnumFORMATETCNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATDATANames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIDataObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetData"
+, "GetDataHere"
+, "QueryGetData"
+, "GetCanonicalFormatEtc"
+, "SetData"
+, "EnumFormatEtc"
+, "DAdvise"
+, "DUnadvise"
+, "EnumDAdvise"
+};
+char *apszIViewObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+};
+char *apszIViewObject2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+, "GetExtent"
+};
+char *apszIAdviseSinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+};
+char *apszIAdviseSink2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+, "OnLinkSrcChange"
+};
+char *apszIDataAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnDataChange"
+};
+char *apszIOleCacheNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+};
+char *apszIOleCache2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+, "UpdateCache"
+, "DiscardCache"
+};
+char *apszIOleCacheControlNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnRun"
+, "OnStop"
+};
+char *apszIDropTargetNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "DragEnter"
+, "DragOver"
+, "DragLeave"
+, "Drop"
+};
+char *apszIDropSourceNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "QueryContinueDrag"
+, "GiveFeedback"
+};
+char *apszIPersistNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+};
+char *apszIPersistStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "InitNew"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "HandsOffStorage"
+};
+char *apszIPersistStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+};
+char *apszIPersistFileNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "GetCurFile"
+};
+char *apszIBindCtxNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RegisterObjectBound"
+, "RevokeObjectBound"
+, "ReleaseBoundObjects"
+, "SetBindOptions"
+, "GetBindOptions"
+, "GetRunningObjectTable"
+, "RegisterObjectParam"
+, "GetObjectParam"
+, "EnumObjectParam"
+, "RevokeObjectParam"
+};
+char *apszIMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+, "BindToObject"
+, "BindToStorage"
+, "Reduce"
+, "ComposeWith"
+, "Enum"
+, "IsEqual"
+, "Hash"
+, "IsRunning"
+, "GetTimeOfLastChange"
+, "Inverse"
+, "CommonPrefixWith"
+, "RelativePathTo"
+, "GetDisplayName"
+, "ParseDisplayName"
+, "IsSystemMoniker"
+};
+char *apszIRunningObjectTableNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Register"
+, "Revoke"
+, "IsRunning"
+, "GetObject"
+, "NoteChangeTime"
+, "GetTimeOfLastChange"
+, "EnumRunning"
+};
+char *apszIEnumMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumOLEVERBNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIOleObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetClientSite"
+, "GetClientSite"
+, "SetHostNames"
+, "Close"
+, "SetMoniker"
+, "GetMoniker"
+, "InitFromData"
+, "GetClipboardData"
+, "DoVerb"
+, "EnumVerbs"
+, "Update"
+, "IsUpToDate"
+, "GetUserClassID"
+, "GetUserType"
+, "SetExtent"
+, "GetExtent"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "GetMiscStatus"
+, "SetColorScheme"
+};
+char *apszIOleClientSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SaveObject"
+, "GetMoniker"
+, "GetContainer"
+, "ShowObject"
+, "OnShowWindow"
+, "RequestNewObjectLayout"
+};
+char *apszIRunnableObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetRunningClass"
+, "Run"
+, "IsRunning"
+, "LockRunning"
+, "SetContainedObject"
+};
+char *apszIParseDisplayNameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+};
+char *apszIOleContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+};
+char *apszIOleItemContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+, "GetObject"
+, "GetObjectStorage"
+, "IsRunning"
+};
+char *apszIOleAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnRename"
+, "SendOnSave"
+, "SendOnClose"
+};
+char *apszIOleLinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetUpdateOptions"
+, "GetUpdateOptions"
+, "SetSourceMoniker"
+, "GetSourceMoniker"
+, "SetSourceDisplayName"
+, "GetSourceDisplayName"
+, "BindToSource"
+, "BindIfRunning"
+, "GetBoundSource"
+, "UnbindSource"
+, "Update"
+};
+char *apszIOleWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+};
+char *apszIOleInPlaceObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "InPlaceDeactivate"
+, "UIDeactivate"
+, "SetObjectRects"
+, "ReactivateAndUndo"
+};
+char *apszIOleInPlaceActiveObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "TranslateAccelerator"
+, "OnFrameWindowActivate"
+, "OnDocWindowActivate"
+, "ResizeBorder"
+, "EnableModeless"
+};
+char *apszIOleInPlaceUIWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+};
+char *apszIOleInPlaceFrameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+, "InsertMenus"
+, "SetMenu"
+, "RemoveMenus"
+, "SetStatusText"
+, "EnableModeless"
+, "TranslateAccelerator"
+};
+char *apszIOleInPlaceSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "CanInPlaceActivate"
+, "OnInPlaceActivate"
+, "OnUIActivate"
+, "GetWindowContext"
+, "Scroll"
+, "OnUIDeactivate"
+, "OnInPlaceDeactivate"
+, "DiscardUndoState"
+, "DeactivateAndUndo"
+, "OnPosRectChange"
+};
+char *apszIRpcChannelBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetBuffer"
+, "SendReceive"
+, "FreeBuffer"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+, "DebugServerQueryInterface"
+, "DebugServerRelease"
+};
+char *apszIPSFactoryBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+char *apszIRpcChannelNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetStream"
+, "Call"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+};
+char *apszIPSFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dbginv.hxx b/private/ole32/olethunk/olethk32/dbginv.hxx
new file mode 100644
index 000000000..274e0dd09
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbginv.hxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbginv.hxx
+//
+// Contents: Header for invocation debugging
+//
+// History: 08-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DBGINV_HXX__
+#define __DBGINV_HXX__
+
+typedef struct _INTERFACENAMES
+{
+ char *pszInterface;
+ char **ppszMethodNames;
+} INTERFACENAMES;
+
+extern INTERFACENAMES inInterfaceNames[];
+extern char *apszApiNames[];
+
+#endif // #ifndef __DBGINV_HXX__
diff --git a/private/ole32/olethunk/olethk32/dbgitbl.cxx b/private/ole32/olethunk/olethk32/dbgitbl.cxx
new file mode 100644
index 000000000..2c0c78cb6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgitbl.cxx
@@ -0,0 +1,82 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgitbl.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "dbgint.cxx"
+#if DBG == 1
+
+INTERFACENAMES inInterfaceNames[] =
+{
+ "IUnknown", apszIUnknownNames
+, "IClassFactory", apszIClassFactoryNames
+, "IMarshal", apszIMarshalNames
+, "IStdMarshalInfo", apszIStdMarshalInfoNames
+, "IMessageFilter", apszIMessageFilterNames
+, "IExternalConnection", apszIExternalConnectionNames
+, "IEnumString", apszIEnumStringNames
+, "IEnumUnknown", apszIEnumUnknownNames
+, "IEnumSTATSTG", apszIEnumSTATSTGNames
+, "ILockBytes", apszILockBytesNames
+, "IStream", apszIStreamNames
+, "IStorage", apszIStorageNames
+, "IRootStorage", apszIRootStorageNames
+, "IEnumFORMATETC", apszIEnumFORMATETCNames
+, "IEnumSTATDATA", apszIEnumSTATDATANames
+, "IDataObject", apszIDataObjectNames
+, "IViewObject", apszIViewObjectNames
+, "IViewObject2", apszIViewObject2Names
+, "IAdviseSink", apszIAdviseSinkNames
+, "IAdviseSink2", apszIAdviseSink2Names
+, "IDataAdviseHolder", apszIDataAdviseHolderNames
+, "IOleCache", apszIOleCacheNames
+, "IOleCache2", apszIOleCache2Names
+, "IOleCacheControl", apszIOleCacheControlNames
+, "IDropTarget", apszIDropTargetNames
+, "IDropSource", apszIDropSourceNames
+, "IPersist", apszIPersistNames
+, "IPersistStorage", apszIPersistStorageNames
+, "IPersistStream", apszIPersistStreamNames
+, "IPersistFile", apszIPersistFileNames
+, "IBindCtx", apszIBindCtxNames
+, "IMoniker", apszIMonikerNames
+, "IRunningObjectTable", apszIRunningObjectTableNames
+, "IEnumMoniker", apszIEnumMonikerNames
+, "IEnumOLEVERB", apszIEnumOLEVERBNames
+, "IOleObject", apszIOleObjectNames
+, "IOleClientSite", apszIOleClientSiteNames
+, "IRunnableObject", apszIRunnableObjectNames
+, "IParseDisplayName", apszIParseDisplayNameNames
+, "IOleContainer", apszIOleContainerNames
+, "IOleItemContainer", apszIOleItemContainerNames
+, "IOleAdviseHolder", apszIOleAdviseHolderNames
+, "IOleLink", apszIOleLinkNames
+, "IOleWindow", apszIOleWindowNames
+, "IOleInPlaceObject", apszIOleInPlaceObjectNames
+, "IOleInPlaceActiveObject", apszIOleInPlaceActiveObjectNames
+, "IOleInPlaceUIWindow", apszIOleInPlaceUIWindowNames
+, "IOleInPlaceFrame", apszIOleInPlaceFrameNames
+, "IOleInPlaceSite", apszIOleInPlaceSiteNames
+, "IRpcChannelBuffer", apszIRpcChannelBufferNames
+, "IRpcProxyBuffer", apszIRpcProxyBufferNames
+, "IRpcStubBuffer", apszIRpcStubBufferNames
+, "IPSFactoryBuffer", apszIPSFactoryBufferNames
+, "IRpcChannel", apszIRpcChannelNames
+, "IRpcProxy", apszIRpcProxyNames
+, "IRpcStub", apszIRpcStubNames
+, "IPSFactory", apszIPSFactoryNames
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dirs b/private/ole32/olethunk/olethk32/dirs
new file mode 100644
index 000000000..b7d4cd275
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dirs
@@ -0,0 +1,40 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+#
+# Note that is currently omitted because there is no difference
+# from the daytona binary.
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/olethunk/olethk32/dllentry.cxx b/private/ole32/olethunk/olethk32/dllentry.cxx
new file mode 100644
index 000000000..394b4bc8b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dllentry.cxx
@@ -0,0 +1,56 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dllentry.cxx
+//
+// Contents: DLL entry point code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+extern "C"
+{
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+};
+
+extern "C" BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason,
+ LPVOID lpReserved)
+{
+ BOOL fRc;
+
+ if ((dwReason == DLL_PROCESS_ATTACH) || (dwReason == DLL_THREAD_ATTACH))
+ {
+ // If this is an attach, initialize the Cruntimes first
+ if (fRc = _CRT_INIT(hDll, dwReason, lpReserved))
+ {
+ fRc = LibMain(hDll, dwReason, lpReserved);
+ }
+ }
+ else
+ {
+ // This is a detach so call the Cruntimes second
+ LibMain(hDll, dwReason, lpReserved);
+ fRc = _CRT_INIT(hDll, dwReason, lpReserved);
+ }
+
+ return fRc;
+}
+
+extern "C" BOOL __stdcall DllMain (HANDLE hDll, DWORD dwReason,
+ LPVOID lpReserved)
+{
+ // This is not currently used...but must be present to avoid
+ // an undefined symbol
+
+ return FALSE;
+}
+
+
+
diff --git a/private/ole32/olethunk/olethk32/fntomthd.cxx b/private/ole32/olethunk/olethk32/fntomthd.cxx
new file mode 100644
index 000000000..ec62999e6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/fntomthd.cxx
@@ -0,0 +1,2082 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fntomthd.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+BYTE CONST ftmIClassFactory[] =
+{
+ 3,
+ 4
+};
+BYTE CONST ftmIMarshal[] =
+{
+ 6,
+ 0,
+ 0,
+ 0,
+ 8,
+ 7,
+ 0,
+ 3,
+ 4,
+ 5
+};
+BYTE CONST ftmIStdMarshalInfo[] =
+{
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIMessageFilter[] =
+{
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 5
+};
+BYTE CONST ftmIExternalConnection[] =
+{
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIEnumString[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIEnumUnknown[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIEnumSTATSTG[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmILockBytes[] =
+{
+ 0,
+ 0,
+ 9,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 6,
+ 7,
+ 8
+};
+BYTE CONST ftmIStream[] =
+{
+ 4,
+ 0,
+ 12,
+ 0,
+ 13,
+ 8,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 6,
+ 11,
+ 10,
+ 5,
+ 7
+};
+BYTE CONST ftmIStorage[] =
+{
+ 0,
+ 0,
+ 13,
+ 15,
+ 12,
+ 9,
+ 10,
+ 0,
+ 0,
+ 6,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 5,
+ 8,
+ 11,
+ 14,
+ 16,
+ 17
+};
+BYTE CONST ftmIRootStorage[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIEnumFORMATETC[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIEnumSTATDATA[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIDataObject[] =
+{
+ 0,
+ 0,
+ 6,
+ 11,
+ 10,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 4,
+ 3,
+ 8
+};
+BYTE CONST ftmIViewObject[] =
+{
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIViewObject2[] =
+{
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIAdviseSink[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 3,
+ 0,
+ 7
+};
+BYTE CONST ftmIAdviseSink2[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 5,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 3,
+ 0,
+ 6
+};
+BYTE CONST ftmIDataAdviseHolder[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleCache[] =
+{
+ 7,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleCache2[] =
+{
+ 7,
+ 9,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8
+};
+BYTE CONST ftmIOleCacheControl[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0
+};
+BYTE CONST ftmIDropTarget[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 3,
+ 4,
+ 6
+};
+BYTE CONST ftmIDropSource[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersist[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistStorage[] =
+{
+ 0,
+ 8,
+ 0,
+ 6,
+ 5,
+ 3,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistStream[] =
+{
+ 0,
+ 0,
+ 0,
+ 7,
+ 5,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistFile[] =
+{
+ 0,
+ 0,
+ 0,
+ 8,
+ 7,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIBindCtx[] =
+{
+ 0,
+ 7,
+ 0,
+ 6,
+ 4,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10,
+ 9,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 11,
+ 12
+};
+BYTE CONST ftmIMoniker[] =
+{
+ 16,
+ 22,
+ 19,
+ 17,
+ 14,
+ 13,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 15,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 21,
+ 10,
+ 9,
+ 8,
+ 18,
+ 12,
+ 6,
+ 0,
+ 4,
+ 11,
+ 0,
+ 0,
+ 0,
+ 7,
+ 5,
+ 3,
+ 20
+};
+BYTE CONST ftmIRunningObjectTable[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 8,
+ 7,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 4,
+ 0
+};
+BYTE CONST ftmIEnumMoniker[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3
+};
+BYTE CONST ftmIEnumOLEVERB[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3
+};
+BYTE CONST ftmIOleObject[] =
+{
+ 0,
+ 21,
+ 16,
+ 20,
+ 15,
+ 12,
+ 14,
+ 0,
+ 0,
+ 11,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10,
+ 7,
+ 5,
+ 0,
+ 13,
+ 9,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3,
+ 8,
+ 17,
+ 18,
+ 19,
+ 22,
+ 23
+};
+BYTE CONST ftmIOleClientSite[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 8
+};
+BYTE CONST ftmIRunnableObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 3,
+ 5
+};
+BYTE CONST ftmIParseDisplayName[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleContainer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 5,
+ 0
+};
+BYTE CONST ftmIOleItemContainer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 7,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 5,
+ 0
+};
+BYTE CONST ftmIOleAdviseHolder[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 7
+};
+BYTE CONST ftmIOleLink[] =
+{
+ 0,
+ 0,
+ 0,
+ 13,
+ 11,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 12,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 6,
+ 4,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 3,
+ 10
+};
+BYTE CONST ftmIOleWindow[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 3,
+ 5
+};
+BYTE CONST ftmIOleInPlaceActiveObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceUIWindow[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceFrame[] =
+{
+ 0,
+ 13,
+ 0,
+ 12,
+ 11,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 10,
+ 0,
+ 0,
+ 9,
+ 8,
+ 3,
+ 0,
+ 14
+};
+BYTE CONST ftmIOleInPlaceSite[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 14,
+ 10,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 5,
+ 0,
+ 9,
+ 11,
+ 12,
+ 13
+};
+BYTE CONST ftmIRpcChannelBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7
+};
+BYTE CONST ftmIRpcProxyBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIRpcStubBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 8,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4
+};
+BYTE CONST ftmIPSFactoryBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIRpcChannel[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6
+};
+BYTE CONST ftmIRpcProxy[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIRpcStub[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4
+};
+BYTE CONST ftmIPSFactory[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
diff --git a/private/ole32/olethunk/olethk32/freelist.cxx b/private/ole32/olethunk/olethk32/freelist.cxx
new file mode 100644
index 000000000..6ba44e5e9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/freelist.cxx
@@ -0,0 +1,468 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: freelist.cxx
+//
+// Contents: CFreeList implementations
+//
+// History: 07-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//
+// Each element, when it is free, has a pointer stored within it that
+// points to the next free element. We can do this because we know that
+// the element is free, all of its data is unused. These pointers are used
+// as DWORDs since they can be virtual pointers (16:16).
+//
+#define CALC_NEXTPTR(lpElement) \
+ ((LPDWORD)((DWORD)(lpElement) + m_iNextPtrOffset))
+
+//
+// Each block of elements has a pointer to the next block of elements. We
+// allocate extra room for this pointer just after all of the elements within
+// the block. These pointers are used as DWORDs since they can be virtual
+// pointers (16:16).
+
+#define CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize) \
+ ((LPDWORD)((DWORD)(lpBlock) + (dwElementSectionSize)))
+
+//
+// Here are our global free lists, created on DLL load
+// The block sizes are generally -1 to allow space for block
+// list overhead
+//
+CFreeList flFreeList16( // THUNK1632OBJ free list
+ &mmodel16Public,
+ sizeof(THUNK1632OBJ),
+ 63,
+ FIELD_OFFSET(THUNK1632OBJ, pphHolder));
+
+CFreeList flFreeList32( // THUNK3216OBJ free list
+ &mmodel32,
+ sizeof(THUNK3216OBJ),
+ 63,
+ FIELD_OFFSET(THUNK3216OBJ, pphHolder));
+
+CFreeList flHolderFreeList( // PROXYHOLDER free list
+ &mmodel32,
+ sizeof(PROXYHOLDER),
+ 63,
+ FIELD_OFFSET(PROXYHOLDER, pphNext));
+
+CFreeList flRequestFreeList( // IID request free list
+ &mmodel32,
+ sizeof(IIDNODE),
+ 7,
+ FIELD_OFFSET(IIDNODE, pNextNode));
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::CFreeList
+//
+// Arguments: pmm - Memory model to use
+// iElementSize - The size of the structure being made into a
+// free list. e.g. sizeof THUNK1632OBJ
+// iElementsPerBlock - How many elements to allocate at a time
+// (a block contains this many elements).
+// iNextPtrOffset - Offset within the element's structure for
+// the place to store the free list's next
+// element pointer. Sometimes (for debugging,
+// etc.) it is desirable to make this NOT 0
+// (the beginning of the element structure).
+//
+// Synopsis: constructor for CFreeList class
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+// 7-05-94 BobDay (Bob Day) Changed it to be list based
+//
+//----------------------------------------------------------------------------
+CFreeList::CFreeList( CMemoryModel *pmm,
+ UINT iElementSize,
+ UINT iElementsPerBlock,
+ UINT iNextPtrOffset )
+{
+ //
+ // Save away the allocator information
+ //
+ m_pmm = pmm;
+ m_iElementSize = iElementSize;
+ m_iElementsPerBlock = iElementsPerBlock;
+ m_iNextPtrOffset = iNextPtrOffset;
+
+ //
+ // Set the list of elements to empty
+ //
+ m_dwHeadElement = 0;
+ m_dwTailElement = 0;
+
+ //
+ // Set the list of blocks to empty
+ //
+ m_dwHeadBlock = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::AllocElement
+//
+// Synopsis: Allocates an element from the various blocks of elements
+// and allocates a new block if necessary.
+//
+// Returns: 0 if failed to alloc an element,
+// otherwise the DWORD representing the alloc'd element.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+DWORD CFreeList::AllocElement( void )
+{
+ DWORD dwNewHeadBlock;
+ DWORD dwElementSectionSize;
+ DWORD dwBlockSize;
+ LPVOID lpBlock;
+ UINT iCnt;
+ DWORD dwElement;
+ LPVOID lpElement;
+ LPDWORD lpElementNextPtr;
+
+ //
+ // If the list of available elements is empty, callback to the derived
+ // class and make them add an entire new block of elements.
+ //
+ if ( m_dwHeadElement == 0 )
+ {
+ //
+ // Allocate a new block
+ //
+ iCnt = m_iElementsPerBlock;
+ dwElementSectionSize = m_iElementSize * m_iElementsPerBlock;
+
+ //
+ // Here we allocate an extra DWORD so that we can store in the block
+ // the address of the next block. In this way we have a list of
+ // blocks so that when the time comes to free them, we can find them
+ // all.
+ //
+ dwBlockSize = dwElementSectionSize + sizeof(DWORD);
+
+ dwNewHeadBlock = m_pmm->AllocMemory( dwBlockSize );
+
+ if ( dwNewHeadBlock == 0 )
+ {
+ //
+ // Yikes, the block allocator failed!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, AllocMemory failed\n"));
+ return 0;
+ }
+ //
+ // Now initialize the block and link it into the block list.
+ //
+
+ lpBlock = m_pmm->ResolvePtr( dwNewHeadBlock, dwBlockSize );
+ if ( lpBlock == NULL )
+ {
+ //
+ // Couldn't get a pointer to the block, some memory mapping
+ // problem?
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, "
+ "ResolvePtr for block failed "
+ "for address %08lX, size %08lX\n",
+ dwNewHeadBlock, dwBlockSize ));
+ // Try to return bad block to pool
+ m_pmm->FreeMemory( dwNewHeadBlock );
+ return 0;
+ }
+
+#if DBG == 1
+ // 0xDE = Alloc'd but not init'd
+ memset( lpBlock, 0xDE, dwBlockSize );
+#endif
+
+ //
+ // Make this block point to the previous block
+ //
+ *CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize) = m_dwHeadBlock;
+ m_dwHeadBlock = dwNewHeadBlock; // Update block list
+
+ m_pmm->ReleasePtr(dwNewHeadBlock);
+
+ //
+ // Now initialize all of the elements within the block to be free.
+ //
+ // The below loop skips the first element, free's all of the remaining
+ // ones. This way we can return the first one and all of the rest will
+ // be in accending order; The order doesn't really matter, but its
+ // nice.
+ //
+ dwElement = dwNewHeadBlock;
+
+ while ( iCnt > 1 ) // Free n-1 items (we skip the first)
+ {
+ --iCnt;
+ dwElement += m_iElementSize; // Skip to next one (miss 1st one)
+
+ FreeElement( dwElement );
+ }
+
+ dwElement = dwNewHeadBlock; // Use the first one as our alloc'd one
+ }
+ else
+ {
+ // We better have some blocks by now
+ thkAssert( m_dwHeadBlock != 0 );
+
+ // Better have a "end of list" too!
+ thkAssert( m_dwTailElement != 0 );
+
+ //
+ // Grab an available element off the top (head) of the list.
+ //
+ dwElement = m_dwHeadElement;
+
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Yikes, we weren't able to get a pointer to the element!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, "
+ "ResolvePtr for element failed "
+ "for address %08lX, size %08lX\n",
+ dwElement, m_iElementSize ));
+ return 0;
+ }
+
+ //
+ // Update the list to reflect the fact that we just removed the head
+ // and replace it with the one which was pointed to by the head.
+ //
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+ m_dwHeadElement = *lpElementNextPtr;
+
+ m_pmm->ReleasePtr(dwElement);
+
+ //
+ // Also, if we are now at the end of the list, then the tail element
+ // should point to nowhere (i.e. there is nothing to insert after).
+ //
+ if ( m_dwHeadElement == 0 )
+ {
+ m_dwTailElement = 0;
+ }
+ }
+
+#if DBG == 1
+ // Erase the memory being returned to highlight reuse of dead values
+
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ memset( lpElement, 0xED, m_iElementSize );
+ m_pmm->ReleasePtr(dwElement);
+
+ thkDebugOut((DEB_ITRACE,
+ "CFreeList::AllocElement, allocated element at %08lX\n",
+ dwElement ));
+#endif
+
+ return dwElement;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::FreeElement
+//
+// Synopsis: Un-Allocates an element from the various blocks of elements,
+// basically put the element back on the free list.
+//
+// Arguments: dwElement - Element to free
+//
+// Returns: -none- Asserts if failed.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+void CFreeList::FreeElement( DWORD dwElement )
+{
+ LPVOID lpElement;
+ LPDWORD lpElementNextPtr;
+ DWORD dwResolved;
+
+ //
+ // First, make sure we can set this new element's next element pointer
+ // to zero (he's going to be a the end of the list).
+ //
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Yikes, we couldn't get a pointer to this element's place to store
+ // its next pointer.
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::FreeElement, "
+ "ResolvePtr failed for free'd element\n"
+ "for address %08lX, size %08lX\n",
+ dwElement, m_iElementSize ));
+ thkAssert(FALSE && "CFreeList::FreeElement, "
+ "Resolve Ptr failed for free'd element\n");
+ return;
+ }
+
+#if DBG == 1
+ // Fill memory so its values can't be reused
+ if ( fZapProxy ) // Not doing this is important for
+ // the "PrepareForCleanup" processing the OLE32
+ // does on thread detach. ZapProxy can be used
+ // to turn it back on.
+ {
+ memset(lpElement, 0xDD, m_iElementSize);
+ }
+#endif
+
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+
+ *lpElementNextPtr = 0; // Zap his next pointer since he'll be on the end
+
+ m_pmm->ReleasePtr(dwElement);
+
+ //
+ // Add this element back onto the end (tail) of the list.
+ //
+ if ( m_dwTailElement == 0 )
+ {
+ //
+ // Well, the list was empty, time to set it up
+ //
+ thkAssert( m_dwHeadElement == 0 );
+
+ lpElementNextPtr = &m_dwHeadElement;
+ dwResolved = 0;
+ }
+ else
+ {
+ //
+ // Ok, the list wasn't empty, so we add this new one onto the end.
+ //
+ thkAssert( m_dwHeadElement != 0 );
+
+ dwResolved = m_dwTailElement;
+ lpElement = m_pmm->ResolvePtr( m_dwTailElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Oh no, we couldn't get a pointer to the next element pointer for
+ // the guy who is currently the tail of the list.
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::FreeElement, "
+ "ResolvePtr failed for last element\n"
+ "for address %08lX, size %08lX\n",
+ m_dwTailElement, m_iElementSize ));
+ thkAssert(FALSE && "CFreeList::FreeElement, "
+ "Resolve Ptr failed for last element\n");
+ return;
+ }
+
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+ }
+
+ //
+ // Update our tail pointer to point to our newly free'd guy.
+ //
+ m_dwTailElement = dwElement;
+
+ //
+ // Make the last guy point to this newly free'd guy
+ //
+ *lpElementNextPtr = dwElement;
+
+ if (dwResolved != 0)
+ {
+ m_pmm->ReleasePtr(dwResolved);
+ }
+
+ thkDebugOut((DEB_ITRACE,
+ "CFreeList::FreeElement, free'd element at %08lX\n",
+ dwElement ));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::FreeMemoryBlocks
+//
+// Arguments: -none-
+//
+// Returns: -nothing-
+//
+// Synopsis: Called by derived destructors to allow them to free up their
+// contents before going away.
+//
+// History: 7-05-94 BobDay (Bob Day) Created it
+//
+//----------------------------------------------------------------------------
+
+void CFreeList::FreeMemoryBlocks( void )
+{
+ DWORD dwBlock;
+ DWORD dwElementSectionSize;
+ DWORD dwBlockSize;
+ DWORD dwNextBlock;
+ LPVOID lpBlock;
+
+ //
+ // Compute some constants for this list ahead of time
+ //
+ dwElementSectionSize = m_iElementSize * m_iElementsPerBlock;
+
+ //
+ // Add room for that extra DWORD, block next pointer. (See comment in
+ // AllocElement where it allocates an extra DWORD)
+ //
+ dwBlockSize = dwElementSectionSize + sizeof(DWORD);
+
+ //
+ // Iterate through the list of blocks free'ing them
+ //
+ dwBlock = m_dwHeadBlock;
+
+ while( dwBlock != 0 )
+ {
+ //
+ // Find the next block ptr
+ //
+ lpBlock = m_pmm->ResolvePtr( dwBlock, dwBlockSize );
+ if ( lpBlock == NULL )
+ {
+ //
+ // If we get an error here, we just drop out of loop
+ //
+ dwNextBlock = 0;
+ }
+ else
+ {
+ dwNextBlock = *CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize);
+
+#if DBG == 1
+ memset(lpBlock, 0xEE, dwBlockSize);
+#endif
+
+ m_pmm->ReleasePtr(dwBlock);
+ m_pmm->FreeMemory( dwBlock );
+ }
+ dwBlock = dwNextBlock;
+ }
+
+ m_dwHeadElement = 0;
+ m_dwTailElement = 0;
+ m_dwHeadBlock = 0;
+}
diff --git a/private/ole32/olethunk/olethk32/freelist.hxx b/private/ole32/olethunk/olethk32/freelist.hxx
new file mode 100644
index 000000000..139de795a
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/freelist.hxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: freelist.hxx
+//
+// Contents: CFreeList classes
+//
+// History: 07-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FREELIST_HXX__
+#define __FREELIST_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFreeList (fl)
+//
+// Purpose: Implements a block allocator with replaceable underlying
+// memory strategies
+//
+// Interface: AllocElement - To allocate a proxy
+// ReleaseElement - To return an element to the free pool
+// AllocBlock - Callback for block allocation
+// GetElementNextPtr - Callback for list traversal
+//
+// Notes: At some point we might want to make this have one free list per
+// block. Then we would easily be able to tell which blocks have
+// all free elements within them and we able to be freed.
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+// 6-29-94 BobDay (Bob Day) Made list based
+//
+//----------------------------------------------------------------------------
+class CFreeList
+{
+public:
+ DWORD AllocElement( void );
+ void FreeElement( DWORD dwElement );
+ void FreeMemoryBlocks( void );
+
+ CFreeList( CMemoryModel *pmm,
+ UINT iElementSize,
+ UINT iElementsPerBlock,
+ UINT iNextPtrOffset );
+private:
+ CMemoryModel *m_pmm;
+
+ DWORD m_iElementSize;
+ DWORD m_iElementsPerBlock;
+ DWORD m_iNextPtrOffset;
+ DWORD m_dwHeadElement;
+ DWORD m_dwTailElement;
+ DWORD m_dwHeadBlock;
+};
+
+// Free lists
+extern CFreeList flFreeList16;
+extern CFreeList flFreeList32;
+extern CFreeList flHolderFreeList;
+extern CFreeList flRequestFreeList;
+
+#endif // #ifndef __FREELIST_HXX__
diff --git a/private/ole32/olethunk/olethk32/headers.cxx b/private/ole32/olethunk/olethk32/headers.cxx
new file mode 100644
index 000000000..50f0513e8
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/headers.cxx
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled headers file
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+extern "C" {
+#include <malloc.h>
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <wownt32.h>
+}
+
+#include <ole2.h>
+#include <olecoll.h>
+#include <privguid.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+#include <utils.h>
+#include <memapi.hxx>
+
+#include <interop.hxx>
+#include <wow32fn.h>
+#include <thunkapi.hxx>
+#include <stksw.hxx>
+#include "mmodel.hxx"
+#include "stalloc.hxx"
+#include "nest.hxx"
+#include "olethk32.hxx"
+#include "map_kv.h"
+#include "map_dwp.h"
+#include "obj16.hxx"
+#include "thkmgr.hxx"
+#include "freelist.hxx"
+#include "cthkmgr.hxx"
+
+#include "tlsthk.hxx"
+#include "thop.hxx"
+#include "thi.hxx"
+#include "the.hxx"
+#include "thopapi.hxx"
+#include "thopint.hxx"
+#include "inv16.hxx"
+#include "alias.hxx"
+#include "thoputil.hxx"
+#include "apinot.hxx"
+
+#if DBG == 1
+#include "dbginv.hxx"
+#endif
diff --git a/private/ole32/olethunk/olethk32/heap.cxx b/private/ole32/olethunk/olethk32/heap.cxx
new file mode 100644
index 000000000..9268967cc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/heap.cxx
@@ -0,0 +1,63 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: heap.cxx
+//
+// Contents: memory management
+//
+// Classes:
+//
+// Functions: operator new
+// operator delete
+//
+// History: 5-Dec-95 JeffE Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Function: operator new, public
+//
+// Synopsis: Global operator new which does not throw exceptions.
+//
+// Arguments: [size] -- Size of the memory to allocate.
+//
+// Returns: A pointer to the allocated memory. Is *NOT* initialized to 0!
+//
+// Notes: We override new to make delete easier.
+//
+//----------------------------------------------------------------------------
+void* _CRTAPI1
+operator new (size_t size)
+{
+ return(CoTaskMemAlloc(size));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ::operator delete
+//
+// Synopsis: Free a block of memory
+//
+// Arguments: [lpv] - block to free.
+//
+// History: 18-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+void _CRTAPI1 operator delete(void FAR* lpv)
+{
+ CoTaskMemFree (lpv);
+}
+
+
+
+
+
+
diff --git a/private/ole32/olethunk/olethk32/ichannel.cxx b/private/ole32/olethunk/olethk32/ichannel.cxx
new file mode 100644
index 000000000..7896e04e6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/ichannel.cxx
@@ -0,0 +1,49 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ichannel.cxx
+//
+// Contents: Maps the RpcChannel to RpcChannelBuffer
+// This is required to support custom interface marshalling.
+//
+// History: 24-Mar-94 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+
+//
+// the new 32 bit channel interface - buffer based
+//
+class CRpcChannelBuffer : public IPpcChannelBuffer
+{
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ HRESULT STDMETHODCALLTYPE GetBuffer(RPCOLEMESSAGE *pMessage,REFIID riid);
+ HRESULT STDMETHODCALLTYPE SendReceive(RPCOLEMESSAGE *pMessage,ULONG *pStatus);
+ HRESULT STDMETHODCALLTYPE FreeBuffer(RPCOLEMESSAGE *pMessage);
+ HRESULT STDMETHODCALLTYPE GetDestCtx(DWORD *pdwDestContext,void **ppvDestContext);
+ HRESULT STDMETHODCALLTYPE IsConnected( void);
+};
+
+// 16 bit channel interface - stream based
+// class see by the 16 bit implemantation
+// needs to be mapped to the RpcChannelBuffer
+class CRpcChannel : public IRpcChannel
+{
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream);
+ STDMETHOD(Call)(IStream FAR* pIStream);
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx);
+ STDMETHOD(IsConnected)(void);
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/iidtothi.cxx b/private/ole32/olethunk/olethk32/iidtothi.cxx
new file mode 100644
index 000000000..54c250227
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/iidtothi.cxx
@@ -0,0 +1,79 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: iidtothi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <coguid.h>
+#include <oleguid.h>
+IIDTOTHI CONST aittIidToThi[] =
+{
+ &IID_IUnknown, THI_IUnknown
+, &IID_IClassFactory, THI_IClassFactory
+, &IID_IMarshal, THI_IMarshal
+, &IID_IStdMarshalInfo, THI_IStdMarshalInfo
+, &IID_IMessageFilter, THI_IMessageFilter
+, &IID_IExternalConnection, THI_IExternalConnection
+, &IID_IEnumString, THI_IEnumString
+, &IID_IEnumUnknown, THI_IEnumUnknown
+, &IID_IEnumSTATSTG, THI_IEnumSTATSTG
+, &IID_ILockBytes, THI_ILockBytes
+, &IID_IStream, THI_IStream
+, &IID_IStorage, THI_IStorage
+, &IID_IRootStorage, THI_IRootStorage
+, &IID_IEnumFORMATETC, THI_IEnumFORMATETC
+, &IID_IEnumSTATDATA, THI_IEnumSTATDATA
+, &IID_IDataObject, THI_IDataObject
+, &IID_IViewObject, THI_IViewObject
+, &IID_IViewObject2, THI_IViewObject2
+, &IID_IAdviseSink, THI_IAdviseSink
+, &IID_IAdviseSink2, THI_IAdviseSink2
+, &IID_IDataAdviseHolder, THI_IDataAdviseHolder
+, &IID_IOleCache, THI_IOleCache
+, &IID_IOleCache2, THI_IOleCache2
+, &IID_IOleCacheControl, THI_IOleCacheControl
+, &IID_IDropTarget, THI_IDropTarget
+, &IID_IDropSource, THI_IDropSource
+, &IID_IPersist, THI_IPersist
+, &IID_IPersistStorage, THI_IPersistStorage
+, &IID_IPersistStream, THI_IPersistStream
+, &IID_IPersistFile, THI_IPersistFile
+, &IID_IBindCtx, THI_IBindCtx
+, &IID_IMoniker, THI_IMoniker
+, &IID_IRunningObjectTable, THI_IRunningObjectTable
+, &IID_IEnumMoniker, THI_IEnumMoniker
+, &IID_IEnumOLEVERB, THI_IEnumOLEVERB
+, &IID_IOleObject, THI_IOleObject
+, &IID_IOleClientSite, THI_IOleClientSite
+, &IID_IRunnableObject, THI_IRunnableObject
+, &IID_IParseDisplayName, THI_IParseDisplayName
+, &IID_IOleContainer, THI_IOleContainer
+, &IID_IOleItemContainer, THI_IOleItemContainer
+, &IID_IOleAdviseHolder, THI_IOleAdviseHolder
+, &IID_IOleLink, THI_IOleLink
+, &IID_IOleWindow, THI_IOleWindow
+, &IID_IOleInPlaceObject, THI_IOleInPlaceObject
+, &IID_IOleInPlaceActiveObject, THI_IOleInPlaceActiveObject
+, &IID_IOleInPlaceUIWindow, THI_IOleInPlaceUIWindow
+, &IID_IOleInPlaceFrame, THI_IOleInPlaceFrame
+, &IID_IOleInPlaceSite, THI_IOleInPlaceSite
+, &IID_IRpcChannelBuffer, THI_IRpcChannelBuffer
+, &IID_IRpcProxyBuffer, THI_IRpcProxyBuffer
+, &IID_IRpcStubBuffer, THI_IRpcStubBuffer
+, &IID_IPSFactoryBuffer, THI_IPSFactoryBuffer
+, &IID_IRpcChannel, THI_IRpcChannel
+, &IID_IRpcProxy, THI_IRpcProxy
+, &IID_IRpcStub, THI_IRpcStub
+, &IID_IPSFactory, THI_IPSFactory
+};
diff --git a/private/ole32/olethunk/olethk32/inv16.cxx b/private/ole32/olethunk/olethk32/inv16.cxx
new file mode 100644
index 000000000..a381b048d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv16.cxx
@@ -0,0 +1,608 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv16.cxx
+//
+// Contents: 32->16 Call thunking
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "..\..\ole232\inplace\inplace.h" // We need CFrameFilter for
+ // WinWord 6 Hack
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn16, public
+//
+// Synopsis: Sets up the THUNKINFO and starts thunking for a 32->16 call
+//
+// Arguments: [iidx] - Custom interface or known interface index
+// [dwMethod] - Method index
+// [pvStack32] - 32-bit stack
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C"
+{
+ULONG InvokeOn16_count = 0;
+ULONG InvokeOn16_break = 0;
+
+int _iInvokeOn16BreakIidx = -1;
+int _iInvokeOn16BreakMethod = -1;
+};
+#endif
+
+// InvokeOn16 uses a lot of local variables so allocate its locals
+// rather than declaring them on the stack. This saves roughly
+// 150 bytes of stack per call
+
+struct INVOKE16RECORD
+{
+ THOP CONST *pThop;
+ THOP CONST * CONST *ppThop;
+ UINT uiThop;
+ VTBLFN UNALIGNED CONST *pvfnVtbl;
+ VPVOID vpvThis16;
+ VPVOID vpvVtbl16;
+ VPVOID UNALIGNED CONST *pvpvThis16;
+ DWORD dwStack16[MAX_PARAMS];
+ THUNKINFO ti;
+ THUNK3216OBJ *ptoThis32;
+ ThreadData *ptd;
+};
+
+DWORD InvokeOn16(IIDIDX iidx, DWORD dwMethod, LPVOID pvStack32)
+{
+ // NOTE: Do not declare local variables in this routine
+ // except for debug builds
+ INVOKE16RECORD *pir;
+ DWORD dwResult;
+
+#if DBG == 1
+ ULONG ulInvokeOn16_count = ++InvokeOn16_count;
+ if (InvokeOn16_count == InvokeOn16_break)
+ {
+ DebugBreak();
+ }
+
+ thkDebugOut((DEB_ITRACE, "%sInvokeOn16(0x%x, 0x%x, %p)\n",
+ NestingLevelString(), iidx, dwMethod, pvStack32));
+#endif
+
+ pir = (INVOKE16RECORD *)STACKALLOC32(sizeof(INVOKE16RECORD));
+ if (pir == NULL)
+ {
+ // BUGBUG - This error isn't guaranteed to mean anything for
+ // this call. Not much else we can do, though
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // pvStack32 is a pointer to an array of arguments from the
+ // 32-bit call. It's always laid out with the first
+ // argument low and increasing from there
+
+ pir->ti.s32.pbStart = (BYTE *)pvStack32;
+ pir->ti.s32.pbCurrent = pir->ti.s32.pbStart;
+
+ pir->ti.s16.pbStart = (BYTE *)pir->dwStack16;
+ pir->ti.s16.pbCurrent = pir->ti.s16.pbStart;
+
+ pir->ti.scResult = S_OK;
+ pir->ti.fResultThunked = FALSE;
+
+ pir->ptd = TlsThkGetData();
+ if (pir->ptd == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn16: Call refused\n"));
+
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.pThkMgr = pir->ptd->pCThkMgr;
+ thkAssert(pir->ti.pThkMgr != NULL);
+
+ thkAssert(iidx >= 0 && iidx < THI_COUNT);
+
+ // For each interface there is an array of thop strings, one for
+ // each method. The IUnknown methods don't have thop strings so
+ // bias the thop string pointer to account for that
+
+ thkAssert(dwMethod >= SMI_COUNT);
+
+ pir->ppThop = athopiInterfaceThopis[iidx].ppThops-SMI_COUNT;
+ pir->uiThop = athopiInterfaceThopis[iidx].uiSize;
+
+ // Methods are cdecl so we need to move upwards in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = 1;
+
+ // We need to look up the appropriate method pointer by
+ // looking in the 16-bit object's vtable
+ GET_STACK32(&pir->ti, pir->ptoThis32, THUNK3216OBJ *);
+
+ thkDebugOut((DEB_INVOKES,
+ "InvokeOn16: ptoThis32 = %08lX\n", pir->ptoThis32 ));
+
+ if ( pir->ptoThis32->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "InvokeOn16: Attempt to call %s::%s"
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ pir->ptoThis32, pir->ptoThis32->vpvThis16));
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ // check PROXYFLAG_CLEANEDUP before calling DebugValidateProxy3216.
+ // Otherwise we might get asserts on checked OLE.
+ DebugValidateProxy3216(pir->ptoThis32);
+
+ pir->ti.dwCallerProxy = (DWORD)pir->ptoThis32;
+ pir->vpvThis16 = pir->ptoThis32->vpvThis16;
+ pir->pvpvThis16 = (VPVOID UNALIGNED *)
+ GetReadPtr16(&pir->ti, pir->vpvThis16, sizeof(VPVOID));
+ if (pir->pvpvThis16 == NULL)
+ {
+ dwResult = pir->ti.scResult;
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return dwResult;
+ }
+
+ pir->vpvVtbl16 = *pir->pvpvThis16;
+ pir->pvfnVtbl = (VTBLFN UNALIGNED *)
+ GetReadPtr16(&pir->ti, pir->vpvVtbl16, sizeof(VPVOID)*pir->uiThop);
+
+ WOWRELVDMPTR(pir->vpvThis16);
+
+ if (pir->pvfnVtbl == NULL)
+ {
+ dwResult = pir->ti.scResult;
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return dwResult;
+ }
+
+ // Push the 16-bit this pointer on the stack first
+ TO_STACK16(&pir->ti, pir->vpvThis16, VPVOID);
+
+ thkAssert(dwMethod < pir->uiThop);
+
+ pir->pThop = pir->ppThop[dwMethod];
+
+ thkAssert(pir->pThop != NULL);
+
+ pir->ti.pThop = pir->pThop;
+ pir->ti.pvfn = pir->pvfnVtbl[dwMethod];
+ pir->ti.iidx = iidx;
+ pir->ti.dwMethod = dwMethod;
+ pir->ti.this32 = (IUnknown *)pir->ptoThis32;
+
+ WOWRELVDMPTR(pir->vpvVtbl16);
+
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn16 on %p:%p, %s::%s\n",
+ NestingLevelString(), ulInvokeOn16_count,
+ pir->vpvThis16, pir->ti.pvfn,
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod]));
+
+ DebugIncrementNestingLevel();
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_INVOKETHKIN16);
+
+#if DBG == 1
+ SStackRecord sr;
+
+ RecordStackState16(&sr);
+#endif
+
+#if DBG == 1
+ if ((_iInvokeOn16BreakIidx > 0 && _iInvokeOn16BreakIidx == (int)iidx) &&
+ (_iInvokeOn16BreakMethod < 0 ||
+ _iInvokeOn16BreakMethod == (int)dwMethod))
+ {
+ DebugBreak();
+ }
+#endif
+
+ dwResult = EXECUTE_THOP3216(&pir->ti);
+
+#if DBG == 1
+
+ if ( !pir->ti.fResultThunked && FAILED(dwResult) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn16 probable failure %s::%s sc = %08lX\n",
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+
+ CheckStackState16(&sr);
+
+#endif
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ DebugDecrementNestingLevel();
+
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn16 on %p:%p, %s::%s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn16_count,
+ pir->vpvThis16, pir->ti.pvfn,
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ dwResult));
+
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Call3216, private
+//
+// Synopsis: Sets up stack and transitions to 16-bit
+//
+// Arguments: [pvfn] - Function to call
+// [pbStack] - Stack in 32-bits
+// [cbStack] - Size of stack
+//
+// Returns: Appropriate status code
+//
+// History: 04-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+extern "C" ULONG Call3216_count = 0;
+extern "C" ULONG Call3216_break = 0;
+#endif
+
+DWORD Call3216(VPVOID pvfn, BYTE *pbStack, UINT cbStack)
+{
+#if DBG == 1
+ ULONG ulCall3216_count = ++Call3216_count;
+ if (Call3216_count == Call3216_break)
+ {
+ DebugBreak();
+ }
+#endif
+
+ VPVOID vpvStack16;
+ DWORD dwResult;
+ void *pvStack16;
+
+ dwResult = (DWORD)S_OK;
+
+ if (cbStack <= WCB16_MAX_CBARGS)
+ {
+ thkDebugOut((DEB_ITRACE, "CallbackTo16Ex(%p, %lu, %p) #(%x)\n",
+ pvfn, cbStack, pbStack, ulCall3216_count));
+
+ // pbStack must have at least WCB16_MAX_CBARGS bytes of valid memory
+ // since 16V always copies that many bytes
+
+ // In our case pbStack is from InvokeOn16 which should be large enough
+ thkAssert(MAX_PARAMS*sizeof(DWORD) >= WCB16_MAX_CBARGS);
+
+ if (!CallbackTo16Ex(pvfn, WCB16_CDECL, cbStack, pbStack,
+ &dwResult))
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+ else
+ {
+ CALLDATA UNALIGNED *pcd;
+ UINT cbAlloc;
+
+ cbAlloc = cbStack+sizeof(CALLDATA);
+
+ vpvStack16 = STACKALLOC16(cbAlloc);
+ if (vpvStack16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ pvStack16 = (void *)WOWFIXVDMPTR(vpvStack16, cbAlloc);
+
+ pcd = (CALLDATA UNALIGNED *)((BYTE *)pvStack16+cbStack);
+ pcd->vpfn = (DWORD)pvfn;
+ pcd->vpvStack16 = vpvStack16;
+ pcd->cbStack = cbStack;
+
+ memcpy(pvStack16, pbStack, cbStack);
+
+ WOWRELVDMPTR(vpvStack16);
+
+ thkDebugOut((DEB_ITRACE, "CallbackTo16(%p, (%p, %p, %lu)) #(%x)\n",
+ gdata16Data.fnCallStub16, pvfn, vpvStack16,
+ cbStack, ulCall3216_count));
+ dwResult = CallbackTo16(gdata16Data.fnCallStub16,
+ vpvStack16+cbStack);
+
+ STACKFREE16(vpvStack16, cbAlloc);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkCall3216, public
+//
+// Synopsis: Sets up the 16-bit stack and makes a 32->16 call
+//
+// Arguments: [pti] - Thunk state info
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 DrewB Created
+// 08-Aug-94 AlexT Add IOleClientSite::OnShowWindow code
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C" ULONG ThunkCall3216_count = 0;
+extern "C" ULONG ThunkCall3216_break = 0;
+#endif
+
+DWORD ThunkCall3216(THUNKINFO *pti)
+{
+ DWORD dwReturn;
+ UINT cbStack;
+ DWORD dwCallerTID;
+ HRESULT hrCaller;
+
+
+#if DBG == 1
+ ULONG ulThunkCall3216_count = ++ThunkCall3216_count;
+ thkAssert( (ThunkCall3216_count != ThunkCall3216_break) &&
+ "Break Count Hit");
+#endif
+
+ thkAssert(*pti->pThop == THOP_END);
+ pti->pThop++;
+ thkAssert(*pti->pThop == THOP_ROUTINEINDEX);
+ pti->pThop++;
+
+ thkDebugOut((DEB_ITRACE, "ThunkCall3216 #(%x) %p, index %d\n",
+ ulThunkCall3216_count, pti->pvfn, *pti->pThop));
+
+ cbStack = pti->s16.pbCurrent-pti->s16.pbStart;
+
+ // The this pointer should always be on the stack
+ thkAssert(cbStack >= sizeof(VPVOID));
+
+ //
+ // Hacks for specific interface member functions.
+ // The placement of these hacks here is by no means an optimal solution.
+ // It just happens to be convienient for now since everything goes through
+ // here. This section is for pre-processing.
+ //
+ if ( IIDIDX_IS_INDEX(pti->iidx) )
+ {
+ switch( IIDIDX_INDEX(pti->iidx) )
+ {
+ case THI_IOleClientSite:
+#define METHOD_ONSHOWWINDOW 7
+ if ( pti->dwMethod == METHOD_ONSHOWWINDOW )
+ {
+ //
+ // Here we merge the input queues for the sole reason so that
+ // we can link the object's window activations into the calling
+ // thread's window z-order.
+ //
+
+ hrCaller = CoGetCallerTID( &dwCallerTID );
+
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ TRUE );
+ }
+ }
+ break;
+
+ case THI_IOleObject:
+#define METHOD_DOVERB 11
+ if ( pti->dwMethod == METHOD_DOVERB )
+ {
+ //
+ // Here we merge the input queues for the sole reason so
+ // that we can link the object's window activations into
+ // the calling thread's window z-order.
+ //
+
+ hrCaller = CoGetCallerTID( &dwCallerTID );
+
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ TRUE );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ dwReturn = Call3216((VPVOID)pti->pvfn, pti->s16.pbStart, cbStack);
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ //
+ // Hacks for specific interface member functions.
+ // Again, the placement of these is by no means an optimal solution.
+ // They can be moved as long as they have the same effect for just these
+ // interfaces. This section is for post-processing.
+ //
+ if ( IIDIDX_IS_INDEX(pti->iidx) )
+ {
+ switch( IIDIDX_INDEX(pti->iidx) )
+ {
+ case THI_IOleClientSite:
+ if ( pti->dwMethod == METHOD_ONSHOWWINDOW )
+ {
+ //
+ // Unmerge the input queues afterward.
+ //
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ FALSE );
+ }
+ }
+ break;
+
+ case THI_IOleObject:
+ if ( pti->dwMethod == METHOD_DOVERB )
+ {
+ //
+ // Unmerge the input queues afterward.
+ //
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ FALSE );
+ }
+ }
+
+#define METHOD_GETCLIENTSITE 4
+ if ( pti->dwMethod == METHOD_GETCLIENTSITE )
+ {
+ //
+ // Excel 5.0a needs to perform some special processing
+ // on the way out of a IOleObject::GetClientSite call.
+ // See CTHKMGR.CXX and APINOT.CXX for more details.
+ //
+ if ( TlsThkGetAppCompatFlags() & OACF_CLIENTSITE_REF )
+ {
+ //
+ // Tell the thkmgr that we are thunking a bad
+ // IOleObject::GetClientSite reference on the way out.
+ //
+ thkDebugOut((DEB_WARN,"TC3216: OACF_CLIENTSITE_REF used: "
+ "Setting to clientsite thunk state\n"));
+
+ pti->pThkMgr->SetThkState(
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE);
+ }
+ }
+ break;
+
+ case THI_IOleInPlaceFrame:
+#define METHOD_REMOVEMENUS 11
+ //
+ // Winword 6.0a didn't call OleSetMenuDescriptor(NULL)
+ // during its IOleInPlaceFrame::RemoveMenus. This leaves
+ // OLE's frame filter in place. The frame filter holds references
+ // to some objects so everybody's refcounting gets thrown off
+ // Here, when we see a RemoveMenus call completing we force
+ // the OleSetMenuDescriptor(NULL) call to occur. This shuts
+ // down the frame filter and corrects the reference counts.
+ //
+ // There is one other hack necessary: Word unsubclasses the
+ // window itself directly rather than going through
+ // OleSetMenuDescriptor. Therefore the frame filter code
+ // is patched to only unhook if it detects that it is the
+ // current hook
+ //
+ // See APINOT.CXX for more hack code.
+ //
+ if (pti->dwMethod == METHOD_REMOVEMENUS)
+ {
+ if ( TlsThkGetAppCompatFlags() & OACF_RESETMENU )
+ {
+ HRESULT hr;
+ HWND hwnd;
+ LPOLEINPLACEFRAME lpoipf;
+
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ lpoipf = (LPOLEINPLACEFRAME)pti->this32;
+ hr = lpoipf->GetWindow( &hwnd );
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ if ( FAILED(hr) )
+ {
+ break;
+ }
+
+ thkDebugOut((DEB_WARN,
+ "TC3216: OACF_RESETMENU used: "
+ "Setting menu descriptor "
+ "to NULL on %p\n", hwnd));
+
+ OleSetMenuDescriptor(NULL, hwnd, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( !pti->fResultThunked )
+ {
+ dwReturn = TransformHRESULT_1632( dwReturn );
+
+#if DBG == 1
+ if (FAILED(dwReturn) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "Call3216 pvfn = %08lX Probably failed hr = %08lX\n",
+ pti->pvfn, dwReturn));
+ }
+#endif
+ }
+
+ thkDebugOut((DEB_ITRACE,
+ "ThunkCall3216 #(%x) returns 0x%08lX\n",
+ ulThunkCall3216_count,
+ dwReturn));
+
+ return dwReturn;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetOwnerPublicHMEM16, public
+//
+// Synopsis: Changes the 16-bit memory handle into a public selector, owned
+// by nobody. This prevents any app from taking it away when it
+// is cleaned up.
+//
+// Arguments: [hmem] - 16-bit memory handle
+//
+// Returns: Appropriate status code
+//
+// History: 13-Jul-94 BobDay Created it
+//
+//----------------------------------------------------------------------------
+void SetOwnerPublicHMEM16( DWORD hmem )
+{
+ CallbackTo16(gdata16Data.fnSetOwnerPublic16, hmem );
+}
diff --git a/private/ole32/olethunk/olethk32/inv16.hxx b/private/ole32/olethunk/olethk32/inv16.hxx
new file mode 100644
index 000000000..a317ad370
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv16.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv16.hxx
+//
+// Contents: 32->16 invoke function header
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __INV16_HXX__
+#define __INV16_HXX__
+
+DWORD InvokeOn16(IIDIDX iidx, DWORD dwMethod, LPVOID pvStack32);
+DWORD ThunkCall3216(THUNKINFO *pti);
+void SetOwnerPublicHMEM16( DWORD hMem16 );
+
+#endif // #ifndef __INV16_HXX__
diff --git a/private/ole32/olethunk/olethk32/inv32.cxx b/private/ole32/olethunk/olethk32/inv32.cxx
new file mode 100644
index 000000000..25245d2fc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv32.cxx
@@ -0,0 +1,496 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv32.cxx
+//
+// Contents: Implementation of InvokeOn32
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+
+#include <apilist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn32, public
+//
+// Synopsis: Sets up the THUNKINFO and starts thunking for a 16->32 call
+//
+// Arguments: [dw1] - Ignored
+// [dwMethod] - Method index
+// [pvStack32] - 32-bit stack
+//
+// Returns: Appropriate status code
+//
+// History: 18-Dec-93 JohannP Created
+// 21-Feb-94 DrewB Modified
+// 09-Dec-94 JohannP added stack switching
+//
+// Note: On WIN95 this function get is executed on the 32 bit stack.
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C"
+{
+ULONG InvokeOn32_count = 0;
+ULONG InvokeOn32_break = 0;
+
+int _iInvokeOn32BreakIidx = -1;
+int _iInvokeOn32BreakMethod = -1;
+};
+#endif
+
+
+// InvokeOn32 uses a lot of local variables so allocate its locals
+// rather than declaring them on the stack. This saves roughly
+// 150 bytes of stack per call
+
+struct INVOKE32RECORD
+{
+ THOP CONST *pThop;
+ THOP CONST * CONST *ppThop;
+ UINT uiThop;
+ VTBLFN CONST *pvfnVtbl;
+ VTBLFN CONST * CONST *ppvfnThis32;
+ DWORD dwStack32[MAX_PARAMS];
+ THUNKINFO ti;
+ VPVOID vpvThis16;
+ THUNK1632OBJ UNALIGNED *pto;
+ IIDIDX iidx;
+ ThreadData *ptd;
+};
+
+STDAPI_(DWORD) SSAPI(InvokeOn32)(DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
+{
+ // NOTE: Do not declare local variables in this routine
+ // except for debug builds
+ INVOKE32RECORD *pir;
+ DWORD dwResult;
+
+#if DBG == 1
+ ULONG ulInvokeOn32_count = ++InvokeOn32_count;
+
+ if (InvokeOn32_count == InvokeOn32_break)
+ {
+ DebugBreak();
+ }
+
+ thkDebugOut((DEB_ITRACE, "%sInvokeOn32(0x%08x, %p)\n",
+ NestingLevelString(),
+ dwMethod, pvStack16));
+#endif // DBG
+
+ pir = (INVOKE32RECORD *)STACKALLOC32(sizeof(INVOKE32RECORD));
+ if (pir == NULL)
+ {
+ // BUGBUG - This error isn't guaranteed to mean anything for
+ // this call. Not much else we can do, though
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // pvStack16 is the pointer to the first parameter of the 16-bit
+ // routine. The compiler will adjust it appropriately according
+ // to the calling convention of the routine so for PASCAL APIs
+ // it will be high and for CDECL methods it will be low
+
+ pir->ti.s16.pbStart = (BYTE *)pvStack16;
+ pir->ti.s16.pbCurrent = pir->ti.s16.pbStart;
+
+ pir->ti.s32.pbStart = (BYTE *)pir->dwStack32;
+ pir->ti.s32.pbCurrent = pir->ti.s32.pbStart;
+
+ pir->ti.scResult = S_OK;
+ pir->ti.fResultThunked = FALSE;
+
+ if (dwMethod >= THK_API_BASE)
+ {
+ dwMethod -= THK_API_BASE;
+ pir->iidx = IIDIDX_INVALID;
+
+ // APIs are handled as if there were a giant interface which
+ // contains all the APIs as methods.
+ pir->ppThop = apthopsApiThops;
+ pir->uiThop = THK_API_COUNT;
+
+ pir->pvfnVtbl = apfnApiFunctions;
+
+ // APIs are pascal so we need to move downward in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = -1;
+
+ pir->ti.dwCallerProxy = 0;
+ }
+ else
+ {
+ // For each interface there is an array of thop strings, one for
+ // each method. The IUnknown methods don't have thop strings so
+ // bias the thop string pointer to account for that
+
+ thkAssert(dwMethod >= SMI_COUNT);
+
+ // Methods are cdecl so we need to move upwards in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = 1;
+
+ // We need to look up the appropriate method pointer by
+ // looking in the 32-bit object's vtable
+ GET_STACK16(&pir->ti, pir->vpvThis16, VPVOID);
+
+ thkDebugOut((DEB_INVOKES,
+ "InvokeOn32: vpvThis16 = %08lX\n", pir->vpvThis16 ));
+
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if (pir->pto == NULL)
+ {
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_INVALIDARG;
+ }
+
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ // Make sure proxy is still valid.
+ // BUGBUG: After PPC/Win95 we might want to look at using
+ // a signiture for validating this rather than IsValidInterface
+ // because it will speed this code path up.
+ if (!IsValidInterface(pir->pto->punkThis32))
+ {
+ thkDebugOut((
+ DEB_ERROR, "InvokeOn32: %p: Invalid proxied object %p\n",
+ pir->vpvThis16, pir->pto->punkThis32));
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ RELVDMPTR(pir->vpvThis16);
+ return (DWORD)E_INVALIDARG;
+ }
+
+ DebugValidateProxy1632(pir->vpvThis16);
+
+ pir->ppvfnThis32 = (VTBLFN CONST * CONST*)pir->pto->punkThis32;
+ }
+ else
+ {
+ // Temporary proxies cannot be validated
+
+ // A temporary proxy's this pointer is actually a pointer
+ // to the real this pointer, so indirect through the this
+ // pointer to retrieve the real this pointer
+ pir->ppvfnThis32 = (VTBLFN CONST * CONST *)*(void **)pir->pto->punkThis32;
+ thkAssert(pir->ppvfnThis32 != NULL);
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn32 on temporary "
+ "%s proxy for %p\n", IidIdxString(pir->pto->iidx),
+ pir->ppvfnThis32));
+ }
+
+ pir->iidx = pir->pto->iidx;
+ RELVDMPTR(pir->vpvThis16);
+
+ if (pir->ppvfnThis32 == NULL)
+ {
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.dwCallerProxy = pir->vpvThis16;
+
+ thkAssert(pir->iidx >= 0 && pir->iidx < THI_COUNT);
+
+ pir->ppThop = athopiInterfaceThopis[pir->iidx].ppThops-SMI_COUNT;
+ pir->uiThop = athopiInterfaceThopis[pir->iidx].uiSize;
+
+ pir->pvfnVtbl = *pir->ppvfnThis32;
+
+ // Push the 32-bit this pointer on the stack first
+ TO_STACK32(&pir->ti, pir->ppvfnThis32, VTBLFN CONST * CONST*);
+ }
+
+ thkAssert(dwMethod < pir->uiThop);
+
+ pir->pThop = pir->ppThop[dwMethod];
+
+ thkAssert(pir->pThop != NULL);
+
+ pir->ti.pThop = pir->pThop;
+ pir->ti.pvfn = pir->pvfnVtbl[dwMethod];
+ pir->ti.iidx = pir->iidx;
+ pir->ti.dwMethod = dwMethod;
+
+ pir->ptd = TlsThkGetData();
+ if (pir->ptd == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn32: Call refused\n"));
+
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.pThkMgr = pir->ptd->pCThkMgr;
+ thkAssert(pir->ti.pThkMgr != NULL);
+
+#if DBG == 1
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p, %s\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ti.pvfn, apszApiNames[dwMethod]));
+ }
+ else
+ {
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p:%p, %s::%s (0x%0x:0x%0x)\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ppvfnThis32, pir->ti.pvfn,
+ inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ pir->iidx,
+ dwMethod));
+ }
+#endif
+
+ DebugIncrementNestingLevel();
+ // save and set the new thunk state
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_INVOKETHKIN32);
+
+#if DBG == 1
+ if ((_iInvokeOn32BreakIidx > 0 &&
+ _iInvokeOn32BreakIidx == (int)pir->iidx) &&
+ (_iInvokeOn32BreakMethod < 0 ||
+ _iInvokeOn32BreakMethod == (int)dwMethod))
+ {
+ DebugBreak();
+ }
+#endif
+
+#if DBG == 1
+ SStackRecord sr;
+
+ RecordStackState16(&sr);
+#endif
+
+#if DBG == 1
+ if (fStabilizeProxies)
+#endif
+ {
+ // HACK HACK HACK
+ // Because of changes in the way refcounting rules work between
+ // 16 and 32-bits, we have to stabilize this pointers for
+ // 16->32 calls. To effect this, we do a purely local AddRef
+ //
+ // Temporary proxies are not valid proxies so they cannot
+ // be stabilized
+ if (pir->iidx != IIDIDX_INVALID)
+ {
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ pir->ti.pThkMgr->LocalAddRefProxy(pir->pto);
+ }
+ RELVDMPTR(pir->vpvThis16);
+ }
+ }
+
+ dwResult = EXECUTE_THOP1632(&pir->ti);
+
+#if DBG == 1
+ if (fStabilizeProxies)
+#endif
+ {
+ // Remove our stabilization reference
+ // Note that we don't really know whether the proxy is
+ // still valid, so we're just crossing our fingers here
+ // and hoping that things continue to work
+ if (pir->iidx != IIDIDX_INVALID)
+ {
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ RELVDMPTR(pir->vpvThis16);
+
+ DebugValidateProxy1632(pir->vpvThis16);
+
+ pir->ti.pThkMgr->ReleaseProxy1632(pir->vpvThis16);
+ }
+ else
+ {
+ RELVDMPTR(pir->vpvThis16);
+ }
+ }
+ }
+
+#if DBG == 1
+
+ if ( !pir->ti.fResultThunked && FAILED(dwResult) )
+ {
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn32 probable failure %s sc = %08lX\n",
+ apszApiNames[dwMethod],
+ dwResult));
+ }
+ else
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn32 probable failure %s::%s sc = %08lX\n",
+ inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+ }
+
+ CheckStackState16(&sr);
+
+#endif
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ DebugDecrementNestingLevel();
+
+ if ( !pir->ti.fResultThunked )
+ {
+ dwResult = TransformHRESULT_3216( dwResult );
+ }
+
+#if DBG == 1
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn32 on %p, %s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn32_count, pir->ti.pvfn,
+ apszApiNames[dwMethod], dwResult ));
+ }
+ else
+ {
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn32 on %p:%p, %s::%s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ppvfnThis32,
+ pir->ti.pvfn, inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+#endif
+
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+
+ return dwResult;
+}
+
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: SSCallback16
+//
+// Synopsis: Switches to 16 bit and calls back to 16 bit.
+//
+// Arguments: [vpfn16] -- function pointer
+// [dwParam] -- pointer to parameter
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD WINAPI SSCallback16(DWORD vpfn16, DWORD dwParam)
+{
+ DWORD dwRet;
+ // switch to the 16 bit stack
+ //
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32->16(%p)\n",NestingLevelString(), vpfn16));
+ dwRet = SSCall(8, SSF_SmallStack, WOWCallback16, vpfn16, dwParam);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32<-16 done\n",NestingLevelString() ));
+ }
+ else
+ {
+ dwRet = WOWCallback16(vpfn16, dwParam);
+ }
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SSCallback16Ex
+//
+// Synopsis: Like SSCallback16 except can handle up 16 bytes of parametes
+//
+// Arguments: [vpfn16] -- see Callback16Ex
+// [dwFlags] --
+// [cbArgs] --
+// [pArgs] --
+// [pdwRetCode] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSCallback16Ex(DWORD vpfn16, DWORD dwFlags,
+ DWORD cbArgs, PVOID pArgs, PDWORD pdwRetCode)
+{
+ DWORD dwRet;
+ // switch to the 16 bit stack
+ //
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32->16 (%p)\n",NestingLevelString(), vpfn16));
+ dwRet = SSCall(20, SSF_SmallStack, WOWCallback16Ex,vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32<-16 done\n",NestingLevelString() ));
+ }
+ else
+ {
+ dwRet = WOWCallback16Ex(vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
+ }
+ return dwRet;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn32
+//
+// Synopsis: Switches to the 32 bit stack and calls SSAPI(InvokeOn32)
+//
+// Arguments: [dw1] -- See SSAPI(InvokeOn32)
+// [dwMethod] --
+// [pvStack16] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes: Only executed under WIN95
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) InvokeOn32 (DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
+{
+ DWORD dwRes;
+ if (SSONSMALLSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16->32 (0x%08x, %p)\n",
+ NestingLevelString(), dwMethod, pvStack16));
+ dwRes = SSCall(12 ,SSF_BigStack, SSInvokeOn32, dw1, dwMethod, pvStack16);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16<-32 done(0x%08x, %p)\n",
+ NestingLevelString(), dwMethod, pvStack16));
+ }
+ else
+ dwRes = SSInvokeOn32(dw1, dwMethod, pvStack16);
+
+ return dwRes;
+}
+
+#endif // _CHICAGO_
+
diff --git a/private/ole32/olethunk/olethk32/map_dwp.h b/private/ole32/olethunk/olethk32/map_dwp.h
new file mode 100644
index 000000000..7c2173143
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_dwp.h
@@ -0,0 +1,66 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapDwordPtr
+{
+public:
+ // Construction
+ CMapDwordPtr(UINT nBlockSize=10)
+ : m_mkv(sizeof(void FAR*), sizeof(DWORD), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID) &key, sizeof(DWORD), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(DWORD key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID) &key, sizeof(DWORD), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(DWORD key)
+ { return m_mkv.RemoveKey((LPVOID) &key, sizeof(DWORD)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, DWORD FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(DWORD key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(DWORD)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/olethunk/olethk32/map_kv.cxx b/private/ole32/olethunk/olethk32/map_kv.cxx
new file mode 100644
index 000000000..152c717d3
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.cxx
@@ -0,0 +1,540 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <olecoll.h>
+#include "map_kv.h"
+#include "plex.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+//CMapKeyToValue::CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey,
+CMapKeyToValue::CMapKeyToValue(UINT cbValue, UINT cbKey,
+ int nBlockSize, LPFNHASHKEY lpfnHashKey, UINT nHashSize)
+{
+ Assert(nBlockSize > 0);
+
+ m_cbValue = cbValue;
+ m_cbKey = cbKey;
+ m_cbKeyInAssoc = cbKey == 0 ? sizeof(CKeyWrap) : cbKey;
+
+ m_pHashTable = NULL;
+ m_nHashTableSize = nHashSize;
+ m_lpfnHashKey = lpfnHashKey;
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks = NULL;
+ m_nBlockSize = nBlockSize;
+ //if (memctx == MEMCTX_SAME)
+ // memctx = CoMemctxOf(this);
+ //m_memctx = memctx;
+ //Assert(m_memctx != MEMCTX_UNKNOWN);
+}
+
+CMapKeyToValue::~CMapKeyToValue()
+{
+ ASSERT_VALID(this);
+ RemoveAll();
+ Assert(m_nCount == 0);
+}
+
+
+// simple, default hash function
+// REVIEW: need to check the value in this for GUIDs and strings
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey)
+{
+ UINT hash = 0;
+ BYTE FAR* lpb = (BYTE FAR*)pKey;
+
+ while (cbKey-- != 0)
+ hash = 257 * hash + *lpb++;
+
+ return hash;
+}
+
+
+BOOL CMapKeyToValue::InitHashTable()
+{
+ ASSERT_VALID(this);
+ Assert(m_nHashTableSize > 0);
+
+ if (m_pHashTable != NULL)
+ return TRUE;
+
+ Assert(m_nCount == 0);
+
+ if ((m_pHashTable = (CAssoc FAR* FAR*)CoTaskMemAlloc(m_nHashTableSize * sizeof(CAssoc FAR*))) == NULL)
+ return FALSE;
+
+ memset(m_pHashTable, 0, sizeof(CAssoc FAR*) * m_nHashTableSize);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+
+void CMapKeyToValue::RemoveAll()
+{
+ ASSERT_VALID(this);
+
+ // free all key values and then hash table
+ if (m_pHashTable != NULL)
+ {
+ // destroy assocs
+ for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
+ {
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
+ pAssoc = pAssoc->pNext)
+ // assoc itself is freed by FreeDataChain below
+ FreeAssocKey(pAssoc);
+ }
+
+ // free hash table
+ CoTaskMemFree(m_pHashTable);
+ m_pHashTable = NULL;
+ }
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks->FreeDataChain();
+ m_pBlocks = NULL;
+
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Assoc helpers
+// CAssoc's are singly linked all the time
+
+CMapKeyToValue::CAssoc FAR*
+ CMapKeyToValue::NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ if (m_pFreeList == NULL)
+ {
+ // add another block
+ CPlex FAR* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, SizeAssoc());
+
+ if (newBlock == NULL)
+ return NULL;
+
+ // chain them into free list
+ register BYTE FAR* pbAssoc = (BYTE FAR*) newBlock->data();
+ // free in reverse order to make it easier to debug
+ pbAssoc += (m_nBlockSize - 1) * SizeAssoc();
+ for (int i = m_nBlockSize-1; i >= 0; i--, pbAssoc -= SizeAssoc())
+ {
+ ((CAssoc FAR*)pbAssoc)->pNext = m_pFreeList;
+ m_pFreeList = (CAssoc FAR*)pbAssoc;
+ }
+ }
+ Assert(m_pFreeList != NULL); // we must have something
+
+ CMapKeyToValue::CAssoc FAR* pAssoc = m_pFreeList;
+
+ // init all fields except pNext while still on free list
+ pAssoc->nHashValue = hash;
+ if (!SetAssocKey(pAssoc, pKey, cbKey))
+ return NULL;
+
+ SetAssocValue(pAssoc, pValue);
+
+ // remove from free list after successfully initializing it (except pNext)
+ m_pFreeList = m_pFreeList->pNext;
+ m_nCount++;
+ Assert(m_nCount > 0); // make sure we don't overflow
+
+ return pAssoc;
+}
+
+
+// free individual assoc by freeing key and putting on free list
+void CMapKeyToValue::FreeAssoc(CMapKeyToValue::CAssoc FAR* pAssoc)
+{
+ pAssoc->pNext = m_pFreeList;
+ m_pFreeList = pAssoc;
+ m_nCount--;
+ Assert(m_nCount >= 0); // make sure we don't underflow
+
+ FreeAssocKey(pAssoc);
+}
+
+
+// find association (or return NULL)
+CMapKeyToValue::CAssoc FAR*
+CMapKeyToValue::GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const
+{
+ if (m_lpfnHashKey)
+ nHash = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ nHash = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ if (m_pHashTable == NULL)
+ return NULL;
+
+ // see if it exists
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ return pAssoc;
+ }
+ return NULL;
+}
+
+
+BOOL CMapKeyToValue::CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey2, UINT cbKey2) const
+{
+ LPVOID pKey1;
+ UINT cbKey1;
+
+ GetAssocKeyPtr(pAssoc, &pKey1, &cbKey1);
+ return cbKey1 == cbKey2 && memcmp(pKey1, pKey2, cbKey1) == 0;
+}
+
+
+BOOL CMapKeyToValue::SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const
+{
+ Assert(cbKey == m_cbKey || m_cbKey == 0);
+
+ if (m_cbKey == 0)
+ {
+ Assert(m_cbKeyInAssoc == sizeof(CKeyWrap));
+
+ // alloc, set size and pointer
+ if ((pAssoc->key.pKey = CoTaskMemAlloc(cbKey)) == NULL)
+ return FALSE;
+
+ pAssoc->key.cbKey = cbKey;
+ }
+
+ LPVOID pKeyTo;
+
+ GetAssocKeyPtr(pAssoc, &pKeyTo, &cbKey);
+
+ memcpy(pKeyTo, pKey, cbKey);
+
+ return TRUE;
+}
+
+
+// gets pointer to key and its length
+void CMapKeyToValue::GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const
+{
+ if (m_cbKey == 0)
+ {
+ // variable length key; go indirect
+ *ppKey = pAssoc->key.pKey;
+ *pcbKey = pAssoc->key.cbKey;
+ }
+ else
+ {
+ // fixed length key; key in assoc
+ *ppKey = (LPVOID)&pAssoc->key;
+ *pcbKey = m_cbKey;
+ }
+}
+
+
+void CMapKeyToValue::FreeAssocKey(CAssoc FAR* pAssoc) const
+{
+ if (m_cbKey == 0)
+ CoTaskMemFree(pAssoc->key.pKey);
+}
+
+
+void CMapKeyToValue::GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const
+{
+ *ppValue = (char FAR*)&pAssoc->key + m_cbKeyInAssoc;
+}
+
+
+void CMapKeyToValue::GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueFrom;
+ GetAssocValuePtr(pAssoc, &pValueFrom);
+ Assert(pValue != NULL);
+ memcpy(pValue, pValueFrom, m_cbValue);
+}
+
+
+void CMapKeyToValue::SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueTo;
+ GetAssocValuePtr(pAssoc, &pValueTo);
+ if (pValue == NULL)
+ memset(pValueTo, 0, m_cbValue);
+ else
+ memcpy(pValueTo, pValue, m_cbValue);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// lookup value given key; return FALSE if key not found; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ UINT nHash;
+ HMAPKEY hmapkey = (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+ return LookupHKey(hmapkey, pValue);
+ //return LookupHKey((HMAPKEY)GetAssocAt(pKey, cbKey, nHash), pValue);
+}
+
+
+// lookup value given key; return FALSE if NULL (or bad) key; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::LookupHKey(HMAPKEY hKey, LPVOID pValue) const
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ {
+ memset(pValue, 0, m_cbValue);
+ return FALSE; // not in map
+ }
+
+ ASSERT_VALID(this);
+
+ GetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// lookup and if not found add; returns FALSE only if OOM; if added,
+// value added and pointer passed are set to zeros.
+BOOL CMapKeyToValue::LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ if (Lookup(pKey, cbKey, pValue))
+ return TRUE;
+
+ // value set to zeros since lookup failed
+
+ return ((CMapKeyToValue FAR*)this)->SetAt(pKey, cbKey, NULL);
+}
+
+
+// the only place new assocs are created; return FALSE if OOM;
+// never returns FALSE if keys already exists
+BOOL CMapKeyToValue::SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ UINT nHash;
+ register CAssoc FAR* pAssoc;
+
+ ASSERT_VALID(this);
+
+ if ((pAssoc = GetAssocAt(pKey, cbKey, nHash)) == NULL)
+ {
+ if (!InitHashTable())
+ // out of memory
+ return FALSE;
+
+ // it doesn't exist, add a new Association
+ if ((pAssoc = NewAssoc(nHash, pKey, cbKey, pValue)) == NULL)
+ return FALSE;
+
+ // put into hash table
+ pAssoc->pNext = m_pHashTable[nHash];
+ m_pHashTable[nHash] = pAssoc;
+
+ ASSERT_VALID(this);
+ }
+ else
+ {
+ SetAssocValue(pAssoc, pValue);
+ }
+
+ return TRUE;
+}
+
+
+// set existing hkey to value; return FALSE if NULL or bad key
+BOOL CMapKeyToValue::SetAtHKey(HMAPKEY hKey, LPVOID pValue)
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ return FALSE; // not in map
+
+ ASSERT_VALID(this);
+
+ SetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// remove key - return TRUE if removed
+BOOL CMapKeyToValue::RemoveKey(LPVOID pKey, UINT cbKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ UINT i;
+ if (m_lpfnHashKey)
+ i = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ i = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ ppAssocPrev = &m_pHashTable[i];
+
+ CAssoc FAR* pAssoc;
+ for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &pAssoc->pNext;
+ }
+ return FALSE; // not found
+}
+
+
+// remove key based on pAssoc (HMAPKEY)
+BOOL CMapKeyToValue::RemoveHKey(HMAPKEY hKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ // REVIEW: would like some way to verify that hKey is valid
+ CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL || pAssoc->nHashValue >= m_nHashTableSize)
+ // null hkey or bad hash value
+ return FALSE;
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[pAssoc->nHashValue];
+
+ while (*ppAssocPrev != NULL)
+ {
+ if (*ppAssocPrev == pAssoc)
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &(*ppAssocPrev)->pNext;
+ }
+
+ return FALSE; // not found (must have a screwed up list or passed
+ // a key from another list)
+}
+
+
+HMAPKEY CMapKeyToValue::GetHKey(LPVOID pKey, UINT cbKey) const
+{
+ UINT nHash;
+
+ ASSERT_VALID(this);
+
+ return (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Iterating
+
+// for fixed length keys, copies key to pKey; pcbKey can be NULL;
+// for variable length keys, copies pointer to key to pKey; sets pcbKey.
+
+void CMapKeyToValue::GetNextAssoc(POSITION FAR* pNextPosition,
+ LPVOID pKey, UINT FAR* pcbKey, LPVOID pValue) const
+{
+ ASSERT_VALID(this);
+
+ Assert(m_pHashTable != NULL); // never call on empty map
+
+ register CAssoc FAR* pAssocRet = (CAssoc FAR*)*pNextPosition;
+ Assert(pAssocRet != NULL);
+
+ if (pAssocRet == (CAssoc FAR*) BEFORE_START_POSITION)
+ {
+ // find the first association
+ for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
+ break;
+ Assert(pAssocRet != NULL); // must find something
+ }
+
+ // find next association
+ CAssoc FAR* pAssocNext;
+ if ((pAssocNext = pAssocRet->pNext) == NULL)
+ {
+ // go to next bucket
+ for (UINT nBucket = pAssocRet->nHashValue + 1;
+ nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
+ break;
+ }
+
+ // fill in return data
+ *pNextPosition = (POSITION) pAssocNext;
+
+ // fill in key/pointer to key
+ LPVOID pKeyFrom;
+ UINT cbKey;
+ GetAssocKeyPtr(pAssocRet, &pKeyFrom, &cbKey);
+ if (m_cbKey == 0)
+ // variable length key; just return pointer to key itself
+ *(void FAR* FAR*)pKey = pKeyFrom;
+ else
+ memcpy(pKey, pKeyFrom, cbKey);
+
+ if (pcbKey != NULL)
+ *pcbKey = cbKey;
+
+ // get value
+ GetAssocValue(pAssocRet, pValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CMapKeyToValue::AssertValid() const
+{
+#ifdef _DEBUG
+ Assert(m_cbKeyInAssoc == (m_cbKey == 0 ? sizeof(CKeyWrap) : m_cbKey));
+
+ Assert(m_nHashTableSize > 0);
+ Assert(m_nCount == 0 || m_pHashTable != NULL);
+
+ if (m_pHashTable != NULL)
+ Assert(!IsBadReadPtr(m_pHashTable, m_nHashTableSize * sizeof(CAssoc FAR*)));
+
+ if (m_lpfnHashKey)
+ Assert(!IsBadCodePtr((FARPROC)m_lpfnHashKey));
+
+ if (m_pFreeList != NULL)
+ Assert(!IsBadReadPtr(m_pFreeList, SizeAssoc()));
+
+ if (m_pBlocks != NULL)
+ Assert(!IsBadReadPtr(m_pBlocks, SizeAssoc() * m_nBlockSize));
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+ // REVIEW: Assert(m_memctx == MEMCTX_SHARED ||
+ // CoMemctxOf(this) == MEMCTX_UNKNOWN || CoMemctxOf(this) == m_memctx);
+#endif //_DEBUG
+}
+
diff --git a/private/ole32/olethunk/olethk32/map_kv.h b/private/ole32/olethunk/olethk32/map_kv.h
new file mode 100644
index 000000000..608b6bf32
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.h
@@ -0,0 +1,116 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+//#include <memapi.hxx>
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+#ifdef WIN32
+DECLARE_HANDLE(HMAPKEY);
+#else
+DECLARE_HANDLE32(HMAPKEY);
+#endif
+
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class FAR CMapKeyToValue
+{
+public:
+ CMapKeyToValue(UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10,
+ LPFNHASHKEY lpfnHashKey = NULL,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/olethunk/olethk32/map_kv.hxx b/private/ole32/olethunk/olethk32/map_kv.hxx
new file mode 100644
index 000000000..37e0ed7a1
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.hxx
@@ -0,0 +1,114 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+#ifdef WIN32
+DECLARE_HANDLE(HMAPKEY);
+#else
+DECLARE_HANDLE32(HMAPKEY);
+#endif
+
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class FAR CMapKeyToValue
+{
+public:
+ CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10, LPFNHASHKEY lpfnHashKey = &MKVDefaultHashKey,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+ DWORD m_memctx;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/olethunk/olethk32/mmodel.cxx b/private/ole32/olethunk/olethk32/mmodel.cxx
new file mode 100644
index 000000000..e097b16cb
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/mmodel.cxx
@@ -0,0 +1,232 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mmodel.cxx
+//
+// Contents: CMemoryModel
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+CMemoryModel16 mmodel16Public(TRUE);
+CMemoryModel16 mmodel16Owned(FALSE);
+CMemoryModel32 mmodel32;
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::AllocMemory
+//
+// Synopsis: Allocates memory
+//
+// Arguments: [cb] - Size of block to allocate
+//
+// Returns: New address of block or NULL
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CMemoryModel16::AllocMemory(DWORD cb)
+{
+ VPVOID vpv;
+ HMEM16 hmem16;
+
+ thkAssert(cb > 0);
+
+ vpv = WgtAllocLock(GMEM_MOVEABLE, cb, &hmem16);
+ if (vpv == 0)
+ {
+ //
+ // Not able to allocate a 16-bit memory block!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel16::AllocMemory, "
+ "Allocation failed, size %08lX\n",
+ cb));
+ return 0;
+ }
+
+ if (_fPublic)
+ {
+ SetOwnerPublicHMEM16(hmem16);
+ }
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::FreeMemory
+//
+// Synopsis: Deallocates a block of memory previously allocated
+//
+// Arguments: [dwMem] - Address of memory block to free
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel16::FreeMemory(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ WgtUnlockFree(dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::ResolvePtr
+//
+// Synopsis: Returns a resolved pointer given an abstract pointer
+//
+// Arguments: [dwMem] - Address to get pointer from
+// [cb] - Length, starting at given address, to make valid
+// pointers for.
+//
+// Returns: LPVOID - A real pointer equivalent to the abstract pointer.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+// Notes: Be careful of alignment issues
+//
+//----------------------------------------------------------------------------
+
+LPVOID CMemoryModel16::ResolvePtr(DWORD dwMem, DWORD cb)
+{
+ LPVOID pv;
+
+ thkAssert(dwMem != 0 && cb > 0);
+
+ pv = (LPVOID)WOWFIXVDMPTR(dwMem, cb);
+ if (pv == NULL)
+ {
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel16::ResolvePtr, "
+ "WOWGetVDMPointer failed on %08lX, size %08lX\n",
+ dwMem, cb));
+ }
+
+ return pv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMemoryModel16::ReleasePtr, public
+//
+// Synopsis: Releases a resolved pointer
+//
+// Arguments: [dwMem] - Abstract pointer to release
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel16::ReleasePtr(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ WOWRELVDMPTR(dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::AllocMemory
+//
+// Synopsis: Allocates memory
+//
+// Arguments: [cb] - Size of block to allocate
+//
+// Returns: New address of block or NULL
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CMemoryModel32::AllocMemory(DWORD cb)
+{
+ DWORD dwMem;
+
+ thkAssert(cb > 0);
+
+ dwMem = (DWORD)CoTaskMemAlloc(cb);
+ if (dwMem == 0)
+ {
+ //
+ // Not able to allocate a 32-bit memory block!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel32::AllocBlock, "
+ "CoTaskMemAlloc failed size %08lX\n",
+ cb));
+ return 0;
+ }
+
+ return dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::FreeMemory
+//
+// Synopsis: Deallocates a block of memory previously allocated
+//
+// Arguments: [dwMem] - Address of memory block to free
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel32::FreeMemory(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ CoTaskMemFree((LPVOID)dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::ResolvePtr
+//
+// Synopsis: Returns a resolved pointer given an abstract pointer
+//
+// Arguments: [dwMem] - Address to get pointer from
+// [cb] - Length, starting at given address, to make valid
+// pointers for.
+//
+// Returns: LPVOID - A real pointer equivalent to the abstract pointer.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+// Notes: Be careful of alignment issues
+//
+//----------------------------------------------------------------------------
+
+LPVOID CMemoryModel32::ResolvePtr(DWORD dwMem, DWORD cb)
+{
+ thkAssert(dwMem != 0 && cb > 0);
+
+ return (LPVOID)dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMemoryModel32::ReleasePtr, public
+//
+// Synopsis: Releases a resolved pointer
+//
+// Arguments: [dwMem] - Abstract pointer to release
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel32::ReleasePtr(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+}
diff --git a/private/ole32/olethunk/olethk32/mmodel.hxx b/private/ole32/olethunk/olethk32/mmodel.hxx
new file mode 100644
index 000000000..be7da2be2
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/mmodel.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mmodel.hxx
+//
+// Contents: CMemoryModel
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MMODEL_HXX__
+#define __MMODEL_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel (mm)
+//
+// Purpose: Defines an abstract interface to memory allocation
+// so that code can be written which uses both 16 and
+// 32-bit memory
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel
+{
+public:
+ virtual DWORD AllocMemory(DWORD cb) = 0;
+ virtual void FreeMemory(DWORD dwMem) = 0;
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb) = 0;
+ virtual void ReleasePtr(DWORD dwMem) = 0;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel16 (mm16)
+//
+// Purpose: 16-bit memory model
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel16 : public CMemoryModel
+{
+public:
+ CMemoryModel16(BOOL fPublic)
+ {
+ _fPublic = fPublic;
+ }
+
+ virtual DWORD AllocMemory(DWORD cb);
+ virtual void FreeMemory(DWORD dwMem);
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb);
+ virtual void ReleasePtr(DWORD dwMem);
+
+private:
+ BOOL _fPublic;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel32 (mm32)
+//
+// Purpose: 16-bit memory model
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel32 : public CMemoryModel
+{
+public:
+ virtual DWORD AllocMemory(DWORD cb);
+ virtual void FreeMemory(DWORD dwMem);
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb);
+ virtual void ReleasePtr(DWORD dwMem);
+};
+
+extern CMemoryModel16 mmodel16Public;
+extern CMemoryModel16 mmodel16Owned;
+extern CMemoryModel32 mmodel32;
+
+#endif // #ifndef __MMODEL_HXX__
diff --git a/private/ole32/olethunk/olethk32/nest.hxx b/private/ole32/olethunk/olethk32/nest.hxx
new file mode 100644
index 000000000..42b3f6aba
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/nest.hxx
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: nest.hxx
+//
+// Contents: Nested Log Helping macros & function
+//
+// History: 17-Jul-94 BobDay Split off from THOPUTIL.HXX due
+// to header ordering problems.
+//
+//----------------------------------------------------------------------------
+#ifndef __NEST_HXX__
+#define __NEST_HXX__
+
+#if DBG == 1
+
+extern int _iThunkNestingLevel;
+
+char *NestingLevelString(void);
+#define DebugIncrementNestingLevel() (_iThunkNestingLevel++)
+#define DebugDecrementNestingLevel() (_iThunkNestingLevel--)
+
+#else
+
+#define DebugIncrementNestingLevel()
+#define DebugDecrementNestingLevel()
+
+#endif
+
+#endif // #ifndef __NEST_HXX__
diff --git a/private/ole32/olethunk/olethk32/olethk32.cxx b/private/ole32/olethunk/olethk32/olethk32.cxx
new file mode 100644
index 000000000..520a04b9f
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.cxx
@@ -0,0 +1,616 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: olethk32.cxx
+//
+// Contents: Main routines for olethk32.dll
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#include <userapis.h>
+#pragma hdrstop
+
+#include <thkmgr.hxx>
+#include <stdio.h>
+
+
+DECLARE_INFOLEVEL(thk);
+DECLARE_INFOLEVEL(Stack);
+
+DATA16 gdata16Data;
+
+#if DBG == 1
+BOOL fSaveProxy = FALSE; // Used to find apps who call dead proxies
+BOOL fStabilizeProxies = TRUE; // Used to easily disable stabilization
+BOOL fZapProxy = FALSE; // Used to zap entries in freelist
+
+#ifdef _CHICAGO_
+BOOL fSSOn = TRUE;
+#endif // _CHICAGO_
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+void CallOutputFunctions(const char *buffer);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
+CLIPFORMAT g_cfLinkSourceDescriptor, g_cfObjectDescriptor;
+
+BYTE g_abLeadTable[256];
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoThreadDetach
+//
+// Synopsis: When a thread is detaching, cleanup for it.
+//
+// Effects: This is called during both DLL_THREAD_DETACH, and
+// DLL_PROCESS_DETACH.
+//
+// Arguments: (none)
+//
+// History: 3-18-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void
+DoThreadDetach()
+{
+ thkDebugOut((DEB_DLL,"_IN DoThreadDetach\n"));
+ //
+ // If there is thunk data, clean it up now.
+ //
+ if (TlsGetValue(dwTlsThkIndex) != NULL)
+ {
+ thkDebugOut((DEB_DLL,"DoThreadDetach calling ThkMgrUninitialize\n"));
+ ThkMgrUninitialize(0, 0, 0);
+ }
+ thkDebugOut((DEB_DLL,"OUT DoThreadDetach\n"));
+}
+//+---------------------------------------------------------------------------
+//
+// Function: LibMain, public
+//
+// Synopsis: DLL initialization entry point
+//
+// History: 23-Feb-94 DrewB Created
+//
+// Notes:
+//
+// (KevinRo 19-Mar-95)
+//
+// Caution needs to be exercised during cleanup. OLE32.DLL has
+// a pointer that we pass in during CoInitializeWOW. This pointer
+// is used to call back into OLETHK32 for cleanup purposes, as well as
+// accessing functions exposed by the 16-bit side. It is important that
+// when OLETHK32 unloads, the pointer in OLE32 is marked as invalid.
+// There is a call during the DLL_PROCESS_DETACH below that causes
+// OLE32 to invalidate its pointer.
+//
+// In addition, the last thread attached to a DLL will not generate
+// a DLL_THREAD_DETACH. Instead, it generates a DLL_PROCESS_DETACH. This
+// means that DLL_PROCESS_DETACH should perform all the steps that
+// DLL_THREAD_DETACH does in addition to whatever DLL_PROCESS_DETACH work
+// that needs to be done.
+//
+// Lastly, OLETHK32.DLL is statically linked to OLE32.DLL. This means
+// that OLETHK32.DLL's DLL_PROCESS_DETACH will be called before OLE32's.
+// That is why it is safe for us to call the OLE32 entry point during
+// DLL_PROCESS_DETACH
+//----------------------------------------------------------------------------
+
+extern "C" BOOL _CRTAPI1 LibMain(HANDLE hDll,
+ DWORD dwReason,
+ LPVOID lpReserved)
+{
+ switch( dwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+#if DBG == 1
+ char achInfoLevel[80];
+
+ if (GetProfileStringA("olethk32", "InfoLevel", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thkInfoLevel = strtol (achInfoLevel, NULL, 0);
+ }
+#endif
+ thkDebugOut((DEB_DLL,"_IN DLL_PROCESS_ATTACH\n"));
+
+ //
+ // Save a slot in the thread local storage for our PSTACK (pseudo-
+ // stack) pointer.
+ //
+
+ if (!TlsThkAlloc())
+ {
+ thkDebugOut((DEB_WARN, "TlsThkAlloc failed\n"));
+ return FALSE;
+ }
+ thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_ATTACH\n"));
+ break;
+
+ case DLL_THREAD_ATTACH:
+ thkDebugOut((DEB_DLL,"_IN DLL_THREAD_ATTACH\n"));
+ TlsSetValue(dwTlsThkIndex, NULL);
+ thkDebugOut((DEB_DLL,"OUT DLL_THREAD_ATTACH\n"));
+ break;
+
+ case DLL_THREAD_DETACH:
+ thkDebugOut((DEB_DLL,"_IN DLL_THREAD_DETACH\n"));
+
+ //
+ // Call OLE32.DLL and tell it to cleanup for this thread. This will
+ // not mark OLE32's ptr invalid since this is only a thread detach
+ // and not a process detach. This is a private API between OLE32 and
+ // OLETHK32.
+ //
+ thkDebugOut((DEB_DLL,"Calling Unload WOW for Thread Detach\n"));
+
+ CoUnloadingWOW(FALSE);
+
+ //
+ // When the thread for this task goes away, we need to clean out
+ // the thunk manager.
+ //
+
+ DoThreadDetach();
+
+ thkDebugOut((DEB_DLL,"OUT DLL_THREAD_DETACH\n"));
+ break;
+
+ case DLL_PROCESS_DETACH:
+ thkDebugOut((DEB_DLL,
+ "IN DLL_PROCESS_DETACH: %s\n",
+ lpReserved?"Process Exit":"Dll Unload"));
+
+ //
+ // The last threads cleanup needs to be done here.
+ //
+ if (lpReserved == NULL)
+ {
+ //
+ // Call OLE32.DLL and tell it to cleanup for this thread, and to
+ // never call us again, since we are going away. This is a private
+ // API between OLE32 and OLETHK32. This call will mark OLE32's
+ // private pointer to us as invalid.
+ //
+ thkDebugOut((DEB_DLL,"Calling Unload WOW\n"));
+
+ CoUnloadingWOW(TRUE);
+
+ //
+ // lpReserved being NULL means this cleanup is due to
+ // a FreeLibrary. If it was due to process exit, there
+ // is no way for us to determine the state of the data
+ // structures in the system. Other threads may have been
+ // right smack in the middle of taking apart data structures.
+ //
+ //
+ // Chicago unloads DLL's differently than NT. On Chicago, the
+ // 32-bit side cleans up first, plus resources allocated on
+ // the 32-bit side are released when the 16-bit process goes
+ // away. On NT, the 16-bit process is treated like a thread,
+ // so we have to cleanup.
+ //
+
+#ifndef _CHICAGO_
+ DoThreadDetach();
+#endif
+ //
+ // Only cleanup the memory if the process is not going away.
+ // On Windows NT, there are cases when the NTVDM needs to be
+ // blown away. We shouldn't be calling back to the 16-bit
+ // side in this case. Therefore, we explicitly call free here
+ // instead of putting it in the destructor.
+ //
+ flFreeList32.FreeMemoryBlocks();
+ flHolderFreeList.FreeMemoryBlocks();
+ flRequestFreeList.FreeMemoryBlocks();
+ }
+
+ TlsThkFree();
+
+ //
+ // Call to cleanup 16-bit memory if we are running on Win95.
+ // This should free up the 16-bit memory associated with this
+ // process. This is called in IntOpUninitialize on NT, since it
+ // needs to be called before the 16-bit side goes away.
+ //
+
+#ifdef _CHICAGO_
+ flFreeList16.FreeMemoryBlocks();
+#endif
+
+
+ thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_DETACH\n"));
+ break;
+ }
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IntOpInitialize, public
+//
+// Synopsis: Initializes the 32-bit interoperability code
+//
+// Arguments: [lpdata16] - 16-bit call data
+// [dw1] - Ignored
+// [dw2] - Ignored
+//
+// Returns: Appropriate status code
+//
+// History: 22-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI IntOpInitialize(LPDATA16 lpdata16, DWORD dw1, DWORD dw2)
+{
+ int i;
+
+ thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "_IN IntOpInitialize (%08lX)\n",
+ lpdata16));
+
+ thkAssert((THOP_LASTOP & ~THOP_OPMASK) == 0);
+
+#if DBG == 1
+ char achInfoLevel[80];
+#ifdef _CHICAGO_
+ if (GetProfileStringA("CairOLE InfoLevels",
+ "Stack", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ StackInfoLevel = strtol (achInfoLevel, NULL, 0);
+ }
+
+ if (GetProfileStringA("CairOLE InfoLevels",
+ "StackOn", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ fSSOn = strtol (achInfoLevel, NULL, 0);
+ }
+#endif // _CHICAGO_
+
+ if (GetProfileIntA("olethk32", "BreakOnInit", FALSE))
+ {
+ // DebugBreak's in WOW are fatal unless the exception
+ // is handled somehow. If a debugger is hooked up,
+ // it'll get first crack at the break exception
+ // If not, our handler will ignore the exception so
+ // execution can continue
+
+ __try
+ {
+ DebugBreak();
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ }
+
+ fSaveProxy = GetProfileIntA("olethk32", "SaveProxy", FALSE);
+ fZapProxy = GetProfileIntA("olethk32", "ZapProxy", FALSE);
+ fStabilizeProxies = GetProfileIntA("olethk32", "Stabilize", TRUE);
+#endif
+
+ // Copy passed parameter from 16-bit world...
+ memcpy( (LPVOID)&gdata16Data, (LPVOID)lpdata16, sizeof( DATA16 ) );
+
+#if defined(_CHICAGO_)
+ g_cfObjectDescriptor =
+ RegisterClipboardFormatA("Object Descriptor");
+ g_cfLinkSourceDescriptor =
+ RegisterClipboardFormatA("Link Source Descriptor");
+#else
+ g_cfObjectDescriptor =
+ RegisterClipboardFormat(__TEXT("Object Descriptor"));
+ g_cfLinkSourceDescriptor =
+ RegisterClipboardFormat(__TEXT("Link Source Descriptor"));
+#endif
+ if (g_cfObjectDescriptor == 0 || g_cfLinkSourceDescriptor == 0)
+ {
+ thkDebugOut((DEB_WARN, "IntOpInitialize: "
+ "Unable to register clipboard formats\n"));
+ return E_UNEXPECTED;
+ }
+
+ // Create a lookup table for lead-byte-ness
+ // so we can avoid calling IsDBCSLeadByte on every character
+ // during string validation
+ for (i = 0; i < 256; i++)
+ {
+ g_abLeadTable[i] = (BYTE)IsDBCSLeadByte((BYTE)i);
+ }
+
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpInitialize (%08lX)\n",
+ lpdata16));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IntOpUninitialize, public
+//
+// Synopsis: Cleanup initiated by 16-bit DLL unload
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// History: 29-Nov-94 DrewB Created
+//
+// Notes: (KevinRo) This routine is only called by compobj.dll. To make
+// things even more interesting, it is only called on Windows/NT. Win95
+// does the flFreeList16.FreeMemoryBlocks during PROCESS_DETACH. Cleanup
+// of the proxies is not neccessary on Win95, since the 16-bit process will
+// clean them up for us.
+//
+//----------------------------------------------------------------------------
+
+STDAPI IntOpUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "_IN IntOpUninitialize\n"));
+#ifndef _CHICAGO_
+ // Remove all existing proxies since we're going to free the
+ // proxy memory in the next step
+ if (TlsThkGetData() != NULL)
+ {
+ CThkMgr *ptm = TlsThkGetThkMgr();
+
+ if (ptm)
+ {
+ ptm->RemoveAllProxies();
+ }
+ }
+
+ // Clean up the 16-bit freelist at this time because we know
+ // that 16-bit code is still active and available for callback
+ // If we waited for the freelist destructor to be called, 16-bit
+ // code would already be cleaned up and the WOWGlobalFree calls
+ // would fail
+ flFreeList16.FreeMemoryBlocks();
+
+ WgtDump();
+#else
+ thkAssert(!"IntOpUninitialize called on Win95");
+#endif
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpUninitialize\n"));
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr1632Thunk, public
+//
+// Synopsis: Trivial function to allow calling HRESULT conversion
+// functions from 16-bit
+//
+// Arguments: [hr] - HRESULT to convert
+// [dw1]
+// [dw2]
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Required because 16-bit calls to CallProc32W use three
+// arguments
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr1632Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
+{
+ return TransformHRESULT_1632(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr3216Thunk, public
+//
+// Synopsis: Trivial function to allow calling HRESULT conversion
+// functions from 16-bit
+//
+// Arguments: [hr] - HRESULT to convert
+// [dw1]
+// [dw2]
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Required because 16-bit calls to CallProc32W use three
+// arguments
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr3216Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
+{
+ return TransformHRESULT_3216(hr);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThkAddAppCompatFlag
+//
+// Synopsis: Takes the given flag and ORs it into the current app
+// compatibility flag set
+//
+// Effects:
+//
+// Arguments: [dwFlag] -- flag to set
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Mar-95 alexgo author
+//
+// Notes: This function exists so that 16bit thunk dll's may
+// also set app compatibility flags. olethk32 code typically
+// sets the flags directly via TlsThkSetAppCompatFlags
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(void) ThkAddAppCompatFlag( DWORD dwFlag )
+{
+ DWORD dw;
+
+ dw = TlsThkGetAppCompatFlags();
+
+ dw |= dwFlag;
+
+ TlsThkSetAppCompatFlags(dw);
+}
+
+
+#if DBG == 1
+static LONG _wgtAllocated = 0;
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtAllocLock, public debug
+//
+// Synopsis: Tracking for WOWGlobalAllocLock16
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+VPVOID WgtAllocLock(WORD wFlags, DWORD cb, HMEM16 *ph)
+{
+ HMEM16 h;
+ VPVOID vpv;
+
+ vpv = WOWGlobalAllocLock16(wFlags, cb, &h);
+ if (vpv != 0)
+ {
+#ifdef WGT_TRACK
+ if (WOWGlobalLockSize16(h, &cb) != 0)
+ {
+ _wgtAllocated += cb;
+ WOWGlobalUnlock16(h);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to get size of allocated block 0x%04lX\n",
+ h));
+
+ // This is a guess at how big a block Win16 will allocate
+ _wgtAllocated += (cb+31) & 31;
+ }
+#endif
+
+ if (ph != NULL)
+ {
+ *ph = h;
+ }
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to allocate %d bytes of 16-bit memory\n",
+ cb));
+ }
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtUnlockFree, public
+//
+// Synopsis: Tracking for WOWGlobalUnlockFree16
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void WgtUnlockFree(VPVOID vpv)
+{
+ HMEM16 h;
+ DWORD cb;
+
+ if (vpv == 0)
+ {
+ thkDebugOut((DEB_WARN, "Attempt to free NULL\n"));
+ }
+ else
+ {
+#ifdef WGT_TRACK
+ // BUGBUG - Total hack, incorrect
+ h = (HMEM16)(vpv >> 16);
+
+ if (WOWGlobalLockSize16(h, &cb) != 0)
+ {
+ _wgtAllocated -= cb;
+ WOWGlobalUnlock16(h);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to get size of allocated block 0x%04lX\n",
+ h));
+ }
+#endif
+
+ WOWGlobalUnlockFree16(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtDump, public
+//
+// Synopsis: Dumps global tracking information
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void WgtDump(void)
+{
+ if (_wgtAllocated != 0)
+ {
+ thkDebugOut((DEB_WARN,
+ "%d bytes of 16-bit memory currently allocated\n",
+ _wgtAllocated));
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkCallOutputFunctions, public
+//
+// Synopsis: thunked pass-thru to Ole32 CallOutputFunctions for 16-bit land
+//
+// History: 23-Jan-95 murthys Created
+//
+//----------------------------------------------------------------------------
+
+void ThkCallOutputFunctions(const char * buffer, PVOID dummy1, PVOID dummy2)
+{
+ CallOutputFunctions(buffer);
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/olethunk/olethk32/olethk32.hxx b/private/ole32/olethunk/olethk32/olethk32.hxx
new file mode 100644
index 000000000..f78d48232
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.hxx
@@ -0,0 +1,31 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: olethk32.hxx
+//
+// Contents: Global definitions
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OLETHK32_HXX__
+#define __OLETHK32_HXX__
+
+extern DATA16 gdata16Data;
+
+#if DBG == 1
+extern BOOL fSaveProxy;
+extern BOOL fStabilizeProxies;
+extern BOOL fZapProxy;
+#endif
+
+extern CLIPFORMAT g_cfLinkSourceDescriptor, g_cfObjectDescriptor;
+
+extern BYTE g_abLeadTable[];
+
+extern DWORD dwTlsThkIndex;
+
+#endif // #ifndef __OLETHK32_HXX__
diff --git a/private/ole32/olethunk/olethk32/olethk32.rc b/private/ole32/olethunk/olethk32/olethk32.rc
new file mode 100644
index 000000000..87034fe3b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.rc
@@ -0,0 +1,14 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft OLE for Windows and Windows NT"
+#define VER_INTERNALNAME_STR "OLETHK32.DLL"
+#define VER_ORIGINALFILENAME_STR "OLETHK32.DLL"
+#include <common.ver>
+
+
diff --git a/private/ole32/olethunk/olethk32/plex.cxx b/private/ole32/olethunk/olethk32/plex.cxx
new file mode 100644
index 000000000..a00245bf2
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/plex.cxx
@@ -0,0 +1,45 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//#include <ole2int.h>
+#include "plex.h"
+
+// Collection support
+
+#define CairoleAssert(x) thkAssert(x)
+
+CPlex FAR* CPlex::Create(CPlex FAR* FAR& pHead, UINT nMax, UINT cbElement)
+{
+ CairoleAssert(nMax > 0 && cbElement > 0);
+ CPlex FAR* p = (CPlex FAR*)CoTaskMemAlloc(sizeof(CPlex) + nMax * cbElement);
+ if (p == NULL)
+ return NULL;
+
+ p->nMax = nMax;
+ p->nCur = 0;
+ p->pNext = pHead;
+ pHead = p; // change head (adds in reverse order for simplicity)
+ return p;
+}
+
+void CPlex::FreeDataChain() // free this one and links
+{
+ CPlex FAR* pThis;
+ CPlex FAR* pNext;
+
+ for (pThis = this; pThis != NULL; pThis = pNext) {
+ pNext = pThis->pNext;
+ pThis->pNext = NULL; // So compiler won't do nasty optimizations
+ CoTaskMemFree(pThis);
+ }
+}
diff --git a/private/ole32/olethunk/olethk32/plex.h b/private/ole32/olethunk/olethk32/plex.h
new file mode 100644
index 000000000..7095bb7ae
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/plex.h
@@ -0,0 +1,30 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#ifndef __PLEX_H__
+#define __PLEX_H__
+
+#define INTERNAL_(x) x
+
+struct FAR CPlex // warning variable length structure
+{
+ CPlex FAR* pNext;
+ UINT nMax;
+ UINT nCur;
+ /* BYTE data[maxNum*elementSize]; */
+
+ INTERNAL_(void FAR*) data() { return this+1; }
+
+ static INTERNAL_(CPlex FAR*) Create(CPlex FAR* FAR& head, UINT nMax, UINT cbElement);
+
+ INTERNAL_(void) FreeDataChain(); // free this one and links
+};
+
+#endif //__PLEX_H__
diff --git a/private/ole32/olethunk/olethk32/stalloc.cxx b/private/ole32/olethunk/olethk32/stalloc.cxx
new file mode 100644
index 000000000..363d49d9a
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/stalloc.cxx
@@ -0,0 +1,397 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stalloc.cxx
+//
+// Contents: CStackAllocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+// Notes: Loosely based on BobDay's original PSTACK implementation
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+// Pad a count to the given alignment
+// Alignment must be 2^n-1
+#define ALIGN_CB(cb, align) \
+ (((cb)+(align)) & ~(align))
+
+//+---------------------------------------------------------------------------
+//
+// Structure: SStackBlock (sb)
+//
+// Purpose: Header information for stack blocks
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+struct SStackBlock
+{
+ DWORD dwNextBlock;
+ DWORD dwStackTop;
+};
+
+#define BLOCK_OVERHEAD (sizeof(SStackBlock))
+#define BLOCK_START(mem) ((mem)+BLOCK_OVERHEAD)
+#define BLOCK_AVAILABLE(cb) ((cb)-BLOCK_OVERHEAD)
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::CStackAllocator, public
+//
+// Arguments: [pmm] - Memory model to use
+// [cbBlock] - Size of chunk to allocate when necessary
+// [cbAlignment] - Alignment size, must be 2^N
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CStackAllocator::CStackAllocator(CMemoryModel *pmm,
+ DWORD cbBlock,
+ DWORD cbAlignment)
+{
+ thkAssert(BLOCK_AVAILABLE(cbBlock) > 0);
+
+ // Ensure that the alignment is a power of two
+ thkAssert((cbAlignment & (cbAlignment-1)) == 0);
+ // Store alignment - 1 since that's the actual value we need for
+ // alignment computations
+ _cbAlignment = cbAlignment-1;
+
+ // Ensure that overhead and tracking will not affect alignment
+ thkAssert(ALIGN_CB(BLOCK_OVERHEAD, _cbAlignment) == BLOCK_OVERHEAD &&
+ ALIGN_CB(sizeof(SStackMemTrace), _cbAlignment) ==
+ sizeof(SStackMemTrace));
+
+ _pmm = pmm;
+ _cbBlock = cbBlock;
+ _dwBlocks = 0;
+ _dwCurrent = 0;
+ _cbAvailable = 0;
+
+ _psaNext = NULL;
+ _fActive = TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStackAllocator::~CStackAllocator, public virtual
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CStackAllocator::~CStackAllocator(void)
+{
+ Reset();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::Alloc, public
+//
+// Synopsis: Allocates a chunk of memory from the stack
+//
+// Arguments: [cb] - Amount of memory to allocate
+//
+// Returns: Pointer to memory or NULL
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CStackAllocator::Alloc(DWORD cb)
+{
+ DWORD dwMem;
+
+ thkAssert(cb > 0);
+
+ // Round size up to maintain alignment of stack
+ cb = ALIGN_CB(cb, _cbAlignment);
+
+#if DBG == 1
+ // Reserve space to record caller
+ cb += sizeof(SStackMemTrace);
+#endif
+
+ thkAssert(cb <= BLOCK_AVAILABLE(_cbBlock));
+
+ // Check to see if the current block can hold the new allocation
+ if (cb > _cbAvailable)
+ {
+ DWORD dwBlock;
+ SStackBlock UNALIGNED *psb;
+
+ // It's too big, so allocate a new block
+ dwBlock = _pmm->AllocMemory(_cbBlock);
+ if (dwBlock == 0)
+ {
+ return 0;
+ }
+
+ if (_dwBlocks != 0)
+ {
+ // Update current top block
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ psb->dwStackTop = _dwCurrent;
+ _pmm->ReleasePtr(_dwBlocks);
+ }
+
+ // Make the new block the top block
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(dwBlock, sizeof(SStackBlock));
+ psb->dwNextBlock = _dwBlocks;
+ _dwBlocks = dwBlock;
+ _pmm->ReleasePtr(dwBlock);
+
+ _dwCurrent = BLOCK_START(dwBlock);
+ _cbAvailable = BLOCK_AVAILABLE(_cbBlock);
+ }
+
+ thkAssert(_cbAvailable >= cb);
+
+ dwMem = _dwCurrent;
+ _dwCurrent += cb;
+ _cbAvailable -= cb;
+
+#if DBG == 1
+ void *pvMem;
+
+ // Fill memory to show reuse problems
+ pvMem = _pmm->ResolvePtr(dwMem, cb);
+ memset(pvMem, 0xED, cb);
+ _pmm->ReleasePtr(dwMem);
+#endif
+
+#if DBG == 1
+ SStackMemTrace UNALIGNED *psmt;
+
+ psmt = (SStackMemTrace UNALIGNED *)
+ _pmm->ResolvePtr(_dwCurrent-sizeof(SStackMemTrace),
+ sizeof(SStackMemTrace));
+ psmt->cbSize = cb-sizeof(SStackMemTrace);
+
+#if !defined(_CHICAGO_)
+ //
+ // On RISC platforms, psmt points to an unaligned structure.
+ // Use a temp variable so we don't get an alignment fault
+ // when RtlGetCallersAddress returns the value.
+ //
+ void *pv;
+ void *pvCaller;
+ RtlGetCallersAddress(&pvCaller, &pv);
+ psmt->pvCaller = pvCaller;
+#else
+ // Depends on return address being directly below first argument
+ psmt->pvCaller = *((void **)&cb-1);
+#endif
+
+ thkDebugOut((DEB_MEMORY, "Stack: %p alloc 0x%08lX:%3d, avail %d\n",
+ psmt->pvCaller, dwMem, cb, _cbAvailable));
+
+ _pmm->ReleasePtr(_dwCurrent-sizeof(SStackMemTrace));
+#endif
+
+ return dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::Free, public
+//
+// Synopsis: Frees allocated memory
+//
+// Arguments: [dwMem] - Memory
+// [cb] - Amount of memory allocated
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CStackAllocator::Free(DWORD dwMem, DWORD cb)
+{
+ thkAssert(dwMem != 0);
+ thkAssert(cb > 0);
+
+ // Round size up to maintain alignment of stack
+ cb = ALIGN_CB(cb, _cbAlignment);
+
+#if DBG == 1
+ cb += sizeof(SStackMemTrace);
+#endif
+
+ thkAssert(cb <= BLOCK_AVAILABLE(_cbBlock));
+
+#if DBG == 1
+ void *pvCaller;
+
+#if !defined(_CHICAGO_)
+ void *pv;
+ RtlGetCallersAddress(&pvCaller, &pv);
+#else
+ // Depends on return address being directly below first argument
+ pvCaller = *((void **)&dwMem-1);
+#endif
+
+ thkDebugOut((DEB_MEMORY, "Stack: %p frees 0x%08lX:%3d, avail %d\n",
+ pvCaller, dwMem, cb, _cbAvailable));
+#endif
+
+#if DBG == 1
+ if (_dwCurrent-cb != dwMem)
+ {
+ thkDebugOut((DEB_ERROR, "Free of %d:%d is not TOS (0x%08lX)\n",
+ dwMem, cb, _dwCurrent));
+
+ thkAssert(_dwCurrent-cb == dwMem);
+ }
+#endif
+
+ _dwCurrent -= cb;
+ _cbAvailable += cb;
+
+#if DBG == 1
+ void *pvMem;
+
+ // Fill memory to show reuse problems
+ pvMem = _pmm->ResolvePtr(dwMem, cb);
+ memset(pvMem, 0xDD, cb);
+ _pmm->ReleasePtr(dwMem);
+#endif
+
+ if (_dwCurrent == BLOCK_START(_dwBlocks))
+ {
+ SStackBlock UNALIGNED *psb;
+ DWORD dwBlock;
+
+ // If we've just freed up an entire block and it's not the
+ // only block for the stack, free the block itself and
+ // restore stack state from the next block
+ // We keep the first block around forever to avoid memory
+ // thrashing
+
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ dwBlock = psb->dwNextBlock;
+ _pmm->ReleasePtr(_dwBlocks);
+
+ if (dwBlock != 0)
+ {
+ _pmm->FreeMemory(_dwBlocks);
+
+ _dwBlocks = dwBlock;
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ _dwCurrent = psb->dwStackTop;
+ _cbAvailable = _cbBlock-(_dwCurrent-_dwBlocks);
+ _pmm->ReleasePtr(_dwBlocks);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStackAllocator::Reset, public
+//
+// Synopsis: Releases all memory in the stack
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CStackAllocator::Reset(void)
+{
+ DWORD dwBlock;
+ SStackBlock UNALIGNED *psb;
+
+ while (_dwBlocks != 0)
+ {
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ dwBlock = psb->dwNextBlock;
+ _pmm->ReleasePtr(_dwBlocks);
+
+ _pmm->FreeMemory(_dwBlocks);
+
+ _dwBlocks = dwBlock;
+ }
+
+ _dwCurrent = 0;
+ _cbAvailable = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::RecordState, public debug
+//
+// Synopsis: Records the current state of the stack
+//
+// Arguments: [psr] - Storage space for information
+//
+// Modifies: [psr]
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CStackAllocator::RecordState(SStackRecord *psr)
+{
+ psr->dwStackPointer = _dwCurrent;
+ psr->dwThreadId = GetCurrentThreadId();
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::CheckState, public debug
+//
+// Synopsis: Checks recorded information about the stack against its
+// current state
+//
+// Arguments: [psr] - Recorded information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CStackAllocator::CheckState(SStackRecord *psr)
+{
+ thkAssert(psr->dwThreadId == GetCurrentThreadId());
+
+ if ((psr->dwStackPointer != 0 && psr->dwStackPointer != _dwCurrent) ||
+ (psr->dwStackPointer == 0 &&
+ _dwCurrent != 0 && _dwCurrent != BLOCK_START(_dwBlocks)))
+ {
+ thkDebugOut((DEB_ERROR, "Stack alloc change: 0x%08lX to 0x%08lX\n",
+ psr->dwStackPointer, _dwCurrent));
+
+ if (_dwCurrent > BLOCK_START(_dwBlocks))
+ {
+ SStackMemTrace UNALIGNED *psmt;
+
+ psmt = (SStackMemTrace UNALIGNED *)
+ _pmm->ResolvePtr(_dwCurrent-sizeof(SStackMemTrace),
+ sizeof(SStackMemTrace));
+ thkDebugOut((DEB_ERROR, "Top alloc: %d bytes by %p\n",
+ psmt->cbSize, psmt->pvCaller));
+ _pmm->ReleasePtr(_dwCurrent-sizeof(SStackMemTrace));
+ }
+
+ thkAssert(!((psr->dwStackPointer != 0 &&
+ psr->dwStackPointer != _dwCurrent) ||
+ (psr->dwStackPointer == 0 &&
+ _dwCurrent != 0 ||
+ _dwCurrent != BLOCK_START(_dwBlocks))));
+ }
+}
+#endif
diff --git a/private/ole32/olethunk/olethk32/stalloc.hxx b/private/ole32/olethunk/olethk32/stalloc.hxx
new file mode 100644
index 000000000..7e4a35afc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/stalloc.hxx
@@ -0,0 +1,113 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stalloc.hxx
+//
+// Contents: CStackAllocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STALLOC_HXX__
+#define __STALLOC_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Struct: SStackMemTrace (smt)
+//
+// Purpose: Stack memory size/leak checking information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+struct SStackMemTrace
+{
+ void *pvCaller;
+ UINT cbSize;
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Class: SStackRecord (sr)
+//
+// Purpose: Capture stack allocation state
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+struct SStackRecord
+{
+ DWORD dwStackPointer;
+ DWORD dwThreadId;
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStackAllocator (sa)
+//
+// Purpose: Abstract definition of a stack allocator with
+// replaceable underlying memory allocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CStackAllocator
+{
+public:
+ CStackAllocator(CMemoryModel *pmm,
+ DWORD cbBlock,
+ DWORD cbAlignment);
+ ~CStackAllocator(void);
+
+ DWORD Alloc(DWORD cb);
+ void Free(DWORD dwMem, DWORD cb);
+
+#if DBG == 1
+ void RecordState(SStackRecord *psr);
+ void CheckState(SStackRecord *psr);
+#endif
+
+ void Reset(void);
+
+ CStackAllocator *GetNextAllocator(void)
+ {
+ return _psaNext;
+ }
+ void SetNextAllocator(CStackAllocator *psa)
+ {
+ _psaNext = psa;
+ }
+
+ BOOL GetActive(void)
+ {
+ return _fActive;
+ }
+ void SetActive(BOOL fActive)
+ {
+ _fActive = fActive;
+ }
+
+private:
+ DWORD _cbBlock;
+ DWORD _cbAlignment;
+ CMemoryModel *_pmm;
+
+ DWORD _dwBlocks;
+ DWORD _dwCurrent;
+ DWORD _cbAvailable;
+
+ CStackAllocator *_psaNext;
+ BOOL _fActive;
+};
+
+#endif // #ifndef __STALLOC_HXX__
diff --git a/private/ole32/olethunk/olethk32/struct16.hxx b/private/ole32/olethunk/olethk32/struct16.hxx
new file mode 100644
index 000000000..5c2674061
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/struct16.hxx
@@ -0,0 +1,91 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: struct16.hxx
+//
+// Contents: 16-bit structures for use in 32-bit code
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+#ifndef __STRUCT16_HXX__
+#define __STRUCT16_HXX__
+
+#pragma pack(2)
+
+typedef struct tagRECT16
+{
+ SHORT left;
+ SHORT top;
+ SHORT right;
+ SHORT bottom;
+} RECT16;
+typedef RECT16 UNALIGNED FAR *LPRECT16;
+
+typedef struct tagFORMATETC16
+{
+ CLIPFORMAT cfFormat;
+ VPVOID ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+} FORMATETC16;
+typedef FORMATETC16 UNALIGNED FAR* LPFORMATETC16;
+
+typedef struct tagOIFI16
+{
+ WORD cb;
+ WORD fMDIApp;
+ HAND16 hwndFrame;
+ HAND16 haccel;
+ SHORT cAccelEntries;
+} OIFI16;
+typedef OIFI16 UNALIGNED FAR* LPOIFI16;
+
+typedef struct tagSTATDATA16
+{ // field used by:
+ FORMATETC16 formatetc; // EnumAdvise, EnumData (cache),
+ // EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ VPVOID pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+} STATDATA16;
+typedef STATDATA16 UNALIGNED FAR * LPSTATDATA16;
+
+typedef struct tagMSG16
+{
+ HWND16 hwnd;
+ WORD message;
+ WORD wParam;
+ LONG lParam;
+ DWORD time;
+ ULONG pt;
+} MSG16;
+typedef MSG16 UNALIGNED FAR *LPMSG16;
+
+typedef struct tagSIZE16
+{
+ SHORT cx;
+ SHORT cy;
+} SIZE16;
+
+typedef struct tagMETAFILEPICT16
+{
+ SHORT mm;
+ SHORT xExt;
+ SHORT yExt;
+ HMETAFILE16 hMF;
+} METAFILEPICT16;
+
+typedef struct tagINTERFACEINFO16
+{
+ VPVOID pUnk;
+ IID iid;
+ WORD wMethod;
+} INTERFACEINFO16;
+
+#pragma pack()
+
+#endif // #ifndef __STRUCT16_HXX__
diff --git a/private/ole32/olethunk/olethk32/tc1632.cxx b/private/ole32/olethunk/olethk32/tc1632.cxx
new file mode 100644
index 000000000..a7a66b70b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tc1632.cxx
@@ -0,0 +1,323 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tc1632.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+DWORD ThunkCall1632(THUNKINFO *pti)
+{
+ DWORD dwReturn;
+ thkAssert(pti->pvfn != NULL);
+ thkAssert(*pti->pThop == THOP_END);
+ pti->pThop++;
+ thkAssert(*pti->pThop == THOP_ROUTINEINDEX);
+ pti->pThop++;
+ if (FAILED(pti->scResult))
+ {
+ return (DWORD)pti->scResult;
+ }
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+ switch(*pti->pThop)
+ {
+ case 0:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 1:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0)
+ );
+ break;
+ case 2:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12)
+ );
+ break;
+ case 3:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 4:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24)
+ );
+ break;
+ case 5:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 6:
+ dwReturn = (*(DWORD (__stdcall *)())pti->pvfn)(
+ );
+ break;
+ case 7:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 8:
+ dwReturn = (*(DWORD (__stdcall *)(
+ WORD,
+ WORD,
+ DWORD))pti->pvfn)(
+ *(WORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 9:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 10:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 11:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ ULARGE_INTEGER,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 12:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 13:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 14:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24),
+ *(DWORD *)(pti->s32.pbStart+28),
+ *(DWORD *)(pti->s32.pbStart+32),
+ *(DWORD *)(pti->s32.pbStart+36),
+ *(DWORD *)(pti->s32.pbStart+40)
+ );
+ break;
+ case 15:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ SIZEL,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(SIZEL *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 16:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ SIZEL,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(SIZEL *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 17:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ WORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(WORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 18:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ SIZEL))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(SIZEL *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 19:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ WORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 20:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24),
+ *(DWORD *)(pti->s32.pbStart+28)
+ );
+ break;
+ case 21:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ WORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24)
+ );
+ break;
+ }
+
+#if DBG == 1
+ if ( !pti->fResultThunked && FAILED(dwReturn) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "ThunkCall1632 pvfn = %08lX Probably failed hr = %08lX\n",
+ pti->pvfn, dwReturn));
+ }
+
+#endif
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
+ return dwReturn;
+}
diff --git a/private/ole32/olethunk/olethk32/the.hxx b/private/ole32/olethunk/olethk32/the.hxx
new file mode 100644
index 000000000..69d320238
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/the.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: the.hxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#define THE_IEnumString 0
+#define THE_IEnumUnknown 1
+#define THE_IEnumSTATSTG 2
+#define THE_IEnumFORMATETC 3
+#define THE_IEnumSTATDATA 4
+#define THE_IEnumMoniker 5
+#define THE_IEnumOLEVERB 6
diff --git a/private/ole32/olethunk/olethk32/thi.hxx b/private/ole32/olethunk/olethk32/thi.hxx
new file mode 100644
index 000000000..5f754af85
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thi.hxx
@@ -0,0 +1,73 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thi.hxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#define THI_IUnknown 0
+#define THI_IClassFactory 1
+#define THI_IMalloc THI_COUNT
+#define THI_IMarshal 2
+#define THI_IStdMarshalInfo 3
+#define THI_IMessageFilter 4
+#define THI_IExternalConnection 5
+#define THI_IEnumString 6
+#define THI_IEnumUnknown 7
+#define THI_IEnumSTATSTG 8
+#define THI_ILockBytes 9
+#define THI_IStream 10
+#define THI_IStorage 11
+#define THI_IRootStorage 12
+#define THI_IEnumFORMATETC 13
+#define THI_IEnumSTATDATA 14
+#define THI_IDataObject 15
+#define THI_IViewObject 16
+#define THI_IViewObject2 17
+#define THI_IAdviseSink 18
+#define THI_IAdviseSink2 19
+#define THI_IDataAdviseHolder 20
+#define THI_IOleCache 21
+#define THI_IOleCache2 22
+#define THI_IOleCacheControl 23
+#define THI_IDropTarget 24
+#define THI_IDropSource 25
+#define THI_IPersist 26
+#define THI_IPersistStorage 27
+#define THI_IPersistStream 28
+#define THI_IPersistFile 29
+#define THI_IBindCtx 30
+#define THI_IMoniker 31
+#define THI_IRunningObjectTable 32
+#define THI_IEnumMoniker 33
+#define THI_IEnumOLEVERB 34
+#define THI_IOleObject 35
+#define THI_IOleClientSite 36
+#define THI_IRunnableObject 37
+#define THI_IParseDisplayName 38
+#define THI_IOleContainer 39
+#define THI_IOleItemContainer 40
+#define THI_IOleAdviseHolder 41
+#define THI_IOleLink 42
+#define THI_IOleWindow 43
+#define THI_IOleInPlaceObject 44
+#define THI_IOleInPlaceActiveObject 45
+#define THI_IOleInPlaceUIWindow 46
+#define THI_IOleInPlaceFrame 47
+#define THI_IOleInPlaceSite 48
+#define THI_IRpcChannelBuffer 49
+#define THI_IRpcProxyBuffer 50
+#define THI_IRpcStubBuffer 51
+#define THI_IPSFactoryBuffer 52
+#define THI_IRpcChannel 53
+#define THI_IRpcProxy 54
+#define THI_IRpcStub 55
+#define THI_IPSFactory 56
+#define THI_COUNT 57
diff --git a/private/ole32/olethunk/olethk32/thkmgr.cxx b/private/ole32/olethunk/olethk32/thkmgr.cxx
new file mode 100644
index 000000000..983bdbecb
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thkmgr.cxx
@@ -0,0 +1,536 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thkmgr.cxx
+//
+// Contents: Thunk manager initialization
+// IUnknown transition functions
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkMgrInitialize
+//
+// Synopsis: Creates a new thunkmanager and set it for given thread
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+// Notes: Called from CoInitialize
+//
+//----------------------------------------------------------------------------
+STDAPI ThkMgrInitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ CThkMgr *pcthkmgr = NULL;
+
+ thkDebugOut((DEB_THUNKMGR, "In ThkMgrInitialize()\n"));
+
+ //
+ // If we are already initialized, do nothing.
+ //
+ if (TlsGetValue(dwTlsThkIndex) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR, "OUT ThkMgrInitialize() Already Init\n"));
+ return(NOERROR);
+ }
+
+ //
+ // initialize the Tls storage
+ //
+ if ( NOERROR != TlsThkInitialize())
+ {
+ thkDebugOut((DEB_ERROR, "TlsThkInitialize failed"));
+
+ return E_OUTOFMEMORY;
+ }
+
+ thkAssert(TlsThkGetThkMgr() == NULL);
+
+ pcthkmgr = CThkMgr::Create();
+ TlsThkSetThkMgr(pcthkmgr);
+
+ thkDebugOut((DEB_THUNKMGR, "Out ThkMgrInitialize() => %p\n",
+ pcthkmgr));
+
+ return (pcthkmgr == NULL) ? E_OUTOFMEMORY : NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkMgrUninitialize
+//
+// Synopsis: deletes the thunkmanager and removes it from thread data
+// tls data are removed as well
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+// Notes: Called during CoUninitialize
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) ThkMgrUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ thkDebugOut((DEB_THUNKMGR, "In ThkMgrUninitialize()\n"));
+
+ thkAssert(TlsGetValue(dwTlsThkIndex) != NULL);
+
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ if (pcthkmgr != NULL)
+ {
+ // Note: the thunkmanger gets removed from tlsthk
+ delete pcthkmgr;
+ }
+
+ // If we weren't called from 16-bit code then it's not safe to reset
+ // the 16-bit stack allocator here because we may be doing this
+ // in thread cleanup and it may not be safe to call back into
+ // 16-bit code
+
+ TlsThkGetStack32()->Reset();
+
+ // uninitialize the tls data for this apartment
+ TlsThkUninitialize();
+
+ thkDebugOut((DEB_THUNKMGR, "Out ThkMgrUninitialize()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IUnknownObj32
+//
+// Synopsis: Entry point from 16bit for IUnknown methods
+//
+// Arguments: [vpvThis16] -- Proxy object
+// [wMethod] -- IUnknown method
+// [vpvData] -- Call data
+//
+// Returns: Call result, pdata contains out data for particular call
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) IUnknownObj32(VPVOID vpvThis16, DWORD wMethod, VPVOID vpvData)
+{
+ DWORD dwRet;
+ LONG vpvInterface;
+ IID iid;
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: IUnknownObj32 call refused\n"));
+
+ if (wMethod == SMI_QUERYINTERFACE)
+ {
+ return (DWORD)E_FAIL;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // Note: at this point we should always get a thunkmanager
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ thkAssert(vpvThis16 != 0 && "IUnknownObj32: invalid pointer." );
+ thkAssert(wMethod >= 0 && wMethod < SMI_COUNT);
+
+ switch (wMethod)
+ {
+ case SMI_QUERYINTERFACE:
+ thkAssert(vpvData != NULL &&
+ "IUnknownObj32.QueryInterface without IID");
+
+ // Copy the 16-bit IID into 32-bit memory for the real call
+ iid = *FIXVDMPTR(vpvData, IID);
+ RELVDMPTR(vpvData);
+
+ thkDebugOut((DEB_UNKNOWN,
+ "%sIn QueryInterface1632(%p, %s)\n",
+ NestingLevelString(), vpvThis16,
+ IidOrInterfaceString(&iid)));
+
+ dwRet = pcthkmgr->QueryInterfaceProxy1632(vpvThis16, iid,
+ (void **)&vpvInterface);
+
+ // Translate the 32-bit HRESULT to a 16-bit HRESULT
+ dwRet = (DWORD)TransformHRESULT_3216((HRESULT)dwRet);
+
+ // Pass the return interface pointer back through the IID
+ // memory. We re-resolve the data pointer since nested
+ // calls may have occurred
+ (FIXVDMPTR(vpvData, IID))->Data1 = vpvInterface;
+ RELVDMPTR(vpvData);
+
+ thkDebugOut((DEB_UNKNOWN,
+ "%sOut QueryInterface1632(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), vpvThis16, vpvInterface, dwRet));
+ break;
+
+ case SMI_ADDREF:
+ thkDebugOut((DEB_UNKNOWN, "%sIn AddRef1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+
+ dwRet = pcthkmgr->AddRefProxy1632(vpvThis16);
+
+ thkDebugOut((DEB_UNKNOWN, "%sOut AddRef1632(%p) => %d\n",
+ NestingLevelString(), vpvThis16, dwRet));
+ break;
+
+ case SMI_RELEASE:
+ thkDebugOut((DEB_UNKNOWN, "%sIn Release1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+
+ dwRet = pcthkmgr->ReleaseProxy1632(vpvThis16);
+
+ thkDebugOut((DEB_UNKNOWN, "%sOut Release1632(%p) => %d\n",
+ NestingLevelString(), vpvThis16, dwRet));
+ break;
+ }
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterfaceProxy3216
+//
+// Synopsis: call QueryInterface on a 32 bit proxy
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+// [refiid] -- Interface queried for
+// [ppv] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto, REFIID refiid, LPVOID *ppv)
+{
+ HRESULT hrRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn QueryInterface3216(%p, %s)\n",
+ NestingLevelString(), pto,
+ IidOrInterfaceString(&refiid)));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QIProxy3216 call refused\n"));
+
+ return E_FAIL;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "QueryInterfaceProxy3216: Attempt to QI "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX %s\n",
+ pto, pto->vpvThis16,
+ IidIdxString(IID_IIDIDX(&refiid)) ));
+ *ppv = NULL;
+ return E_FAIL;
+ }
+
+ hrRet = pcthkmgr->QueryInterfaceProxy3216(pto, refiid, ppv);
+
+ //
+ // If the QI for IUnknown failed, then return the current this
+ // pointer as the IUnknown. Watermark 1.02 appears to not support
+ // IUnknown in its IOleInPlaceActiveObject interface, which causes
+ // CoMarshalInterface to fail. The reason it used to work is the
+ // original 16-bit DLL's would just use the provided pointer as
+ // the punk if IUnknown wasn't supported. The following lines of
+ // code emulate that behaviour.
+ //
+ if ((hrRet == E_NOINTERFACE) && IsEqualIID(refiid,IID_IUnknown))
+ {
+ thkDebugOut((DEB_UNKNOWN,
+ "%s Object %p didn't support QI(IID_IUnknown): Faking it\n",
+ NestingLevelString(), pto));
+ ((IUnknown *)pto)->AddRef();
+ *ppv = pto;
+ hrRet = S_OK;
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN,
+ "%sOut QueryInterface3216(%p) => %p, ret:0x%08lX\n",
+ NestingLevelString(), pto, *ppv, hrRet));
+ return hrRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRefProxy3216
+//
+// Synopsis: call addref on an 16 bit object
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+//
+// Returns: New refcount
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD AddRefProxy3216(THUNK3216OBJ *pto)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn AddRef3216(%p)\n",
+ NestingLevelString(), pto));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: AddRefProxy3216 call refused\n"));
+
+ return 0;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "AddRefProxy3216: Attempt to AddRef "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ pto, pto->vpvThis16));
+ return 0;
+ }
+
+ dwRet = pcthkmgr->AddRefProxy3216(pto);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN, "%sOut AddRef3216(%p) => %ld\n",
+ NestingLevelString(), pto, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseProxy3216
+//
+// Synopsis: Release implementation for 32->16 proxies
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+//
+// Returns: New refcount
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD ReleaseProxy3216(THUNK3216OBJ *pto)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn Release3216(%p)\n",
+ NestingLevelString(), pto));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy3216 call refused\n"));
+
+ return 0;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "ReleaseProxy3216: Attempt to Release "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ pto, pto->vpvThis16));
+ return 0;
+ }
+
+ dwRet = pcthkmgr->ReleaseProxy3216(pto);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN, "%sOut Release3216(%p) => %ld\n",
+ NestingLevelString(), pto, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterfaceOnObj16
+//
+// Synopsis: call QueryInterface on an 16 bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+// [refiid] -- IID
+// [ppv] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+struct QIARGS
+{
+ IID iid;
+ void *pvObject;
+};
+
+HRESULT QueryInterfaceOnObj16(VPVOID vpvThis16, REFIID refiid, LPVOID *ppv)
+{
+ HRESULT hrRet;
+ VPVOID vpvArgs;
+ QIARGS UNALIGNED *pqa;
+ BYTE bArgs32[WCB16_MAX_CBARGS];
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceOnObj16(%p, %s)\n",
+ NestingLevelString(), vpvThis16,
+ IidOrInterfaceString(&refiid)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(WCB16_MAX_CBARGS >= 3*sizeof(DWORD));
+ thkAssert(vpvThis16 != 0 && "QueryInterfaceOnObj16: invalid pointer.");
+
+ // Allocate space for the sixteen bit arguments memory
+ vpvArgs = STACKALLOC16(sizeof(QIARGS));
+ if (vpvArgs == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Fill in the in-param memory
+ pqa = FIXVDMPTR(vpvArgs, QIARGS);
+ pqa->iid = refiid;
+
+ // Set up the 16-bit stack in pascal order
+ *(VPVOID *)(bArgs32+0*sizeof(VPVOID)) = vpvArgs+
+ FIELD_OFFSET(QIARGS, pvObject);
+ *(VPVOID *)(bArgs32+1*sizeof(VPVOID)) = vpvArgs;
+ *(VPVOID *)(bArgs32+2*sizeof(VPVOID)) = vpvThis16;
+
+ RELVDMPTR(vpvArgs);
+
+ // Call to 16-bit stub
+ if (!CallbackTo16Ex(gdata16Data.fnQueryInterface16, WCB16_PASCAL,
+ 3*sizeof(DWORD), bArgs32, (DWORD *)&hrRet))
+ {
+ hrRet = E_UNEXPECTED;
+ }
+
+ // Transform the 16-bit HRESULT to a 32-bit HRESULT
+ hrRet = TransformHRESULT_1632(hrRet);
+
+ // Copy back out-param memory
+ pqa = FIXVDMPTR(vpvArgs, QIARGS);
+ *ppv = pqa->pvObject;
+ RELVDMPTR(vpvArgs);
+
+ STACKFREE16(vpvArgs, sizeof(QIARGS));
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceOnObj16(%p) => %p, ret:0x%08lX\n",
+ NestingLevelString(), vpvThis16, *ppv, hrRet));
+
+ return hrRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRefOnObj16
+//
+// Synopsis: calls addref on an 16 bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+//
+// Returns: New ref count
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+DWORD AddRefOnObj16(VPVOID vpvThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefOnObj16(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ dwRet = CallbackTo16(gdata16Data.fnAddRef16, vpvThis16);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefOnObj16(%p) => %ld\n",
+ NestingLevelString(), vpvThis16, dwRet));
+
+ return dwRet;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseOnObj16
+//
+// Synopsis: Release a 16-bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+//
+// Returns: New ref count
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+DWORD ReleaseOnObj16(VPVOID vpvThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseOnObj16(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ dwRet = CallbackTo16(gdata16Data.fnRelease16, vpvThis16);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseOnObj16(%p) => %ld\n",
+ NestingLevelString(), vpvThis16, dwRet));
+
+ return dwRet;
+}
+#endif
+
+#if DBG == 1
+void DebugDump()
+{
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+ pcthkmgr->DebugDump3216();
+ pcthkmgr->DebugDump1632();
+}
+#endif
+
diff --git a/private/ole32/olethunk/olethk32/thkmgr.hxx b/private/ole32/olethunk/olethk32/thkmgr.hxx
new file mode 100644
index 000000000..28ed5cbb4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thkmgr.hxx
@@ -0,0 +1,40 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thkmgr.hxx
+//
+// Contents: 16->32 and 32->16 thunk manager definitions
+//
+// History: 23-Mar-94 JohannP Created
+// 22-May-94 BobDay Split out 16-bit definitions
+// into obj16.hxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THKMGR_HXX__
+#define __THKMGR_HXX__
+
+STDAPI ThkMgrInitialize(DWORD dw1, DWORD dw2, DWORD dw3);
+STDAPI_(void) ThkMgrUninitialize(DWORD dw1, DWORD dw2, DWORD dw3);
+
+//
+// 32->16 prototypes
+//
+
+SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto, REFIID refiid, LPVOID *ppv);
+DWORD AddRefProxy3216(THUNK3216OBJ *pto);
+DWORD ReleaseProxy3216(THUNK3216OBJ *pto);
+
+HRESULT QueryInterfaceOnObj16(VPVOID vpvThis16, REFIID refiid, LPVOID *ppv);
+
+#if DBG == 1
+DWORD AddRefOnObj16(VPVOID vpvThis16);
+DWORD ReleaseOnObj16(VPVOID vpvThis16);
+#else
+#define AddRefOnObj16(this) CallbackTo16(gdata16Data.fnAddRef16, this)
+#define ReleaseOnObj16(this) CallbackTo16(gdata16Data.fnRelease16, this)
+#endif
+
+#endif // #ifndef __THKMGR_HXX__
diff --git a/private/ole32/olethunk/olethk32/thop.hxx b/private/ole32/olethunk/olethk32/thop.hxx
new file mode 100644
index 000000000..159eabfa5
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop.hxx
@@ -0,0 +1,241 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop.hxx
+//
+// Contents: Defines the available thops
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOP_HXX__
+#define __THOP_HXX__
+
+//
+// THOP is a single instruction to the interpreter that encodes,
+// decodes parameters sent via LRPC. A string of THOPs describes how to
+// marshal, unmarshal function's paramaters.
+//
+//
+
+typedef enum
+{
+ THOP_END,
+ // Basic types size of type (win3.1)
+ THOP_SHORTLONG, // Signed ints 2b
+ THOP_WORDDWORD, // Unsigned int 2b
+ THOP_COPY, // Direct copies
+ THOP_LPSTR, // LPSTR -- (zero terminated)
+ THOP_LPLPSTR, // LPLPSTR -- (zero terminated)
+ THOP_BUFFER, // void FAR* -- (size in next long)
+
+ // Windows types
+ THOP_HUSER, // HWND, HMENU 2b
+ THOP_HGDI, // HDC, HICON 2b
+ THOP_SIZE, // SIZE 4b
+ THOP_RECT, // RECT 8b
+ THOP_MSG, // MSG 18b
+
+ // Ole types
+ THOP_HRESULT, // HRESULT 4b
+ THOP_STATSTG, // STATSTG > 38b + size of member lpstr
+ THOP_DVTARGETDEVICE, // DVTARGETDEVICE > 16b
+ THOP_STGMEDIUM, // STGMEDIUM > 12b + size of member lpstr
+ THOP_FORMATETC, // FORMATETC > 18b + size of member tdev
+ THOP_HACCEL, // HACCEL 2b
+ THOP_OIFI, // OLEINPLACEFRAMEINFO 10b
+ THOP_BINDOPTS, // BIND_OPTS > 12b
+ THOP_LOGPALETTE, // LOGPALETTE > 8b
+ THOP_SNB, // SNBs in storage Varies
+ THOP_CRGIID, // ciid, rgiid pair from storage
+ THOP_OLESTREAM, // OLESTREAM
+ THOP_HTASK, // HTASK
+ THOP_INTERFACEINFO, // INTERFACEINFO
+
+ THOP_IFACE, // Known interface type
+ THOP_IFACEOWNER, // For IFACE cases with weak references
+ THOP_IFACENOADDREF, // For IFACE cases with no references by user (IOleCacheControl)
+ THOP_IFACECLEAN, // For IRpcStubBuffer::DebugServerRelease
+ THOP_IFACEGEN, // for QueryInterface, etc (refiid, **ppUnk)
+ THOP_IFACEGENOWNER, // For IFACEGEN cases with weak references
+
+ THOP_ROUTINEINDEX, // Thop for indicating the call type index
+ THOP_RETURNTYPE, // Thop for indicating return type of a routine if
+ // not HRESULT
+ THOP_NULL, // NULL ptr, for checking of reserved fields
+ THOP_ERROR, // Invalid thop, for debugging
+ THOP_ENUM, // Enumerator thop start
+ THOP_CALLBACK, // Callback function and argument
+ THOP_RPCOLEMESSAGE, // RPCOLEMESSAGE
+ THOP_ALIAS32, // 16-bit alias for 32-bit quantity
+ THOP_CLSCONTEXT, // Flags DWORD with special handling
+ THOP_FILENAME, // String which is a filename, needs long/short cvt
+ THOP_SIZEDSTRING, // String which cannot exceed a certain length
+
+ THOP_LASTOP, // Marker for last op
+
+ THOP_OPMASK = 0x3f, // Mask for basic operation code
+
+ // Modifiers
+ THOP_IOMASK = 0xc0,
+ THOP_IN = 0x40, // FAR Pointer to in parameter
+ THOP_OUT = 0x80, // FAR Pointer to out parameter
+ THOP_INOUT = 0xc0 // FAR Pointer to in, out parameter
+} THOP_TYPE;
+
+typedef unsigned char THOP;
+
+#define ALIAS_CREATE 0
+#define ALIAS_RESOLVE 1
+#define ALIAS_REMOVE 2
+
+#define MAX_PARAMS 16
+
+typedef DWORD (__stdcall * VTBLFN)(DWORD dw);
+
+typedef struct tagSTACK16INFO
+{
+ BYTE UNALIGNED *pbStart;
+ BYTE UNALIGNED *pbCurrent;
+ int iDir;
+} STACK16INFO;
+
+typedef struct tagSTACK32INFO
+{
+ BYTE *pbStart;
+ BYTE *pbCurrent;
+} STACK32INFO;
+
+typedef struct tagTHUNKINFO
+{
+ STACK16INFO s16;
+ STACK32INFO s32;
+ THOP CONST *pThop;
+ VTBLFN pvfn;
+ SCODE scResult;
+ BOOL fResultThunked;
+ DWORD dwCallerProxy;
+ CThkMgr *pThkMgr;
+ IIDIDX iidx;
+ DWORD dwMethod;
+ IUnknown *this32;
+} THUNKINFO;
+
+// These are declared extern "C" because there was a bug in the
+// PPC compiler (aug '95) where the const related decorations on
+// the global data symbols was not done consistantly. By using
+// extern "C" the bug is simply avoided.
+// The problem was only with aThopFunctions*[] but I added
+// aThopEnumFunctions*[] for a consistent look and usage. A related
+// bug is fixed with apthopsApiThops[].
+
+extern "C" DWORD (* CONST aThopFunctions1632[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopFunctions3216[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopEnumFunctions1632[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopEnumFunctions3216[])(THUNKINFO *);
+
+#define SKIP_STACK16(s16, cb) \
+ (s16)->pbCurrent = (s16)->iDir < 0 ? \
+ (s16)->pbCurrent-(cb) : \
+ (s16)->pbCurrent+(cb)
+
+#define PTR_STACK16(s16, cb) \
+ ((s16)->pbCurrent-((s16)->iDir < 0 ? (cb) : 0))
+
+#define GET_STACK16(pti, val, typ) \
+ if ((pti)->s16.iDir < 0) \
+ { \
+ (pti)->s16.pbCurrent -= sizeof(typ); \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent; \
+ } \
+ else \
+ { \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent; \
+ (pti)->s16.pbCurrent += sizeof(typ); \
+ }
+
+#define TO_STACK16(pti, val, typ) \
+ if ((pti)->s16.iDir < 0) \
+ { \
+ (pti)->s16.pbCurrent -= sizeof(typ); \
+ *(typ UNALIGNED *)(pti)->s16.pbCurrent = (val); \
+ } \
+ else \
+ { \
+ *(typ UNALIGNED *)(pti)->s16.pbCurrent = (val); \
+ (pti)->s16.pbCurrent += sizeof(typ); \
+ }
+
+#define PEEK_STACK16(pti, val, typ) \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent
+
+#define INDEX_STACK16(pti, val, typ, idx, predec) \
+ (val) = *(typ UNALIGNED *)((pti)->s16.iDir < 0 ? \
+ ((pti)->s16.pbCurrent+(idx)-(predec)) : \
+ ((pti)->s16.pbCurrent-(idx)))
+
+#define SKIP_STACK32(s32, cb) \
+ (s32)->pbCurrent += (cb)
+
+#define PTR_STACK32(s32) \
+ (s32)->pbCurrent
+
+#define GET_STACK32(pti, val, typ) \
+ (val) = *(typ *)(pti)->s32.pbCurrent; \
+ SKIP_STACK32(&(pti)->s32, sizeof(typ))
+
+#define TO_STACK32(pti, val, typ) \
+ *(typ *)(pti)->s32.pbCurrent = (val);\
+ SKIP_STACK32(&(pti)->s32, sizeof(typ))
+
+#define PEEK_STACK32(pti, val, typ) \
+ (val) = *(typ *)(pti)->s32.pbCurrent
+
+#define INDEX_STACK32(pti, val, typ, idx) \
+ (val) = *(typ *)((pti)->s32.pbCurrent-(idx))
+
+#if DBG == 0
+
+// In debug builds this goes through a function that can emit
+// debug info about thops being executed
+#define EXECUTE_THOP1632(pti) \
+ (*aThopFunctions1632[*((pti)->pThop) & THOP_OPMASK])(pti)
+#define EXECUTE_THOP3216(pti) \
+ (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti)
+#define EXECUTE_ENUMTHOP1632(pti) \
+ (*aThopEnumFunctions1632[*(pti)->pThop])(pti)
+#define EXECUTE_ENUMTHOP3216(pti) \
+ (*aThopEnumFunctions3216[*(pti)->pThop])(pti)
+
+#else
+
+DWORD EXECUTE_THOP1632(THUNKINFO *pti);
+DWORD EXECUTE_THOP3216(THUNKINFO *pti);
+DWORD EXECUTE_ENUMTHOP1632(THUNKINFO *pti);
+DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti);
+
+#endif
+
+#define IS_THOP_IN(pti) ((*((pti)->pThop) & THOP_IN) == THOP_IN)
+#define IS_THOP_OUT(pti) ((*((pti)->pThop) & THOP_OUT) == THOP_OUT)
+
+// Max size of preallocated strings
+#define CBSTRINGPREALLOC 512
+#define CWCSTRINGPREALLOC (CBSTRINGPREALLOC/sizeof(WCHAR))
+
+// BUGBUG - Max size?
+#define CCHMAXSTRING 0x1000
+
+// Max size of preallocated palettes
+#define NPALETTEPREALLOC 256
+
+// Size of a LOGPALETTE structure with N entries
+#define CBPALETTE(n) (sizeof(LOGPALETTE)+((n)-1)*sizeof(PALETTEENTRY))
+
+// Hide the exact field in the RPCOLEMESSAGE we use to store thunking data
+#define ROM_THUNK_FIELD(rom) ((rom)->reserved1)
+
+#endif // #ifndef __THOP_HXX__
diff --git a/private/ole32/olethunk/olethk32/thop16.cxx b/private/ole32/olethunk/olethk32/thop16.cxx
new file mode 100644
index 000000000..32d0ec207
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop16.cxx
@@ -0,0 +1,4114 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop16.cxx
+//
+// Contents: Thop implementations for 16->32
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2.h>
+#include <valid.h>
+#include <string.h>
+
+#include "struct16.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: EXECUTE_THOP1632, public
+//
+// Synopsis: Debugging version of thop dispatch routine
+//
+// Arguments: [pti] - Thunking info
+//
+// Returns: Appropriate status
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+DWORD EXECUTE_THOP1632(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExThop1632: %s (0x%02X), s16 %p, s32 %p\n",
+ ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
+ return (*aThopFunctions1632[*((pti)->pThop) & THOP_OPMASK])(pti);
+}
+#endif
+
+#if DBG == 1
+DWORD EXECUTE_ENUMTHOP1632(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExEnumThop1632: %s (0x%02X), s16 %p, s32 %p\n",
+ EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ return (*aThopEnumFunctions1632[*(pti)->pThop])(pti);
+}
+#endif
+
+// Generated by the tool, in tc1632.cxx
+DWORD ThunkCall1632( THUNKINFO * );
+
+//+---------------------------------------------------------------------------
+//
+// Function: FixedThopHandler, public
+//
+// Synopsis: Generic function which handles the high-level details
+// of thop execution for thops that operate on known-size
+// data
+//
+// Arguments: [pti] - Thunking state information
+// [thop] - Thop being executed
+// [cb16] - 16-bit size
+// [pfn1632] - 16->32 conversion routine
+// [cb32] - 32-bit size
+// [pfn3216] - 32->16 conversion routine
+//
+// Returns: Appropriate status code
+//
+// History: 05-Apr-94 DrewB Created
+//
+// Notes: Automatically increments pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD FixedThopHandler1632(THUNKINFO *pti,
+ THOP thop,
+ UINT cb16,
+ FIXEDHANDLERROUTINE pfn1632,
+ UINT cb32,
+ FIXEDHANDLERROUTINE pfn3216)
+{
+ DWORD dwResult;
+ VPVOID vp16;
+ BYTE *pb16;
+ BYTE *pb32;
+
+ if ((thop & (THOP_IN | THOP_OUT)) != 0)
+ {
+ pb32 = NULL;
+
+ GET_STACK16(pti, vp16, VPVOID);
+ if ( vp16 != 0 )
+ {
+ pb16 = (BYTE *)ValidatePtr16(pti, vp16, cb16, thop);
+ if (pb16 != NULL)
+ {
+ pb32 = (BYTE *)STACKALLOC32(cb32);
+ if (pb32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else if ((thop & THOP_IN) != 0)
+ {
+ (pfn1632)(pb16, pb32, cb16, cb32);
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ TO_STACK32(pti, pb32, BYTE *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ((thop & THOP_OUT) != 0 && vp16 != 0)
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ (pfn3216)(pb32, pb16, cb32, cb16);
+ }
+ else if ((thop & THOP_IN) == 0)
+ {
+ // Zero out-only parameters on failure
+ memset(pb16, 0, cb16);
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+
+ if (pb32 != NULL)
+ {
+ STACKFREE32(pb32, cb32);
+ }
+ }
+ else
+ {
+ (pfn1632)(PTR_STACK16(&pti->s16, cb16), PTR_STACK32(&pti->s32),
+ cb16, cb32);
+ SKIP_STACK16(&pti->s16, cb16);
+ SKIP_STACK32(&pti->s32, cb32);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+ }
+
+ return dwResult;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Handler-based thunks
+//
+// These thunks use the fixed-size generic thop handler to do their work
+//
+//-----------------------------------------------------------------------------
+
+// Handle straight copy
+DWORD Thop_Copy_1632(THUNKINFO *pti)
+{
+ THOP thopSize;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
+
+ thopSize = *++pti->pThop;
+ return FixedThopHandler1632(pti,
+ *(pti->pThop-1),
+ thopSize, FhCopyMemory,
+ thopSize, FhCopyMemory);
+}
+
+DWORD Thop_ShortToLong_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(SHORT), FhShortToLong,
+ sizeof(LONG), FhLongToShort);
+}
+
+DWORD Thop_WordToDword_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(WORD), FhWordToDword,
+ sizeof(DWORD), FhDwordToWord);
+}
+
+DWORD Thop_GdiHandle_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhGdiHandle1632,
+ sizeof(HANDLE), FhGdiHandle3216);
+}
+
+DWORD Thop_UserHandle_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhUserHandle1632,
+ sizeof(HANDLE), FhUserHandle3216);
+}
+
+DWORD Thop_HACCEL_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHaccel1632,
+ sizeof(HANDLE), FhHaccel3216);
+}
+
+DWORD Thop_HTASK_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHtask1632,
+ sizeof(HANDLE), FhHtask3216);
+}
+
+DWORD Thop_HRESULT_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HRESULT), FhHresult1632,
+ sizeof(HRESULT), FhHresult3216);
+}
+
+DWORD Thop_NULL_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(void *), FhNull,
+ sizeof(void *), FhNull);
+}
+
+DWORD Thop_RECT_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(RECT16), FhRect1632,
+ sizeof(RECT), FhRect3216);
+}
+
+DWORD Thop_BINDOPTS_1632( THUNKINFO *pti )
+{
+ VPVOID vpbo16;
+ BIND_OPTS UNALIGNED *pbo;
+ UINT cb;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
+
+ PEEK_STACK16(pti, vpbo16, VPVOID);
+ pbo = (BIND_OPTS UNALIGNED *)GetReadPtr16(pti, vpbo16, sizeof(BIND_OPTS));
+ if (pbo != NULL)
+ {
+ cb = pbo->cbStruct;
+ WOWRELVDMPTR(vpbo16);
+ }
+ else
+ {
+ // Doesn't really matter, since pti->scResult was set to error
+ // by GetReadPtr16
+ cb = sizeof(BIND_OPTS);
+ }
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ cb, FhCopyMemory,
+ cb, FhCopyMemory);
+}
+
+DWORD Thop_SIZE_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(SIZE16), FhSize1632,
+ sizeof(SIZE), FhSize3216);
+}
+
+DWORD Thop_MSG_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(MSG16), FhMsg1632,
+ sizeof(MSG), FhMsg3216);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ERROR_1632, public
+//
+// Synopsis: Any Thop type which should just fail with an error
+// should go be directed here.
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_ERROR_1632 ( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
+
+ thkAssert( FALSE && "Hey we hit an ERROR Thop in 16->32" );
+
+ return (DWORD)E_UNEXPECTED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInString1632, public
+//
+// Synopsis: Converts an in-parameter string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInString1632(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ VPSTR vpstr;
+ LPOLESTR lpstrDest;
+ OLECHAR *ptcStackText;
+
+ dwResult = (DWORD)S_OK;
+ ptcStackText = NULL;
+
+ GET_STACK16(pti, vpstr, VPSTR);
+
+ if (vpstr == 0)
+ {
+ lpstrDest = NULL;
+ }
+ else
+ {
+ ptcStackText = (OLECHAR *)STACKALLOC32(CWCSTRINGPREALLOC*
+ sizeof(OLECHAR));
+ if (ptcStackText == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpstrDest = Convert_VPSTR_to_LPOLESTR( pti, vpstr, ptcStackText,
+ CWCSTRINGPREALLOC );
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 LPSTR: %p -> %p '%ws'\n",
+ vpstr, lpstrDest, lpstrDest));
+
+ TO_STACK32(pti, lpstrDest, LPOLESTR );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (lpstrDest != NULL)
+ {
+ Convert_VPSTR_to_LPOLESTR_free( ptcStackText, lpstrDest );
+ }
+
+ if (ptcStackText != NULL)
+ {
+ STACKFREE32(ptcStackText, CWCSTRINGPREALLOC*sizeof(OLECHAR));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPSTR_1632, public
+//
+// Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LPSTR_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
+ //
+ // We have only input LPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "LPSTR must be input only!" );
+
+ return ThunkInString1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertTaskString3216, public
+//
+// Synopsis: Converts a task-memory string
+//
+// Arguments: [pti] - Thunk info
+// [pos32] - String
+// [vpstrPreAlloc] - Preallocated string or NULL
+// [cchPreAlloc] - Preallocated size or zero
+// [pvpstr16] - String
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pti]
+// [pvpstr16]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Frees preallocation if successful and:
+// Name is too large or
+// Name is NULL
+//
+// Always frees source string if non-zero and valid
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertTaskString3216(THUNKINFO *pti,
+ LPOLESTR pos32,
+ VPSTR vpstrPreAlloc,
+ UINT cchPreAlloc,
+ VPSTR UNALIGNED *pvpstr16)
+{
+ VPVOID vpstr16;
+ UINT cch;
+ SCODE sc;
+
+ sc = S_OK;
+
+ if (pos32 == NULL)
+ {
+ vpstr16 = 0;
+ }
+ else
+ {
+ if (IsBadStringPtrW(pos32, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ cch = lstrlenW(pos32)+1;
+
+ if (cch > cchPreAlloc)
+ {
+ // Our prealloc buffer is too small, so try and get a
+ // new one
+
+ // Allow for each Unicode character to take two
+ // bytes in case of multibyte expansion
+ vpstr16 = (VPSTR)TaskMalloc16( cch*2 );
+ if (vpstr16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpstr16 = vpstrPreAlloc;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ sc = Convert_LPOLESTR_to_VPSTR(pos32, vpstr16, cch, cch*2);
+ if (FAILED(sc) && vpstr16 != vpstrPreAlloc)
+ {
+ TaskFree16(vpstr16);
+ }
+ }
+
+ TaskFree32(pos32);
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // If there was a preallocated string we didn't use,
+ // free it
+ if (vpstrPreAlloc != 0 && vpstrPreAlloc != vpstr16)
+ {
+ TaskFree16(vpstrPreAlloc);
+ }
+
+ *pvpstr16 = vpstr16;
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkOutString1632, public
+//
+// Synopsis: Converts an out param string or filename
+//
+// Arguments: [pti] - Thunk state information
+// [fFile] - Filename or plain string
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkOutString1632(THUNKINFO *pti,
+ BOOL fFile)
+{
+ DWORD dwResult;
+ VPVOID vpvpstr16;
+ VPSTR vpstr16;
+ VPSTR UNALIGNED *lpvpstr16;
+ LPOLESTR *lplpstr32;
+ LPOLESTR lpstr;
+
+ GET_STACK16(pti, vpvpstr16, VPSTR);
+
+ lplpstr32 = NULL;
+ if ( vpvpstr16 != 0 )
+ {
+ lpvpstr16 = (VPSTR UNALIGNED *)GetWritePtr16(pti, vpvpstr16,
+ sizeof(VPSTR));
+ if ( lpvpstr16 != NULL )
+ {
+ WOWRELVDMPTR(vpvpstr16);
+
+ lplpstr32 = &lpstr;
+
+ vpstr16 = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
+ if (vpstr16 == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ }
+ }
+
+ TO_STACK32(pti, lplpstr32, LPOLESTR FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lplpstr32 != NULL )
+ {
+ if ( SUCCEEDED(dwResult) )
+ {
+ SCODE sc;
+
+ if (fFile)
+ {
+ UINT cch;
+
+ // The string pointed to by lpstr is ours so we
+ // can do the long->short conversion in place
+ // without worrying about trashing the memory
+ // The short path name should always be able
+ // to fit in the long path name's buffer since
+ // the file names that we are thunking are always
+ // absolute paths
+
+ cch = lstrlenW(lpstr)+1;
+
+ // Ignore failures; if we can't convert the name
+ // then we simply pass on what we were given
+ GetShortPathName(lpstr, lpstr, cch);
+ }
+
+ sc = ConvertTaskString3216(pti, lpstr, vpstr16,
+ CWCSTRINGPREALLOC, &vpstr16);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree16(vpstr16);
+ vpstr16 = 0;
+ }
+
+ lpvpstr16 = FIXVDMPTR( vpvpstr16, VPSTR );
+ *lpvpstr16 = vpstr16;
+
+#if DBG==1
+ thkDebugOut((DEB_ARGS, "Out1632 LPLPSTR: %p -> %p '%s'\n",
+ lpstr, vpstr16,
+ vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
+ if (vpstr16 != 0)
+ {
+ WOWRELVDMPTR(vpstr16);
+ }
+#endif
+
+ RELVDMPTR( vpvpstr16 );
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Out1632 LPLPSTR NULL\n"));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPLPSTR_1632, public
+//
+// Synopsis: Converts 32-bit LPSTR to 16-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_LPLPSTR_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
+ //
+ // We don't have anything but unmodified LPLPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "LPLPSTR must be unmodified only!" );
+
+ return ThunkOutString1632(pti, FALSE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_BUFFER_1632, public
+//
+// Synopsis: Converts 16-bit block of memory to 32-bit block of memory
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+// 14-Mar-95 KentCe Buffer copy not required for Win95.
+//
+// Notes: WARNING! WARNING! WARNING! For an out parameter this expects
+// three parameters on the stack in the following format and order:
+// VOID * pointer to buffer
+// DWORD count of bytes in buffer
+// DWORD * count of bytes returned in the buffer
+//
+//----------------------------------------------------------------------------
+
+#define WATCH_VALUE 0xfef1f0
+
+DWORD Thop_BUFFER_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vp16;
+ LPVOID lp16;
+ LPVOID lp32;
+ DWORD dwCount;
+ VPVOID vp16CountOut;
+ DWORD dwCountOut32 = 0;
+ DWORD * pdwCountOut32 = &dwCountOut32;
+#if DBG == 1
+ DWORD dwWatch;
+#endif
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We only have in and out BUFFER thops
+ //
+ thkAssert((fThopInput || fThopOutput)
+ && (fThopInput != fThopOutput)
+ && "BUFFER must be in or out only!" );
+
+ GET_STACK16(pti, vp16, VPVOID);
+ GET_STACK16(pti, dwCount, DWORD);
+
+ if (fThopOutput)
+ {
+ // Get the pointer to the returned value off the stack
+ GET_STACK16(pti, vp16CountOut, VPVOID);
+ }
+
+ lp32 = NULL;
+
+ if (vp16 == 0)
+ {
+ // lp32 is already NULL
+ }
+ else if (dwCount == 0)
+ {
+ // If the count is zero then we can pass any valid 32-bit
+ // pointer
+
+#if DBG == 1
+ // In debug, make sure that no data is written back to the
+ // memory we pass on
+ dwWatch = WATCH_VALUE;
+ lp32 = &dwWatch;
+#else
+ lp32 = &dwResult;
+#endif
+ }
+ else
+ {
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+#if defined(_CHICAGO_)
+ lp32 = WOWFIXVDMPTR(vp16, dwCount);
+#else
+ lp16 = ValidatePtr16(pti, vp16, dwCount, *pti->pThop);
+
+ if ( lp16 != NULL )
+ {
+ lp32 = (LPVOID)CoTaskMemAlloc( dwCount );
+ if ( lp32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ if ( fThopInput )
+ {
+ memcpy( lp32, lp16, dwCount );
+ }
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+#endif
+ }
+
+ thkDebugOut((DEB_ARGS, "1632 BUFFER: %p -> %p, %u\n",
+ vp16, lp32, dwCount));
+
+ TO_STACK32(pti, lp32, LPVOID );
+ TO_STACK32(pti, dwCount, DWORD );
+
+ if (fThopOutput)
+ {
+ TO_STACK32(pti, pdwCountOut32, LPVOID );
+ }
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (fThopOutput)
+ {
+ // If the pointer in sixteen bit land is non-null then return the
+ // count of bytes written to the buffer.
+ DWORD UNALIGNED *lpdw16 = (DWORD UNALIGNED *)
+ ValidatePtr16(pti, vp16CountOut, sizeof(DWORD), *pti->pThop);
+
+ if (lpdw16 != NULL)
+ {
+ *lpdw16 = dwCountOut32;
+ WOWRELVDMPTR(vp16CountOut);
+ }
+
+#if !defined(_CHICAGO_)
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+ if ( SUCCEEDED(dwResult) )
+ {
+ if (dwCountOut32 > 0 && vp16 != 0)
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR( vp16, dwCountOut32 );
+
+ memcpy( lp16, lp32, dwCountOut32 );
+
+ WOWRELVDMPTR(vp16);
+ }
+ }
+#endif // _CHICAGO_
+ }
+
+#if DBG == 1
+ if (lp32 != NULL && dwCount == 0)
+ {
+ thkAssert(dwWatch == WATCH_VALUE);
+ }
+#endif
+
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+#if !defined(_CHICAGO_)
+ //
+ // Now free the buffer
+ //
+ if ( lp32 != NULL && dwCount > 0 )
+ {
+ CoTaskMemFree( lp32 );
+ }
+#endif
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SNB_1632, public
+//
+// Synopsis: Converts 16-bit SNB to 32-bit SNB pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_SNB_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID snb16;
+ VPSTR *lpvpstr;
+ VPSTR UNALIGNED *lpvpstrTemp;
+ VPSTR vpstr;
+ SNB snb32;
+ UINT cStr;
+ UINT cStrTemp;
+ LPOLESTR *lplpstr;
+ UINT cbStrings;
+ OLECHAR *pocStr;
+ LPSTR lpstr16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We don't have anything but unmodified SNBs
+ //
+ thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
+
+ GET_STACK16(pti, snb16, VPVOID);
+
+ snb32 = NULL;
+ if ( snb16 != 0 )
+ {
+ //
+ // Count the strings in the 16-bit snb
+ //
+ lpvpstr = (VPSTR FAR *)GetReadPtr16( pti, snb16, sizeof(VPSTR) );
+ if ( lpvpstr != 0 )
+ {
+ lpvpstrTemp = lpvpstr;
+ cStr = 0;
+ cbStrings = 0;
+ do
+ {
+ cStr++;
+ vpstr = *lpvpstrTemp++;
+
+ if ( vpstr == 0 )
+ {
+ break;
+ }
+
+ lpstr16 = GetStringPtr16(pti, vpstr, CCHMAXSTRING,
+ &cStrTemp);
+ if ( lpstr16 == 0 )
+ {
+ WOWRELVDMPTR(snb16);
+ lpvpstr = NULL;
+ break; // Leave with snb32 still NULL
+ }
+
+ WOWRELVDMPTR(vpstr);
+
+ cbStrings += cStrTemp;
+ }
+ while ( TRUE );
+ }
+
+ if ( lpvpstr != NULL )
+ {
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %d strings\n", cStr));
+
+ //
+ // Allocate space for the 32-bit snb
+ //
+ snb32 = (LPOLESTR FAR *)CoTaskMemAlloc( cStr*sizeof(LPOLESTR) +
+ cbStrings*sizeof(WCHAR));
+ if (snb32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pocStr = (OLECHAR *)((BYTE *)snb32+cStr*sizeof(LPOLESTR));
+
+ //
+ // Now convert the strings
+ //
+ lpvpstrTemp = lpvpstr;
+ lplpstr = snb32;
+ cStrTemp = cStr - 1;
+
+ while ( cStrTemp > 0 )
+ {
+ --cStrTemp;
+
+ vpstr = *lpvpstrTemp++;
+
+ thkAssert( vpstr != 0 &&
+ "Loop is processing end of snb\n" );
+
+ // Guaranteed to use pocStr as storage since cbStrings is
+ // large enough to contain all the strings
+ *lplpstr = Convert_VPSTR_to_LPOLESTR( pti, vpstr,
+ pocStr, cbStrings );
+
+ if (*lplpstr == NULL)
+ {
+ CoTaskMemFree(snb32);
+ snb32 = NULL;
+ break;
+ }
+
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %p '%s' -> "
+ "%p '%ws'\n",
+ vpstr, WOWFIXVDMPTR(vpstr, 0),
+ *lplpstr, *lplpstr));
+ WOWRELVDMPTR(vpstr);
+#endif
+
+ pocStr += lstrlenW(pocStr)+1;
+ lplpstr++;
+ }
+
+ // Terminate SNB
+ *lplpstr = NULL;
+
+ thkAssert(*lpvpstrTemp == 0);
+
+ WOWRELVDMPTR(snb16);
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %p -> %p\n", snb16, snb32));
+
+ TO_STACK32(pti, snb32, SNB );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ //
+ // Free SNB memory if necessary
+ //
+ if ( snb32 != 0 )
+ {
+ CoTaskMemFree(snb32);
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInterface1632, private
+//
+// Synopsis: Handles interface thunking for THOP_IFACE and
+// THOP_IFACEGEN
+//
+// Arguments: [pti] - Thunking state information
+// [iidx] - Interface index or IID
+// [thop] - Thop being executed
+// [punkOuter] - Controlling IUnknown or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Assumes caller has already adjusted pti->pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInterface1632(THUNKINFO *pti,
+ IIDIDX iidx,
+ THOP thop,
+ IUnknown *punkOuter)
+{
+ VPVOID vpv;
+ DWORD dwResult;
+ IUnknown *punkThis32In;
+ IUnknown *punkThis32Out;
+ VPVOID vpvThis16;
+ VPVOID vpvIn;
+ VPVOID UNALIGNED *pvpvOut;
+ VPVOID vpPreAlloc = NULL;
+ THUNK1632OBJ UNALIGNED *pto;
+
+ punkThis32In = NULL;
+
+ // Retrieve in or out interface pointer
+ GET_STACK16(pti, vpv, VPVOID);
+
+ // Out takes precedence over in for determining indirection depth
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0)
+ {
+ pvpvOut = (VPVOID UNALIGNED *)GetWritePtr16(pti, vpv, sizeof(VPVOID));
+ if (pvpvOut != NULL)
+ {
+ vpvIn = *pvpvOut;
+ WOWRELVDMPTR(vpv);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - bad "
+ "pointer %p\n", vpv));
+ }
+ }
+ else
+ {
+ vpvIn = vpv;
+ }
+
+ if ((thop & THOP_IN) != 0 && SUCCEEDED(pti->scResult))
+ {
+ if (vpvIn == 0)
+ {
+ punkThis32In = NULL;
+ }
+ else
+ {
+ if ( !IsValidInterface16(pti, vpvIn) )
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - invalid "
+ "interface %p\n", vpvIn));
+ }
+ else
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ punkThis32In = pti->pThkMgr->FindProxy3216(NULL, vpvIn, iidx,
+ NULL);
+
+ if (punkThis32In == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - "
+ "Can't create proxy for %p\n", vpvIn));
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 %s %p -> %p\n",
+ IidIdxString(iidx), vpvIn, punkThis32In));
+ }
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0 && SUCCEEDED(pti->scResult))
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // Preallocate a proxy for the out parameter
+ if ((vpPreAlloc = pti->pThkMgr->CanGetNewProxy1632(iidx))== NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - "
+ "Cannot preallocate %s proxy\n", IidIdxString(iidx)));
+ }
+
+ punkThis32Out = punkThis32In;
+ TO_STACK32(pti, &punkThis32Out, IUnknown **);
+
+ // Set the temporary proxy's this pointer to point to the place
+ // to fetch the real this pointer from
+ pto = FIXVDMPTR(vpPreAlloc, THUNK1632OBJ);
+ pto->punkThis32 = (IUnknown *)&punkThis32Out;
+ RELVDMPTR(vpPreAlloc);
+
+ // Set the out pointer to the temporary proxy so that there's
+ // an object available to all back through even before the
+ // current call has completed
+ // Certain apps (Corel Draw 5.0 is one) point out pointers to
+ // objects which are used inside of calls which fill out the
+ // out pointer and they require that the out pointer be filled
+ // in to operate correctly
+ // This will get NULLed out in failure cases
+ *FIXVDMPTR(vpv, VPVOID) = vpPreAlloc;
+ RELVDMPTR(vpv);
+ }
+ else
+ {
+ TO_STACK32(pti, punkThis32In, IUnknown *);
+ }
+
+ // Assume that our caller has already adjusted pThop
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( ((thop & THOP_OPMASK) == THOP_IFACENOADDREF)
+ && (punkThis32In != NULL)
+ && ((thop & THOP_IN) != 0)
+ && (vpv != 0)
+ && (SUCCEEDED((SCODE)dwResult))
+ && (punkOuter != NULL)
+ )
+ {
+ // NOTE: the 3216 bit pointer did not get addref'd by the users
+ // but should remain until the outer object goes away
+ // Steps:
+ // - Local addref the 3216 proxy
+ // - aggregate it with punkOuter
+
+ THUNK3216OBJ *pto = pti->pThkMgr->LookupProxy3216(vpvIn);
+
+ if (pto)
+ pto->cRefLocal++;
+ vpvThis16 =
+ pti->pThkMgr->FindAggregate1632(NULL, punkOuter,
+ punkThis32In, iidx);
+ }
+ else if (punkThis32In != NULL)
+ {
+ // The rules for [in,out] require that we NOT release here.
+ // Passing an Interface [in,out] has already given the reference away.
+ if( (thop & THOP_INOUT) != THOP_INOUT )
+ {
+ // Note that if the routine called keeps the proxy around
+ // it should AddRef it so this won't really remove the object
+ pti->pThkMgr->FreeProxy3216(vpvIn);
+ }
+ }
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0)
+ {
+ vpvThis16 = 0;
+
+ if (SUCCEEDED((SCODE)dwResult) && punkThis32Out != NULL)
+ {
+ // Get a 16-bit proxy object for the 32-bit object
+
+ if (punkOuter != NULL)
+ {
+ vpvThis16 =
+ pti->pThkMgr->FindAggregate1632(vpPreAlloc, punkOuter,
+ punkThis32Out, iidx);
+ }
+ else
+ {
+ vpvThis16 = pti->pThkMgr->FindProxy1632(vpPreAlloc,
+ punkThis32Out, iidx,
+ NULL);
+ }
+ }
+ else if (vpPreAlloc != NULL)
+ {
+ // Return our preallocated proxy because we don't need it
+ pti->pThkMgr->FreeNewProxy1632(vpPreAlloc, iidx);
+ }
+
+ // Set the out param
+ // Get the VDM pointer again since we may have done nested
+ // transitions since we last got it
+ pvpvOut = FIXVDMPTR(vpv, VPVOID);
+ *pvpvOut = vpvThis16;
+ RELVDMPTR(vpv);
+
+ thkDebugOut((DEB_ARGS, "Out1632 %s %p -> %p\n",
+ IidIdxString(iidx), punkThis32Out, vpvThis16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACEGEN_1632, public
+//
+// Synopsis: Thunks interfaces out through ppvs from 16->32
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACEGEN_1632(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvIid;
+ IUnknown *punkOuter;
+ IID UNALIGNED const *piid;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert(thopOp == THOP_IFACEGEN ||
+ thopOp == THOP_IFACEGENOWNER);
+
+ // The current thop byte indicates how many bytes to look
+ // back in the stack to find the IID which identifies the
+ // interface being returned
+ INDEX_STACK16(pti, vpvIid, VPVOID, *pti->pThop, sizeof(VPVOID));
+ pti->pThop++;
+
+ piid = (IID const *)GetReadPtr16(pti, vpvIid, sizeof(IID const));
+ if (piid == NULL)
+ {
+ pti->scResult = E_INVALIDARG;
+ }
+ else
+ {
+#if DBG == 1
+ if (!IsValidIid(*piid))
+ {
+ pti->scResult = E_INVALIDARG;
+ }
+ else
+#endif
+ {
+ iidx = IidToIidIdx(*piid);
+ }
+
+ WOWRELVDMPTR(vpvIid);
+ }
+
+ punkOuter = NULL;
+ if (thopOp == THOP_IFACEGENOWNER)
+ {
+ // For cases where the controlling unknown is known,
+ // index back on the stack and find the 32-bit unknown
+ // pointer to use
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
+ }
+
+ return ThunkInterface1632(pti, iidx, thop, punkOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OIFI_1632, public
+//
+// Synopsis: Convert OLEINPLACEFRAMEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_OIFI_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpoifi16;
+ OIFI16 UNALIGNED *poifi16;
+ OLEINPLACEFRAMEINFO oifi32;
+ OLEINPLACEFRAMEINFO *poifi32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ // OIFIs are out-only parameters for their contents
+ // However, cb is in/out, so we need to copy cb on the way in
+ // Furthermore, cb may not be set to a valid value, in which
+ // case the documentation mentions that it should be assumed
+ // that this is an OLE 2.0 OIFI
+ // This thop simply ignores cb on the way in and always sets
+ // it to the OLE 2.0 size
+ // Since we're out-only, this always works since the number of
+ // fields we thunk is the size of the structure that we give out
+ // If OLEINPLACEFRAMEINFO is extended, this thop will break
+
+ // Assert that OLEINPLACEFRAMEINFO is what we expect it to be
+ thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
+
+ GET_STACK16(pti, vpoifi16, VPVOID);
+
+ poifi32 = NULL;
+ if (vpoifi16 != 0)
+ {
+ poifi16 = (OIFI16 UNALIGNED *) GetWritePtr16(pti, vpoifi16, sizeof(OIFI16));
+ if (NULL != poifi16)
+ {
+ poifi32 = &oifi32;
+
+ // OIFI's may be an out only parameters but if the "cb" field is
+ // "in" RPC doesn't slice up structs, so the whole thing is "in"
+ // as well. We are Thoping here but if we want this to match
+ // the RPC sematics then we need to copy all the fields.
+
+ poifi32 = &oifi32;
+ poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
+ poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
+ poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
+ poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
+
+ if (poifi16->haccel == NULL)
+ {
+ poifi32->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi32->haccel = HACCEL_32(poifi16->haccel);
+ if (poifi32->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+ WOWRELVDMPTR(vpoifi16);
+ }
+ }
+
+ TO_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (poifi32 != NULL)
+ {
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ poifi16->cb = sizeof(OIFI16);
+ poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
+ poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
+ poifi16->cAccelEntries =
+ ClampULongToUShort(poifi32->cAccelEntries);
+
+ if (poifi32->haccel == NULL)
+ {
+ poifi16->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi16->haccel = HACCEL_16(poifi32->haccel);
+ if (poifi16->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+#if DBG == 1
+ if (SUCCEEDED(dwResult))
+ {
+ thkDebugOut((DEB_ARGS, "Out1632 OIFI: "
+ "%p {%d, %d, 0x%p, 0x%p, %d} -> "
+ "%p {%d, %d, 0x%04X, 0x%04X, %d}\n",
+ poifi32, poifi32->cb, poifi32->fMDIApp,
+ poifi32->hwndFrame, poifi32->haccel,
+ poifi32->cAccelEntries,
+ vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
+ (DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
+ poifi16->cAccelEntries));
+ }
+#endif
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(poifi16, 0, sizeof(OIFI16));
+ }
+
+ RELVDMPTR(vpoifi16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STGMEDIUM_1632, public
+//
+// Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
+// structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_STGMEDIUM_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpstgmedium16;
+ STGMEDIUM UNALIGNED *lpstgmedium16;
+ STGMEDIUM *lpstgmedium32;
+ STGMEDIUM stgmedium32;
+ DWORD dwSize;
+ SCODE sc;
+ BOOL fReleaseParam;
+ SHORT fTransferOwnership;
+ FORMATETC *pfe;
+ THOP thopFeOffset;
+ BOOL fReversedTYMED_NULL = FALSE;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We currently don't have any unmodified or inout thops for STGMEDIUMs
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "STGMEDIUM must be input or output only" );
+
+ // +2 thop byte indicates whether there's a FORMATETC to look at
+ // or not
+ // We need to reference this now before the stack is modified
+ // by argument recovery
+ thopFeOffset = *(pti->pThop+2);
+ if (thopFeOffset > 0)
+ {
+ INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
+ }
+ else
+ {
+ pfe = NULL;
+ }
+
+ GET_STACK16(pti, vpstgmedium16, VPVOID);
+
+ // Next thop byte indicates whether there's an ownership transfer
+ // argument or not
+ pti->pThop++;
+ fReleaseParam = (BOOL)*pti->pThop++;
+
+ if (fReleaseParam)
+ {
+ GET_STACK16(pti, fTransferOwnership, SHORT);
+ }
+ else
+ {
+ fTransferOwnership = FALSE;
+ }
+
+ // Skip FORMATETC offset thop
+ pti->pThop++;
+
+ lpstgmedium32 = NULL;
+
+ if ( vpstgmedium16 != 0 )
+ {
+ if ( fThopInput )
+ {
+ // This code supports GetDataHere() passing TYMED_NULL. It then
+ // behaves like GetData(). This is not per the OLE spec.
+ // According to every OLE spec TYMED_NULL is an invalid type in
+ // GetDataHere(). But AlexGo says that 16bit inproc servers
+ // did support this, especially the Default Handler / Clipboard.
+
+ lpstgmedium16 = (STGMEDIUM FAR *)GetReadPtr16(pti, vpstgmedium16,
+ sizeof(STGMEDIUM));
+
+ if (lpstgmedium16->tymed == TYMED_NULL &&
+ !fTransferOwnership)
+ {
+ WOWRELVDMPTR(vpstgmedium16);
+
+ memset(&stgmedium32, 0, sizeof(stgmedium32));
+ thkAssert( TYMED_NULL == 0 ); // Don't need to set tymed to 0
+
+ fThopInput = FALSE;
+ fThopOutput = TRUE;
+ fReversedTYMED_NULL = TRUE;
+ }
+ else
+ {
+ WOWRELVDMPTR(vpstgmedium16);
+
+ sc = ConvertStgMed1632(pti, vpstgmedium16, &stgmedium32,
+ pfe, fTransferOwnership, &dwSize);
+ if (SUCCEEDED(sc))
+ {
+ lpstgmedium32 = &stgmedium32;
+ }
+ }
+ }
+
+ if ( fThopOutput )
+ {
+ thkAssert( fThopOutput );
+
+ lpstgmedium16 = (STGMEDIUM FAR *)GetWritePtr16(pti, vpstgmedium16,
+ sizeof(STGMEDIUM));
+ if ( lpstgmedium16 != NULL )
+ {
+ lpstgmedium32 = &stgmedium32;
+ WOWRELVDMPTR(vpstgmedium16);
+ }
+
+ // BUGBUG - 32->16 sets tymed to TYMED_NULL before passing
+ // on the STGMEDIUM because some apps incorrectly check for this
+ // I'm assuming this isn't necessary for 16->32 because 32-bit
+ // apps can't rely on tymed being NULL since nothing in the 32-bit
+ // code sets it that way for out parameters
+ // DrewB 5/30
+ }
+ }
+
+ TO_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
+
+ if (fReleaseParam)
+ {
+ TO_STACK32(pti, (BOOL)fTransferOwnership, BOOL);
+ }
+
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpstgmedium32 != NULL)
+ {
+ if ( fThopInput )
+ {
+ if (!fTransferOwnership || FAILED(dwResult))
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ dwSize, TRUE, pfe);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ }
+ }
+ else if (SUCCEEDED(dwResult))
+ {
+ lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ if (lpstgmedium16->pUnkForRelease == NULL)
+ {
+ RELVDMPTR(vpstgmedium16);
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ 0, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ else
+ {
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
+ pfe, FALSE, &dwSize);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ ReleaseStgMedium(lpstgmedium32);
+ }
+ else if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ dwSize, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+
+ // Clear the [out] parameters if the call failed.
+ // Unless it had previously been an [in] parameter.
+ // We don't want to erase the caller's [in] argument.
+
+ if (FAILED(dwResult) && !fReversedTYMED_NULL)
+ {
+ lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ memset(lpstgmedium16, 0, sizeof(STGMEDIUM));
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStatStg3216, public
+//
+// Synopsis: Converts a STATSTG
+//
+// Arguments: [pti] - Thunk info
+// [pss32] - STATSTG
+// [vpss16] - STATSTG
+// [vpstrPreAlloc] - Preallocated string memory or NULL
+// [cchPreAlloc] - Amount preallocated
+//
+// Returns: Appropriate status code
+//
+// Modifies: [vpss16]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Assumes input STATSTG memory is valid
+// Assumes task memory for the string
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStatStg3216(THUNKINFO *pti,
+ STATSTG *pss32,
+ VPVOID vpss16,
+ VPSTR vpstrPreAlloc,
+ UINT cchPreAlloc)
+{
+ STATSTG UNALIGNED *pss16;
+ SCODE sc;
+ VPSTR vpstr16;
+
+ sc = ConvertTaskString3216(pti, pss32->pwcsName,
+ vpstrPreAlloc, cchPreAlloc,
+ &vpstr16);
+ if (SUCCEEDED(sc))
+ {
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ memcpy(pss16, pss32, sizeof(STATSTG));
+ pss16->pwcsName = (LPOLESTR)vpstr16;
+ RELVDMPTR(vpss16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STATSTG_1632, public
+//
+// Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_STATSTG_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpstatstg16;
+ STATSTG UNALIGNED *lpstatstg16;
+ VPSTR vpstr;
+ STATSTG statstg32;
+ STATSTG *lpstatstg32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
+
+ //
+ // We currently don't have any input thops for STATSTGs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
+ "STATSTG must be output only" );
+
+ GET_STACK16(pti, vpstatstg16, VPVOID);
+
+ lpstatstg32 = NULL;
+
+ lpstatstg16 = (STATSTG FAR *)GetWritePtr16( pti, vpstatstg16,
+ sizeof(STATSTG) );
+ if ( lpstatstg16 != NULL )
+ {
+ statstg32.pwcsName = NULL;
+ lpstatstg32 = &statstg32;
+
+ vpstr = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
+ if (vpstr == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ WOWRELVDMPTR(vpstatstg16);
+ }
+
+ TO_STACK32(pti, lpstatstg32, STATSTG FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpstatstg32 != NULL )
+ {
+ if ( SUCCEEDED(dwResult) )
+ {
+ SCODE sc;
+
+ sc = ConvertStatStg3216(pti, &statstg32, vpstatstg16,
+ vpstr, CWCSTRINGPREALLOC);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree16(vpstr);
+
+ lpstatstg16 = FIXVDMPTR(vpstatstg16, STATSTG);
+ memset(lpstatstg16, 0, sizeof(STATSTG));
+ RELVDMPTR(vpstatstg16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_DVTARGETDEVICE_1632, public
+//
+// Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_DVTARGETDEVICE_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ DVTARGETDEVICE *lpdv32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
+
+ //
+ // We currently don't have any output thops for DVTARGETDEVICEs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "DVTARGETDEVICE must be input only" );
+
+ //
+ // Processing for a DVTARGETDEVICE FAR * as input
+ //
+ GET_STACK16(pti, vpdv16, VPVOID);
+
+ lpdv32 = NULL;
+
+ if ( vpdv16 != 0 )
+ {
+ sc = ConvertDvtd1632(pti, vpdv16, ArStack32, FrStack32, &lpdv32,
+ &uiSize);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ }
+ }
+
+ TO_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (lpdv32 != NULL)
+ {
+ FrStack32(lpdv32, uiSize);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FORMATETC_1632, public
+//
+// Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FORMATETC_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpformatetc16;
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ LPFORMATETC lpformatetc32;
+ FORMATETC formatetc32;
+ DVTARGETDEVICE *lpdv32;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We have only input and output thops, not both, or neither
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "formatetc must be input or output only" );
+
+ lpdv32 = NULL;
+
+ GET_STACK16(pti, vpformatetc16, VPVOID);
+
+ if ( vpformatetc16 == 0 )
+ {
+ lpformatetc32 = NULL;
+ }
+ else
+ {
+ lpformatetc32 = &formatetc32;
+
+ if ( fThopInput )
+ {
+ sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, FALSE);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+ //
+ // The below memset is needed at least for the DATA_S_SAMEFORMATETC
+ // case. This allows it to be cleaned up because all its pointers
+ // will be null.
+ //
+ memset( &formatetc32, 0, sizeof(formatetc32) );
+ lpformatetc16 = (LPFORMATETC16)GetWritePtr16(pti, vpformatetc16,
+ sizeof(FORMATETC16));
+ WOWRELVDMPTR(vpformatetc16);
+ }
+ }
+
+ TO_STACK32(pti, lpformatetc32, LPFORMATETC);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( fThopInput )
+ {
+ if (lpformatetc32 != NULL && lpformatetc32->ptd != NULL)
+ {
+ TaskFree32(lpformatetc32->ptd);
+ }
+ }
+
+ if ( fThopOutput && vpformatetc16 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, TRUE);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ memset(lpformatetc16, 0, sizeof(FORMATETC16));
+ RELVDMPTR(vpformatetc16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LOGPALETTE_1632, public
+//
+// Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
+// and converts 32-bit LOGPALETTE returned to 16-bit structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LOGPALETTE_1632 ( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ LPLOGPALETTE lplogpal32;
+ VPVOID vplogpal16;
+ LOGPALETTE UNALIGNED *lplogpal16;
+ VPVOID vp16;
+ LPVOID UNALIGNED *lp16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
+
+ //
+ // It must be either an input or output LOGPALETTE
+ //
+ thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
+ "Hey, LOGPALETTE can't be input and output!" );
+
+ lplogpal32 = NULL;
+
+ if ( (*pti->pThop & THOP_IN) != 0 )
+ {
+ //
+ // Processing for a LPLOGPALETTE as input
+ //
+ GET_STACK16(pti, vplogpal16, VPVOID);
+
+ if ( vplogpal16 != 0 )
+ {
+ // Copy over the input LOGPALETTE structure
+ lplogpal16 = (LPLOGPALETTE)GetReadPtr16( pti, vplogpal16,
+ sizeof(LOGPALETTE) );
+
+ if ( lplogpal16 != NULL )
+ {
+ uiSize = CBPALETTE(lplogpal16->palNumEntries);
+
+ WOWRELVDMPTR(vplogpal16);
+
+ lplogpal16 = (LPLOGPALETTE)GetReadPtr16(pti, vplogpal16,
+ uiSize);
+ if ( lplogpal16 != NULL )
+ {
+ lplogpal32 = (LPLOGPALETTE)CoTaskMemAlloc(uiSize);
+ if ( lplogpal32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ memcpy( lplogpal32, lplogpal16, uiSize );
+ }
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+ }
+ }
+
+ TO_STACK32(pti, lplogpal32, LPLOGPALETTE);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lplogpal32 )
+ {
+ CoTaskMemFree( lplogpal32 );
+ }
+ }
+ else
+ {
+ //
+ // Processing for LPLPLOGPALETTE as output
+ //
+
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ GET_STACK16(pti, vp16, VPVOID);
+
+ vplogpal16 = (VPVOID)TaskMalloc16(CBPALETTE(NPALETTEPREALLOC));
+ if (vplogpal16 == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ TO_STACK32(pti, &lplogpal32, LPLOGPALETTE *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( SUCCEEDED(dwResult) && lplogpal32 != NULL )
+ {
+ //
+ // Copy the returned LOGPALETTE into 16-bit memory
+ //
+ uiSize = CBPALETTE(lplogpal32->palNumEntries);
+ if (uiSize > CBPALETTE(NPALETTEPREALLOC))
+ {
+ TaskFree16(vplogpal16);
+ vplogpal16 = (VPVOID)TaskMalloc16(uiSize);
+ if ( vplogpal16 == 0 )
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ if (vplogpal16 != 0)
+ {
+ lplogpal16 = (LPLOGPALETTE)WOWFIXVDMPTR(vplogpal16, uiSize);
+ if ( lplogpal16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ vplogpal16 = 0;
+ }
+ else
+ {
+ memcpy( lplogpal16, lplogpal32, uiSize );
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+ }
+
+ TaskFree32( lplogpal32 );
+ }
+ else
+ {
+ TaskFree16(vplogpal16);
+ vplogpal16 = 0;
+ }
+
+ //
+ // Update the value pointed to by the parameter on the 16-bit stack
+ //
+ lp16 = FIXVDMPTR(vp16, LPVOID);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ *lp16 = (LPVOID)vplogpal16;
+ RELVDMPTR(vp16);
+ }
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CRGIID_1632, public
+//
+// Synopsis: Converts 16-bit CRGIID to 32-bit CRGIID structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_CRGIID_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ DWORD dwCount;
+ VPVOID vpiid16;
+ IID UNALIGNED *lpiid16;
+ IID *lpiid32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
+
+ //
+ // We currently don't have any output thops for CRGIIDs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "CRGIID must be unmodified only" );
+
+ GET_STACK16(pti, dwCount, DWORD);
+ GET_STACK16(pti, vpiid16, VPVOID);
+
+ lpiid32 = NULL;
+
+ if ( vpiid16 != 0 )
+ {
+ lpiid16 = (IID UNALIGNED *)GetReadPtr16( pti, vpiid16,
+ dwCount*sizeof(IID) );
+ if ( lpiid16 != NULL )
+ {
+ lpiid32 = (IID FAR *)CoTaskMemAlloc( dwCount * sizeof(IID) );
+ if ( lpiid32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ memcpy( lpiid32, lpiid16, dwCount*sizeof(IID) );
+ }
+
+ WOWRELVDMPTR(vpiid16);
+ }
+ }
+
+ TO_STACK32(pti, dwCount, DWORD);
+ TO_STACK32(pti, lpiid32, IID FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpiid32 != NULL )
+ {
+ CoTaskMemFree( lpiid32 );
+ }
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_INTERFACEINFO_1632, public
+//
+// Synopsis: Converts an INTERFACEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 19-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_INTERFACEINFO_1632(THUNKINFO *pti)
+{
+ INTERFACEINFO *pii32;
+ INTERFACEINFO ii32;
+ INTERFACEINFO16 UNALIGNED *pii16;
+ VPVOID vpii16;
+ DWORD dwResult;
+ IUnknown *punk32;
+ VPVOID vpvUnk16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
+ thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
+
+ pii32 = NULL;
+ punk32 = NULL;
+
+ GET_STACK16(pti, vpii16, VPVOID);
+ if (vpii16 != 0)
+ {
+ pii16 = (INTERFACEINFO16 UNALIGNED *)
+ GetReadPtr16(pti, vpii16, sizeof(INTERFACEINFO16));
+ if (pii16 != NULL)
+ {
+ if (pii16->pUnk != NULL)
+ {
+ vpvUnk16 = pii16->pUnk;
+
+ WOWRELVDMPTR(vpii16);
+
+ punk32 =
+ pti->pThkMgr->FindProxy3216(NULL, vpvUnk16,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (punk32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ }
+
+ pii32 = &ii32;
+ pii32->pUnk = punk32;
+ pii32->iid = pii16->iid;
+ pii32->wMethod = pii16->wMethod;
+
+ WOWRELVDMPTR(vpii16);
+
+ thkDebugOut((DEB_ARGS,
+ "In1632 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
+ vpii16, pii32, pii32->pUnk, pii16->pUnk,
+ IidOrInterfaceString(&pii32->iid), pii32->wMethod));
+ }
+ }
+
+ TO_STACK32(pti, pii32, INTERFACEINFO *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (punk32 != NULL)
+ {
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ vpvUnk16 = pii16->pUnk;
+ RELVDMPTR(vpii16);
+ pti->pThkMgr->FreeProxy3216(vpvUnk16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RETURNTYPE_1632, public
+//
+// Synopsis: Thunks the return value of a call
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+// Notes: This thunk assumes that the return value will always fit
+// in 32 bits and that the thops for it are only one thop
+// long. This fits the existing APIs and methods
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_RETURNTYPE_1632(THUNKINFO *pti)
+{
+ THOP thops[2];
+ DWORD dwResult;
+ ALIAS alias;
+ VPVOID vpPreAlloc = NULL;
+ IIDIDX iidx;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RETURNTYPE);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->fResultThunked = TRUE;
+
+ pti->pThop++;
+
+ // Remember return type thop
+ thops[0] = *pti->pThop++;
+ if ((thops[0] & THOP_OPMASK) == THOP_COPY ||
+ (thops[0] & THOP_OPMASK) == THOP_IFACE ||
+ (thops[0] & THOP_OPMASK) == THOP_ALIAS32)
+ {
+ thops[1] = *pti->pThop++;
+ }
+
+ // Preallocate any necessary resources
+ switch(thops[0])
+ {
+ case THOP_IFACE | THOP_IN:
+ iidx = INDEX_IIDIDX(thops[1]);
+ if ((vpPreAlloc =
+ pti->pThkMgr->CanGetNewProxy1632(iidx)) == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ break;
+
+ case THOP_ALIAS32:
+ thkAssert(thops[1] == ALIAS_CREATE);
+
+ // The value used for preallocation doesn't really matter
+ // as long as it's unique and not INVALID_VALUE
+ // In our case we know that we won't have to deal with nested
+ // preallocations so uniqueness is not as much of an issue
+ // By using INVALID_HANDLE_VALUE, we can be sure that there
+ // won't already be an entry with that value already in the
+ // alias table since we're aliasing handles
+ alias = gAliases32.AddValue((DWORD)INVALID_HANDLE_VALUE);
+ if (alias == INVALID_ALIAS)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ break;
+ }
+
+ dwResult = EXECUTE_THOP1632(pti);
+
+ // Now that we have the return value thunk it from 32->16
+ // We must use pti->scResult to check for failure rather than
+ // dwResult because dwResult may not be an SCODE
+
+ switch(thops[0])
+ {
+ case THOP_COPY:
+ // Only handle DWORD copies
+ thkAssert(thops[1] == sizeof(DWORD));
+ break;
+
+ case THOP_SHORTLONG:
+ // For boolean results, not necessary to clamp
+ dwResult = (DWORD)(SHORT)*(LONG *)&dwResult;
+ break;
+
+ case THOP_IFACE | THOP_IN:
+ if (dwResult != 0)
+ {
+ if (FAILED(pti->scResult))
+ {
+ dwResult = 0;
+ }
+ else
+ {
+ dwResult =
+ (DWORD)pti->pThkMgr->FindProxy1632(vpPreAlloc,
+ (IUnknown *)dwResult,
+ iidx, NULL);
+ thkAssert(dwResult != 0);
+
+ thkDebugOut((DEB_ARGS, "Ret1632 %s %p\n",
+ inInterfaceNames[thops[1]].pszInterface,
+ dwResult));
+ }
+ }
+ else
+ {
+ pti->pThkMgr->FreeNewProxy1632(vpPreAlloc, iidx);
+ }
+ break;
+
+ case THOP_ALIAS32:
+ if (dwResult != 0)
+ {
+ if (FAILED(pti->scResult))
+ {
+ dwResult = 0;
+ }
+ else
+ {
+ gAliases32.SetValue(alias, dwResult);
+
+ thkDebugOut((DEB_ARGS, "Ret1632 ALIAS32: 0x%08lX -> 0x%04lX\n",
+ dwResult, alias));
+
+ dwResult = (DWORD)alias;
+ }
+ }
+ break;
+
+ default:
+ thkAssert(!"Unhandled 1632 return type");
+ break;
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACE_1632, public
+//
+// Synopsis: Thunks a known interface pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACE_1632(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ IUnknown *punkOuter;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert( thopOp == THOP_IFACE
+ || thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACENOADDREF);
+
+ iidx = INDEX_IIDIDX(*pti->pThop++);
+
+ // There's a bit of a special case here in that IMalloc is
+ // not thunked so it doesn't have a real index but it's used
+ // in thop strings so it has a fake index to function as a placeholder
+ // The fake index is THI_COUNT so allow that in the assert
+ thkAssert(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) <= THI_COUNT);
+
+ punkOuter = NULL;
+ if ( thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACENOADDREF)
+ {
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
+ }
+
+ return ThunkInterface1632(pti, iidx, thop, punkOuter);
+}
+
+typedef struct tagOLESTREAMOBJECT
+{
+ OLESTREAM os;
+ VPVOID vpolestream16;
+} OLESTREAMOBJECT, FAR * LPOLESTREAMOBJECT;
+
+#define OLESTREAM_GET 0
+#define OLESTREAM_PUT 1
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Callback, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM methods
+//
+// Arguments: [dwMethod] - Index of method to invoke
+// [lposo] - Pointer to 32 LPOLESTREAM
+// [lpv] - Pointer to 32 bit buffer
+// [dwCount] - Size of 32 bit buffer
+//
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Converted to call WOWCallBackEx directly.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Callback( DWORD dwMethod,
+ LPOLESTREAM lpos,
+ LPVOID lpv,
+ DWORD dwCount )
+{
+ const DWORD cbStack = sizeof( DWORD ) +
+ sizeof( VPVOID ) + sizeof( VPVOID );
+
+ BYTE b32Args[cbStack];
+ DWORD dwResult;
+
+ VPVOID vpvVtbl16;
+ VTBLFN vpfn16;
+
+ VPVOID vpolestream16;
+ LPOLESTREAMOBJECT lposo;
+
+ VPVOID vp16;
+ LPVOID lp16;
+
+
+ lposo = (LPOLESTREAMOBJECT)lpos;
+ vpolestream16 = lposo->vpolestream16;
+
+ // Get pointer to 16 bit this pointer
+
+ vpvVtbl16 = (VPVOID)*FIXVDMPTR( vpolestream16, VPVOID );
+ RELVDMPTR(vpolestream16);
+ vpfn16 = (VTBLFN)*FIXVDMPTR( vpvVtbl16+dwMethod*sizeof(VPVOID),
+ VPVOID );
+ RELVDMPTR(vpvVtbl16+dwMethod*sizeof(VPVOID));
+
+ //
+ // now thop the IN 32 bit-block of memory to 16 bit block
+ //
+
+ vp16 = WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
+ if ( vp16 == NULL )
+ {
+ return (DWORD) E_OUTOFMEMORY;
+ }
+
+ if ( dwMethod == OLESTREAM_PUT )
+ {
+ lp16 = WOWFIXVDMPTR( vp16, dwCount );
+ memcpy( lp16, lpv, dwCount );
+ WOWRELVDMPTR(vp16);
+ }
+
+ // setup 32 bit arguements.
+ *(DWORD *)(b32Args) = dwCount;
+ *(VPVOID *)(b32Args+4) = vp16;
+ *(VPVOID *)(b32Args+8) = vpolestream16;
+
+ if ( !CallbackTo16Ex( (DWORD)vpfn16, WCB16_PASCAL, cbStack, b32Args,
+ &dwResult) )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+
+ if ( dwMethod == OLESTREAM_GET )
+ {
+
+ lp16 = WOWFIXVDMPTR( vp16, dwCount );
+ memcpy( (LPVOID) lpv, lp16, dwCount );
+ WOWRELVDMPTR(vp16);
+
+ }
+
+ WgtUnlockFree(vp16);
+
+ thkDebugOut((DEB_INVOKES, "OLESTREAM_Callback returns 0x%08lX\n",
+ dwResult));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Get_Proxy, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Get
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Now calls OLESTREAM::Get using Pascal
+// calling conventions.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Get_Proxy(
+ LPOLESTREAM lpos,
+ void FAR * lpv,
+ DWORD dwCount
+)
+{
+ return OLESTREAM_Callback( OLESTREAM_GET, lpos, lpv, dwCount );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Put_Proxy, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Put
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Now call OLESTREAM::Put using pascal
+// calling conventions.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Put_Proxy(
+ LPOLESTREAM lpos,
+ const void FAR* lpv,
+ DWORD dwCount
+)
+{
+ return OLESTREAM_Callback( OLESTREAM_PUT, lpos,(LPVOID) lpv, dwCount );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OLESTREAM_1632, public
+//
+// Synopsis: Thunks an OLESTREAM parameter from 16-bit to 32-bit
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 14-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+_OLESTREAMVTBL osVtbl =
+{
+ OLESTREAM_Get_Proxy,
+ OLESTREAM_Put_Proxy
+};
+
+DWORD Thop_OLESTREAM_1632(THUNKINFO *pti)
+{
+ OLESTREAMOBJECT osObject;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OLESTREAM);
+
+ //
+ // Ignore the THOP_INPUT/THOP_OUTPUT, it is always just an interface
+ //
+
+ osObject.os.lpstbl = &osVtbl;
+ GET_STACK16(pti, osObject.vpolestream16, VPVOID);
+
+ TO_STACK32(pti, &osObject, LPOLESTREAMOBJECT );
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RPCOLEMESSAGE_1632, public
+//
+// Synopsis: Converts 16-bit RPCOLEMESSAGE to 32-bit RPCOLEMESSAGE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+// 28-May-94 JohannP Rewritten
+// 13-Aug-94 Rickhi made it work for GetBuffer when the
+// buffer size grows, commented better
+//
+// CODEWORK: this routine is inefficient. since it cant tell why it was
+// called (GetBuffer/SendReceive/Invoke/FreeBuffer) it always
+// copies the data, when it only really needs to in Invoke and
+// in SendReceive.
+//
+// Context: This routine will "Thop" a client side RPCOLEMESSGE (aka "rom")
+// three times. The first time for the "getbuffer" call, the second
+// time for the "SendRecieve", and the third time for the "freebuffer".
+// This make it confusing, some calls allocate a buffer but don't
+// free it. Other calls free a buffer they didn't allocate. A good
+// way to see what is happening is to step through several calls to
+// this routine with a debugger and note the pointer values.
+//
+//----------------------------------------------------------------------------
+DWORD Thop_RPCOLEMESSAGE_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ PRPCOLEMESSAGE prom32;
+ VPVOID vprom16;
+ RPCOLEMESSAGE UNALIGNED *prom16;
+ LPVOID lp16;
+ RPCOLEMESSAGE rom32;
+ BOOL fAllocNew = FALSE;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
+
+ //
+ // We currently have only INOUT RPCOLEMESSAGE
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
+ "RPCOLEMESSAGE must be input/output only" );
+
+ //
+ // Processing for a RPCOLEMESSAGE FAR * as input/output
+ //
+ GET_STACK16(pti, vprom16, VPVOID);
+
+ prom32 = NULL;
+ if ( vprom16 != 0 )
+ {
+ // Copy over the input RPCOLEMESSAGE structure
+ prom16 = (RPCOLEMESSAGE UNALIGNED *)
+ GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
+ if ( prom16 != NULL )
+ {
+ // Note: ROM_THUNK_FIELD(prom) holds the pointer to the 32 bit rom
+ // in case the buffer is not NULL
+
+ // Note: this assert is not valid when a fault happens on the
+ // server side. In that case, the return buffer is NULLed
+ // by the 16bit stub but the THUNK_FIELD is non-null.
+
+ //thkAssert((prom16->Buffer == NULL &&
+ // ROM_THUNK_FIELD(prom16) == NULL) ||
+ // (prom16->Buffer != NULL &&
+ // ROM_THUNK_FIELD(prom16) != NULL));
+
+ if (prom16->Buffer != NULL)
+ {
+ prom32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
+
+ if ( prom32->Buffer != NULL )
+ {
+ // we use the min size of the two buffers because when
+ // the stub (server side) calls GetBuffer he is supplying
+ // the old pBuffer with the new (and potentially larger)
+ // cbBuffer
+
+ DWORD cbSizeMin = (prom16->cbBuffer <= prom32->cbBuffer) ?
+ prom16->cbBuffer : prom32->cbBuffer;
+
+ lp16 = (LPVOID)GetReadPtr16(pti,
+ (VPVOID)prom16->Buffer,
+ cbSizeMin);
+ if (lp16 == NULL)
+ {
+ prom32 = NULL;
+ }
+ else
+ {
+ memcpy( prom32->Buffer, lp16, prom32->cbBuffer );
+ WOWRELVDMPTR((VPVOID)prom16->Buffer);
+ }
+ }
+
+ // the stub might be asking for a larger buffer for output
+ // parameters than it was given for input parameters. We have
+ // to figure that out here by comparing the 16bit size with
+ // the 32bit size.
+
+ fAllocNew = (prom32->cbBuffer < prom16->cbBuffer);
+ prom32->cbBuffer = prom16->cbBuffer;
+ }
+ else
+ {
+ rom32 = *prom16;
+ prom32 = &rom32;
+ }
+
+ WOWRELVDMPTR(vprom16);
+ }
+ }
+
+ TO_STACK32(pti, prom32, PRPCOLEMESSAGE);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( prom32 != NULL )
+ {
+ prom16 = (RPCOLEMESSAGE UNALIGNED *)
+ GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
+ if ( prom16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ if (prom32->Buffer == NULL)
+ {
+ // RELEASE THE BUFFER AND ROM:
+ // Free the 16 bit buffer, copy the 32 bit rom into
+ // the 16 bit rom and free the 32bit rom, if it was
+ // allocated
+ //
+ if (prom16->Buffer != 0)
+ {
+ TaskFree16((VPVOID)prom16->Buffer);
+ }
+
+ *prom16 = *prom32;
+
+ if (prom32 != &rom32)
+ {
+ TaskFree32(prom32);
+ prom32 = NULL;
+ }
+ ROM_THUNK_FIELD(prom16) = NULL;
+ }
+ else
+ {
+ // ALLOCATE AND/OR COPYBACK THE BUFFER AND ROM:
+ RPCOLEMESSAGE *pr32;
+ LPVOID pBuffer;
+
+ // Create a message to save the 32-bit message in
+ // Use the existing one in the thunk field if we can
+ if (ROM_THUNK_FIELD(prom16) == NULL)
+ {
+ pr32 = (RPCOLEMESSAGE *)
+ TaskMalloc32(sizeof(RPCOLEMESSAGE));
+ }
+ else
+ {
+ pr32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
+ }
+ *pr32 = *prom32;
+
+ //
+ // Allocate an output buffer and copy the buffer back
+ //
+ if ( (prom16->Buffer == NULL)
+ || (prom16->cbBuffer < prom32->cbBuffer)
+ || fAllocNew)
+ {
+ if (prom16->Buffer != NULL)
+ {
+ TaskFree16((VPVOID) prom16->Buffer);
+ }
+
+ pBuffer = (LPVOID)TaskMalloc16(prom32->cbBuffer );
+ }
+ else
+ {
+ pBuffer = prom16->Buffer;
+ }
+
+ *prom16 = *prom32;
+ prom16->Buffer = pBuffer;
+ ROM_THUNK_FIELD(prom16) = pr32;
+
+ if (prom16->Buffer == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ lp16 = (LPVOID)GetReadPtr16(pti,
+ (VPVOID)prom16->Buffer,
+ prom16->cbBuffer);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( lp16, prom32->Buffer,
+ prom32->cbBuffer );
+ WOWRELVDMPTR((VPVOID)prom16->Buffer);
+ }
+ }
+ }
+ }
+
+ WOWRELVDMPTR(vprom16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ALIAS32_1632, public
+//
+// Synopsis: Handles 16-bit aliases to 32-bit quantities
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ALIAS32_1632(THUNKINFO *pti)
+{
+ ALIAS alias;
+ DWORD dwValue;
+ THOP thopAction;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->pThop++;
+
+ GET_STACK16(pti, alias, ALIAS);
+
+ // Second byte indicates how the alias should be handled
+ thopAction = *pti->pThop++;
+
+ if (alias != 0)
+ {
+ switch(thopAction)
+ {
+ case ALIAS_RESOLVE:
+ dwValue = gAliases32.AliasValue(alias);
+ break;
+
+ case ALIAS_REMOVE:
+ dwValue = gAliases32.AliasValue(alias);
+ gAliases32.RemoveAlias(alias);
+ break;
+
+ default:
+ thkAssert(!"Default hit in Thop_ALIAS32_1632");
+ break;
+ }
+ }
+ else
+ {
+ dwValue = 0;
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 ALIAS32: 0x%04X -> 0x%08lX\n",
+ alias, dwValue));
+
+ TO_STACK32(pti, dwValue, DWORD);
+
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ENUM_1632, public
+//
+// Synopsis: Thunks Enum::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is the start of a 2-byte thop. The next thop
+// byte references a function in the enumerator table, rather
+// than the standard thop table.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ENUM_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ //
+ // Get then next thop byte and execute it as a Enum thop
+ //
+ pti->pThop++;
+ return EXECUTE_ENUMTHOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallbackProcessing_1632, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+typedef struct tagCallbackControl
+{
+ DWORD dwContinue;
+ VPVOID vpfn16;
+} CALLBACKCONTROL;
+
+BOOL CallbackProcessing_1632( DWORD dwContinue )
+{
+ DWORD dwResult;
+ CALLBACKCONTROL *lpcbc;
+
+ lpcbc = (CALLBACKCONTROL *)dwContinue;
+
+ // The callback function must be FAR PASCAL
+ // It's declared CALLBACK in the methods so this is ensured
+ dwResult = CallbackTo16( lpcbc->vpfn16, lpcbc->dwContinue );
+
+ return (BOOL)((WORD)dwResult); // Ignore HIWORD
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CALLBACK_1632, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CALLBACK_1632(THUNKINFO *pti)
+{
+ VPVOID vpfn16;
+ DWORD dwContinue;
+ CALLBACKCONTROL cbc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK16(pti, vpfn16, VPVOID);
+ GET_STACK16(pti, dwContinue, DWORD);
+
+ if ( vpfn16 == 0 )
+ {
+ TO_STACK32(pti, NULL, LPVOID);
+ TO_STACK32(pti, dwContinue, DWORD);
+ }
+ else
+ {
+ cbc.vpfn16 = vpfn16;
+ cbc.dwContinue = dwContinue;
+
+ TO_STACK32(pti, CallbackProcessing_1632, LPVOID);
+ TO_STACK32(pti, (DWORD)&cbc, DWORD);
+ }
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CLSCONTEXT_1632, public
+//
+// Synopsis: Converts a class context flags DWORD
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CLSCONTEXT_1632(THUNKINFO *pti)
+{
+ DWORD dwClsContext;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK16(pti, dwClsContext, DWORD);
+
+ // When passing a 16-bit class context on to 32-bits,
+ // add on a flag to indicate that this is a 16-bit request
+ // in the inproc server case
+
+ if (dwClsContext & CLSCTX_INPROC_SERVER)
+ {
+ dwClsContext |= CLSCTX_INPROC_SERVER16;
+ }
+
+ TO_STACK32(pti, dwClsContext, DWORD);
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FILENAME_1632, public
+//
+// Synopsis: Converts a filename string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FILENAME_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
+
+ // Can be in or out only
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ if ((*pti->pThop & THOP_IN) != 0)
+ {
+ // No special processing is necessary for filenames going
+ // from 16->32 since it isn't possible for 16-bit code to
+ // generate a filename which can't be handled in 32-bits
+
+ return ThunkInString1632(pti);
+ }
+ else
+ {
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ // Convert filenames going from 32->16 to short filenames
+ // to avoid any possible problems with non-8.3 names.
+
+ return ThunkOutString1632(pti, TRUE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SIZEDSTRING_1632, public
+//
+// Synopsis: Converts strings which cannot exceed a given length
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 02-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_SIZEDSTRING_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
+
+ // For 16->32, there are no limits on string length so
+ // thunk the string normally
+
+ // Advance once to account for the length byte
+ // ThunkInString will advance again
+
+ pti->pThop++;
+ return ThunkInString1632(pti);
+}
+
+#define THOP_FN(x) Thop_ ## x ## _1632
+
+DWORD (*CONST aThopFunctions1632[])(THUNKINFO *) =
+{
+
+ // x = Implemented
+ // ? = Mysteriously not needed
+ // = Left to do
+ //
+ // ^
+ // |
+ // +===+
+ // |
+ // v
+ //
+ ThunkCall1632, // x Terminating THOP
+ Thop_ShortToLong_1632, // x SHORTLONG
+ Thop_WordToDword_1632, // x WORDDWORD
+ Thop_Copy_1632, // x COPY
+ THOP_FN(LPSTR), // x LPSTR
+ THOP_FN(LPLPSTR), // x LPLPSTR
+ THOP_FN(BUFFER), // x BUFFER
+ Thop_UserHandle_1632, // x HUSER
+ Thop_GdiHandle_1632, // x HGDI
+ THOP_FN(SIZE), // x SIZE
+ THOP_FN(RECT), // x RECT
+ THOP_FN(MSG), // x MSG
+ THOP_FN(HRESULT), // x HRESULT
+ THOP_FN(STATSTG), // x STATSTG
+ THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
+ THOP_FN(STGMEDIUM), // x STGMEDIUM
+ THOP_FN(FORMATETC), // x FORMATETC
+ THOP_FN(HACCEL), // x HACCEL
+ THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
+ THOP_FN(BINDOPTS), // x BIND_OPTS
+ THOP_FN(LOGPALETTE), // x LOGPALETTE
+ THOP_FN(SNB), // x SNB
+ THOP_FN(CRGIID), // x CRGIID
+ THOP_FN(OLESTREAM), // x OLESTREAM
+ THOP_FN(HTASK), // x HTASK
+ THOP_FN(INTERFACEINFO), // x INTERFACEINFO
+ THOP_FN(IFACE), // x IFACE
+ THOP_FN(IFACE), // x IFACEOWNER
+ THOP_FN(IFACE), // x IFACENOADDREF
+ Thop_ERROR_1632, // x IFACECLEAN
+ THOP_FN(IFACEGEN), // x IFACEGEN
+ THOP_FN(IFACEGEN), // x IFACEGENOWNER
+ Thop_ERROR_1632, // x ROUTINE_INDEX
+ THOP_FN(RETURNTYPE), // x RETURN_TYPE
+ THOP_FN(NULL), // x NULL
+ Thop_ERROR_1632, // x ERROR
+ THOP_FN(ENUM), // x ENUM
+ THOP_FN(CALLBACK), // x CALLBACK
+ THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
+ THOP_FN(ALIAS32), // x ALIAS32
+ THOP_FN(CLSCONTEXT), // x CLSCONTEXT
+ THOP_FN(FILENAME), // x FILENAME
+ THOP_FN(SIZEDSTRING), // x SIZEDSTRING
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: General_Enum_1632, private
+//
+// Synopsis: Thunking for standard OLE enumerator interface ::Next member
+// function.
+//
+// Arguments: [pti] - Thunk state information
+// [uiSize32] - 32-bit information size
+// [uiSize16] - 16-bit information size
+// [pfnCallback] - Data thunking callback
+// [pfnCleanup] - Thunking cleanup
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This handler is called from many IXXXEnum::Next handlers thop
+// thunks to do the standard sorts of "buffer of structures"
+// processing.
+//
+//----------------------------------------------------------------------------
+#define MAX_ALLOCA_STRUCT 10
+
+DWORD General_Enum_1632(
+ THUNKINFO *pti,
+ UINT uiSize32,
+ UINT uiSize16,
+ SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
+ void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
+{
+ DWORD dwResult;
+ ULONG ulCount;
+ VPVOID vpstruct16;
+ VPVOID vpfetched16;
+ LPVOID lpstruct32;
+ LPVOID lpstruct32Iterate;
+ VPVOID vpstruct16Iterate;
+ ULONG ulFetched32;
+ ULONG *lpfetched32;
+ ULONG UNALIGNED *lpfetched16;
+ ULONG ulIterate;
+ LPVOID lp16;
+ BOOL fError;
+ SCODE sc;
+
+ dwResult = (DWORD)S_OK;
+
+ GET_STACK16(pti, ulCount, ULONG );
+ GET_STACK16(pti, vpstruct16, VPVOID );
+ GET_STACK16(pti, vpfetched16, VPVOID );
+
+ //
+ // THIS ROUTINE CAN DEAL WITH dwResult RATHER THAN pti->scResult BECAUSE
+ // WE KNOW THIS IS THE ONLY THOP FOR THIS FUNCTION! NO OTHER CLEANUP
+ // WILL HAVE TO BE DONE!
+ //
+ ulFetched32 = 0;
+ lpfetched32 = &ulFetched32;
+ lp16 = NULL;
+ lpstruct32 = NULL;
+
+ if ( vpstruct16 != 0 )
+ {
+ if ( ulCount == 0 )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ //
+ // Verify we have write access to the 16-bit memory.
+ //
+ lp16 = GetWritePtr16(pti, vpstruct16, uiSize16*ulCount);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ lpstruct32 = (LPVOID)CoTaskMemAlloc( ulCount * uiSize32 );
+ if (lpstruct32 == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ lpstruct32 = (LPVOID)STACKALLOC32( ulCount * uiSize32 );
+ if (lpstruct32 == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ WOWRELVDMPTR(vpstruct16);
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ TO_STACK32(pti, ulCount, ULONG);
+ TO_STACK32(pti, lpstruct32, LPVOID);
+ TO_STACK32(pti, lpfetched32, ULONG FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+ }
+
+ if ( SUCCEEDED(dwResult) )
+ {
+ if ( vpstruct16 != 0 )
+ {
+ // Some apps (MsWorks3 is one) return S_FALSE and do not return
+ // the number of elements retrieved. The only thing we can
+ // do is ignore the enumeration since we don't know how many
+ // were actually set. Of course, we can't ignore all enumerations
+ // when the return is S_FALSE so we only handle the case
+ // where S_FALSE was returned on a enumeration of one element,
+ // in which we can be sure there isn't any valid data
+ if (dwResult == (DWORD)S_FALSE && ulCount == 1)
+ {
+ ulFetched32 = 0;
+ }
+
+ //
+ // Iterate through all of the structures, converting them
+ // into 16-bit
+ //
+ fError = FALSE;
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate < ulFetched32 )
+ {
+ //
+ // Callback to the callback function to do any specific
+ // processing
+ //
+ sc = (*pfnCallback)( pti, lpstruct32Iterate,
+ vpstruct16Iterate );
+
+ if ( FAILED(sc) )
+ {
+ fError = TRUE;
+ dwResult = sc;
+ }
+
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+
+ if ( fError )
+ {
+ //
+ // Cleanup all these guys
+ //
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate <= ulFetched32 )
+ {
+ (*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+ }
+ }
+ }
+
+ if (FAILED(dwResult) && lp16 != NULL)
+ {
+ memset(lp16, 0, ulCount*uiSize16);
+ }
+
+ //
+ // Free up any space we've allocated
+ //
+ if (lpstruct32 != NULL)
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ CoTaskMemFree( lpstruct32 );
+ }
+ else
+ {
+ STACKFREE32(lpstruct32, ulCount*uiSize32);
+ }
+ }
+
+ if ( vpfetched16 != 0 )
+ {
+ lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
+ *lpfetched16 = ulFetched32;
+ RELVDMPTR(vpfetched16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STRING_1632, public
+//
+// Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
+// space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR vpstr;
+ VPSTR UNALIGNED *pvpstr16;
+ SCODE sc;
+
+ vpstr = 0;
+ sc = ConvertTaskString3216(pti, *(LPOLESTR *)lp32, NULL, 0,
+ &vpstr);
+
+ pvpstr16 = FIXVDMPTR(vp16, VPSTR);
+ *pvpstr16 = vpstr;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STRING_1632, public
+//
+// Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR UNALIGNED *lpvpstr16;
+ VPSTR vpstr16;
+
+ lpvpstr16 = FIXVDMPTR( vp16, VPSTR );
+ vpstr16 = *lpvpstr16;
+ RELVDMPTR(vp16);
+
+ if ( vpstr16 != 0 )
+ {
+ TaskFree16( vpstr16 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STRING_1632, public
+//
+// Synopsis: Thunks IEnumSTRING::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STRING_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPOLESTR),
+ sizeof(VPSTR),
+ Callback_STRING_1632,
+ Cleanup_STRING_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_UNKNOWN_1632, public
+//
+// Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpunknown16;
+ SCODE sc = S_OK;
+
+ vpunknown16 =
+ pti->pThkMgr->FindProxy1632(NULL, *(LPUNKNOWN *)lp32,
+ INDEX_IIDIDX(THI_IUnknown), NULL);
+ if (vpunknown16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR( vp16, VPVOID ) = vpunknown16;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_UNKNOWN_1632, public
+//
+// Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPUNKNOWN lpunknown32;
+ VPVOID vpunknown16;
+
+ vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+ lpunknown32 = *(LPUNKNOWN *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (vpunknown16 != 0)
+ {
+ pti->pThkMgr->FreeProxy1632( lpunknown32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_UNKNOWN_1632, public
+//
+// Synopsis: Thunks IEnumUNKNOWN::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_UNKNOWN_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPUNKNOWN),
+ sizeof(LPUNKNOWN),
+ Callback_UNKNOWN_1632,
+ Cleanup_UNKNOWN_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATSTG_1632, public
+//
+// Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ (FIXVDMPTR(vp16, STATSTG))->pwcsName = NULL;
+ RELVDMPTR(vp16);
+ return ConvertStatStg3216(pti, (STATSTG *)lp32, vp16,
+ NULL, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATSTG_1632, public
+//
+// Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATSTG UNALIGNED *lpstatstg16;
+ VPVOID vpstr;
+
+ lpstatstg16 = FIXVDMPTR( vp16, STATSTG );
+ vpstr = (VPVOID)lpstatstg16->pwcsName;
+ RELVDMPTR(vp16);
+
+ if ( vpstr != 0)
+ {
+ TaskFree16( vpstr );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATSTG_1632, public
+//
+// Synopsis: Thunks IEnumSTATSTG::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATSTG_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(STATSTG),
+ sizeof(STATSTG),
+ Callback_STATSTG_1632,
+ Cleanup_STATSTG_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_FORMATETC_1632, public
+//
+// Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ (FIXVDMPTR(vp16, FORMATETC16))->ptd = NULL;
+ RELVDMPTR(vp16);
+ return ConvertFetc3216(pti, (FORMATETC *)lp32, vp16, TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_FORMATETC_1632, public
+//
+// Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ VPVOID vptd;
+
+ lpformatetc16 = FIXVDMPTR( vp16, FORMATETC16 );
+ vptd = lpformatetc16->ptd;
+ RELVDMPTR(vp16);
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_FORMATETC_1632, public
+//
+// Synopsis: Thunks IEnumFORMATETC::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_FORMATETC_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(FORMATETC),
+ sizeof(FORMATETC16),
+ Callback_FORMATETC_1632,
+ Cleanup_FORMATETC_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATDATA_1632, public
+//
+// Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+SCODE Callback_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ LPSTATDATA lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ VPVOID vpadv16;
+
+ sc = S_OK;
+
+ lpstatdata32 = (LPSTATDATA)lp32;
+
+ if (lpstatdata32->pAdvSink != NULL)
+ {
+ // We don't know whether it's an AdviseSink or
+ // an AdviseSink2, so pass AdviseSink2 since it's
+ // a superset of AdviseSink and will work for both
+
+ vpadv16 = pti->pThkMgr->FindProxy1632(NULL, lpstatdata32->pAdvSink,
+ INDEX_IIDIDX(THI_IAdviseSink2),
+ NULL);
+ if (vpadv16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpadv16 = 0;
+ }
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ lpstatdata16->formatetc.ptd = NULL;
+ if (SUCCEEDED(sc))
+ {
+ // If this fails the AdviseSink proxy will be cleaned up in
+ // the cleanup function later
+
+ sc = ConvertFetc3216(pti,
+ &lpstatdata32->formatetc,
+ vp16+FIELD_OFFSET(STATDATA16, formatetc), TRUE);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ lpstatdata16->advf = lpstatdata32->advf;
+ lpstatdata16->pAdvSink = vpadv16;
+ lpstatdata16->dwConnection = lpstatdata32->dwConnection;
+ }
+
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATDATA_1632, public
+//
+// Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATDATA *lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ LPADVISESINK lpadv32;
+ VPVOID vptd;
+
+ lpstatdata32 = (STATDATA FAR *)lp32;
+ lpadv32 = lpstatdata32->pAdvSink;
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ vptd = lpstatdata16->formatetc.ptd;
+ RELVDMPTR(vp16);
+
+ if ( lpstatdata16->pAdvSink != NULL )
+ {
+ // BUGBUG - What is the proper cleanup for interfaces?
+ // Should the objects be released or only the proxies we
+ // created?
+ pti->pThkMgr->FreeProxy1632(lpstatdata32->pAdvSink);
+ }
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATDATA_1632, public
+//
+// Synopsis: Thunks IEnumSTATDATA::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATDATA_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(STATDATA),
+ sizeof(STATDATA16),
+ Callback_STATDATA_1632,
+ Cleanup_STATDATA_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_MONIKER_1632, public
+//
+// Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpmoniker16;
+ SCODE sc = S_OK;
+
+ vpmoniker16 = pti->pThkMgr->FindProxy1632(NULL, *(LPMONIKER *)lp32,
+ INDEX_IIDIDX(THI_IMoniker),
+ NULL);
+ if (vpmoniker16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR(vp16, VPVOID) = vpmoniker16;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_MONIKER_1632, public
+//
+// Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPMONIKER lpmoniker32;
+ VPVOID vpmoniker16;
+
+ vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+ lpmoniker32 = *(LPMONIKER *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (vpmoniker16 != NULL)
+ {
+ pti->pThkMgr->FreeProxy1632( lpmoniker32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_MONIKER_1632, public
+//
+// Synopsis: Thunks IEnumMONIKER::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_MONIKER_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPMONIKER),
+ sizeof(LPMONIKER),
+ Callback_MONIKER_1632,
+ Cleanup_MONIKER_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_OLEVERB_1632, public
+//
+// Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ OLEVERB *lpoleverb32;
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPSTR vpstr;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+ vpstr = 0;
+ sc = ConvertTaskString3216(pti, lpoleverb32->lpszVerbName, NULL, 0,
+ &vpstr);
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ lpoleverb16->lpszVerbName = (LPOLESTR)vpstr;
+ if (SUCCEEDED(sc))
+ {
+ lpoleverb16->lVerb = lpoleverb32->lVerb;
+ lpoleverb16->fuFlags = lpoleverb32->fuFlags;
+ lpoleverb16->grfAttribs = lpoleverb32->grfAttribs;
+ }
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_OLEVERB_1632, public
+//
+// Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPVOID vpstr;
+
+ lpoleverb16 = FIXVDMPTR( vp16, OLEVERB );
+ vpstr = (VPVOID)lpoleverb16->lpszVerbName;
+ RELVDMPTR(vp16);
+
+ if ( vpstr != 0 )
+ {
+ TaskFree16( vpstr );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_OLEVERB_1632, public
+//
+// Synopsis: Thunks IEnumOLEVERB::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_OLEVERB_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(OLEVERB),
+ sizeof(OLEVERB),
+ Callback_OLEVERB_1632,
+ Cleanup_OLEVERB_1632 );
+}
+
+#define THOP_EFN(x) Thop_Enum_ ## x ## _1632
+
+DWORD (*CONST aThopEnumFunctions1632[])(THUNKINFO *) =
+{
+ THOP_EFN(STRING), // STRING
+ THOP_EFN(UNKNOWN), // UNKNOWN
+ THOP_EFN(STATSTG), // STATSTG
+ THOP_EFN(FORMATETC), // FORMATETC
+ THOP_EFN(STATDATA), // STATDATA
+ THOP_EFN(MONIKER), // MONIKER
+ THOP_EFN(OLEVERB), // OLEVERB
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/thop32.cxx b/private/ole32/olethunk/olethk32/thop32.cxx
new file mode 100644
index 000000000..869dd75f3
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop32.cxx
@@ -0,0 +1,3959 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop32.cxx
+//
+// Contents: Thop implementations for 32->16
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2.h>
+#include <string.h>
+#include <valid.h>
+#include "olethk32.hxx"
+#include "struct16.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: EXECUTE_THOP3216, public
+//
+// Synopsis: Debugging version of thop dispatch routine
+//
+// Arguments: [pti] - Thunking info
+//
+// Returns: Appropriate status
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+DWORD EXECUTE_THOP3216(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExThop3216: %s (0x%02X), s16 %p, s32 %p\n",
+ ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
+ return (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti);
+}
+#endif
+
+#if DBG == 1
+DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExEnumThop3216: %s (0x%02X), s16 %p, s32 %p\n",
+ EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ return (*aThopEnumFunctions3216[*(pti)->pThop])(pti);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: FixedThopHandler, public
+//
+// Synopsis: Generic function which handles the high-level details
+// of thop execution for thops that operate on known-size
+// data
+//
+// Arguments: [pti] - Thunking state information
+// [thop] - Thop being executed
+// [cb16] - 16-bit size
+// [pfn1632] - 16->32 conversion routine
+// [cb32] - 32-bit size
+// [pfn3216] - 32->16 conversion routine
+//
+// Returns: Appropriate status code
+//
+// History: 05-Apr-94 DrewB Created
+//
+// Notes: Automatically increments pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD FixedThopHandler3216(THUNKINFO *pti,
+ THOP thop,
+ UINT cb16,
+ FIXEDHANDLERROUTINE pfn1632,
+ UINT cb32,
+ FIXEDHANDLERROUTINE pfn3216)
+{
+ DWORD dwResult;
+ VPVOID vp16;
+ BYTE *pb16;
+ BYTE *pb32;
+
+ if ((thop & (THOP_IN | THOP_OUT)) != 0)
+ {
+ vp16 = 0;
+
+ GET_STACK32(pti, pb32, BYTE *);
+ if ( pb32 != 0 )
+ {
+ if ((thop & THOP_IN) != 0)
+ {
+ if (IsBadReadPtr(pb32, cb32))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+ }
+ if ((thop & THOP_OUT) != 0)
+ {
+ if (IsBadWritePtr(pb32, cb32))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+ }
+
+ vp16 = STACKALLOC16(cb16);
+ if (vp16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ else if ((thop & THOP_IN) != 0)
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+ (pfn3216)(pb32, pb16, cb32, cb16);
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ TO_STACK16(pti, vp16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ((thop & THOP_OUT) != 0 && pb32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+ (pfn1632)(pb16, pb32, cb16, cb32);
+ WOWRELVDMPTR(vp16);
+ }
+ else if ((thop & THOP_IN) == 0)
+ {
+ // Zero out-only parameters on failure
+ memset(pb32, 0, cb32);
+ }
+ }
+
+ if (vp16 != 0)
+ {
+ STACKFREE16(vp16, cb16);
+ }
+ }
+ else
+ {
+ (pfn3216)(PTR_STACK32(&pti->s32), PTR_STACK16(&pti->s16, cb16),
+ cb32, cb16);
+
+ SKIP_STACK16(&pti->s16, cb16);
+ SKIP_STACK32(&pti->s32, cb32);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ return dwResult;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Handler-based thunks
+//
+// These thunks use the fixed-size generic thop handler to do their work
+//
+//-----------------------------------------------------------------------------
+
+// Handle straight copy
+DWORD Thop_Copy_3216(THUNKINFO *pti)
+{
+ THOP thopSize;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
+
+ thopSize = *++pti->pThop;
+ return FixedThopHandler3216(pti,
+ *(pti->pThop-1),
+ thopSize, FhCopyMemory,
+ thopSize, FhCopyMemory);
+}
+
+DWORD Thop_ShortToLong_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(SHORT), FhShortToLong,
+ sizeof(LONG), FhLongToShort);
+}
+
+DWORD Thop_WordToDword_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(WORD), FhWordToDword,
+ sizeof(DWORD), FhDwordToWord);
+}
+
+DWORD Thop_GdiHandle_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhGdiHandle1632,
+ sizeof(HANDLE), FhGdiHandle3216);
+}
+
+DWORD Thop_UserHandle_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhUserHandle1632,
+ sizeof(HANDLE), FhUserHandle3216);
+}
+
+DWORD Thop_HACCEL_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHaccel1632,
+ sizeof(HANDLE), FhHaccel3216);
+}
+
+DWORD Thop_HTASK_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHtask1632,
+ sizeof(HANDLE), FhHtask3216);
+}
+
+DWORD Thop_HRESULT_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HRESULT), FhHresult1632,
+ sizeof(HRESULT), FhHresult3216);
+}
+
+DWORD Thop_NULL_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(void *), FhNull,
+ sizeof(void *), FhNull);
+}
+
+DWORD Thop_RECT_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(RECT16), FhRect1632,
+ sizeof(RECT), FhRect3216);
+}
+
+DWORD Thop_BINDOPTS_3216( THUNKINFO *pti )
+{
+ LPBIND_OPTS pbo;
+ UINT cb;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
+
+ PEEK_STACK32(pti, pbo, LPBIND_OPTS);
+ if (!IsBadReadPtr(pbo, sizeof(LPBIND_OPTS)))
+ {
+ cb = pbo->cbStruct;
+ }
+ else
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ cb, FhCopyMemory,
+ cb, FhCopyMemory);
+}
+
+DWORD Thop_SIZE_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(SIZE16), FhSize1632,
+ sizeof(SIZE), FhSize3216);
+}
+
+DWORD Thop_MSG_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(MSG16), FhMsg1632,
+ sizeof(MSG), FhMsg3216);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ERROR_3216, public
+//
+// Synopsis: Any Thop type which should just fail with an error
+// should go be directed here.
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_ERROR_3216 ( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
+
+ thkAssert( FALSE && "Hey we hit an ERROR Thop in 32->16" );
+
+ return (DWORD)E_UNEXPECTED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInString3216, public
+//
+// Synopsis: Converts an in param string or filename
+//
+// Arguments: [pti] - Thunk state information
+// [fFile] - Filename or plain string
+// [cchMax] - Maximum length allowed or zero
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInString3216(THUNKINFO *pti,
+ BOOL fFile,
+ UINT cchMax)
+{
+ DWORD dwResult;
+ LPOLESTR lpstr32;
+ VPSTR vpstr16;
+ UINT uiSize;
+ LPOLESTR lpstrConv;
+ LPOLESTR lpstrShort;
+
+ dwResult = (DWORD)S_OK;
+
+ lpstrShort = NULL;
+
+ GET_STACK32(pti, lpstr32, LPOLESTR);
+ lpstrConv = lpstr32;
+
+ vpstr16 = 0;
+ if (lpstr32 != NULL)
+ {
+ if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ if (fFile)
+ {
+ DWORD cchNeeded, cchShort;
+
+ // Special case zero-length paths since the length returns from
+ // GetShortPathName become ambiguous when zero characters are
+ // processed
+ cchNeeded = lstrlenW(lpstr32);
+ if (cchNeeded > 0)
+ {
+ cchNeeded = GetShortPathName(lpstr32, NULL, 0);
+ }
+
+ // If we can't convert, simply pass through the name we're given
+ if (cchNeeded > 0)
+ {
+ lpstrShort = (LPOLESTR)CoTaskMemAlloc(cchNeeded*sizeof(WCHAR));
+ if (lpstrShort == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ cchShort = GetShortPathName(lpstr32, lpstrShort,
+ cchNeeded);
+ if (cchShort == 0 || cchShort > cchNeeded)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ lpstrConv = lpstrShort;
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ uiSize = lstrlenW( lpstrConv ) + 1;
+
+ vpstr16 = STACKALLOC16(uiSize*2);
+ if (vpstr16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ char *psz;
+
+ dwResult = Convert_LPOLESTR_to_VPSTR(lpstrConv, vpstr16,
+ uiSize, uiSize*2);
+
+ // If a maximum length was given, truncate the converted
+ // string if necessary
+ if (SUCCEEDED(dwResult) && cchMax > 0 && cchMax < uiSize)
+ {
+ psz = (char *)WOWFIXVDMPTR(vpstr16, 0);
+ psz[cchMax] = 0;
+ WOWRELVDMPTR(vpstr16);
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "In3216 LPSTR %p -> %p '%s'\n",
+ lpstr32, vpstr16,
+ vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
+ if (vpstr16 != 0)
+ {
+ WOWRELVDMPTR(vpstr16);
+ }
+#endif
+
+ TO_STACK16(pti, vpstr16, VPSTR);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if (vpstr16 != 0)
+ {
+ STACKFREE16(vpstr16, uiSize*2);
+ }
+
+ if (lpstrShort != NULL)
+ {
+ CoTaskMemFree(lpstrShort);
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPSTR_3216, public
+//
+// Synopsis: Converts 32-bit LPOLESTR to 16-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LPSTR_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
+ //
+ // We have only input LPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "LPSTR must be input only!" );
+
+ return ThunkInString3216(pti, FALSE, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertTaskString1632, public
+//
+// Synopsis: Converts a task-memory string
+//
+// Arguments: [pti] - Thunk info
+// [vpstr16] - String
+// [posPreAlloc] - Preallocated string or NULL
+// [cchPreAlloc] - Preallocated size or zero
+// [ppos32] - String
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pti]
+// [ppos32]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Frees preallocation if successful and:
+// Name is too large or
+// Name is NULL
+//
+// Always frees source string if non-zero
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertTaskString1632(THUNKINFO *pti,
+ VPSTR vpstr16,
+ LPOLESTR posPreAlloc,
+ UINT cchPreAlloc,
+ LPOLESTR *ppos32)
+{
+ LPOLESTR pos32;
+
+ if (vpstr16 == 0)
+ {
+ pos32 = NULL;
+ }
+ else
+ {
+ pos32 = Convert_VPSTR_to_LPOLESTR(pti, vpstr16, posPreAlloc,
+ cchPreAlloc);
+
+ TaskFree16(vpstr16);
+
+ if (pos32 == NULL)
+ {
+ return pti->scResult;
+ }
+ }
+
+ // If there was a preallocated string we didn't use,
+ // free it
+ if (posPreAlloc != NULL && posPreAlloc != pos32)
+ {
+ TaskFree32(posPreAlloc);
+ }
+
+ *ppos32 = pos32;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkOutString3216, public
+//
+// Synopsis: Converts an out param string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkOutString3216(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ LPOLESTR *lplpstr32;
+ VPVOID vpvpstr16;
+ VPSTR UNALIGNED *lpvpstr16;
+ LPOLESTR lpstr32;
+
+ GET_STACK32(pti, lplpstr32, LPOLESTR FAR *);
+
+ if ( lplpstr32 == NULL )
+ {
+ vpvpstr16 = 0;
+ }
+ else
+ {
+ if (IsBadWritePtr(lplpstr32, sizeof(LPOLESTR)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpvpstr16 = STACKALLOC16(sizeof(VPSTR));
+ if (vpvpstr16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
+ *lpvpstr16 = 0;
+ RELVDMPTR(vpvpstr16);
+
+ lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
+ if (lpstr32 == NULL)
+ {
+ STACKFREE16(vpvpstr16, sizeof(VPSTR));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ TO_STACK16(pti, vpvpstr16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (lplpstr32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
+ if (lpvpstr16 == NULL)
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ SCODE sc;
+
+ sc = ConvertTaskString1632(pti, *lpvpstr16, lpstr32,
+ CWCSTRINGPREALLOC, &lpstr32);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+
+ RELVDMPTR(vpvpstr16);
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree32(lpstr32);
+
+ *lplpstr32 = NULL;
+ }
+ else
+ {
+ *lplpstr32 = lpstr32;
+ }
+
+ thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR: %p -> %p, '%ws'\n",
+ *lpvpstr16, lpstr32, lpstr32));
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR NULL\n"));
+ }
+
+ if (vpvpstr16 != 0)
+ {
+ STACKFREE16(vpvpstr16, sizeof(VPSTR));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPLPSTR_3216, public
+//
+// Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_LPLPSTR_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
+ //
+ // We don't have anything but unmodified LPLPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "LPLPSTR must be unmodified only!" );
+
+ return ThunkOutString3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_BUFFER_3216, public
+//
+// Synopsis: Converts 32-bit block of memory to 16-bit block of memory
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+//
+// Notes: WARNING! WARNING! WARNING! For an out parameter this expects
+// three parameters on the stack in the following format and order:
+// VOID * pointer to buffer
+// DWORD count of bytes in buffer
+// DWORD * count of bytes returned in the buffer
+//
+//----------------------------------------------------------------------------
+
+#define WATCH_VALUE 0xfef1f0
+
+DWORD Thop_BUFFER_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ LPVOID lp32;
+ VPVOID vp16;
+ LPVOID lp16;
+ DWORD dwCount;
+ VPVOID vp16CountOut;
+ LPVOID pvCountOut32;
+ DWORD * pdwCountOut32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // Buffers can only be in or out
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "BUFFER must be in or out only!" );
+
+ GET_STACK32(pti, lp32, LPVOID);
+ GET_STACK32(pti, dwCount, DWORD);
+
+ if (fThopOutput)
+ {
+ GET_STACK32(pti, pvCountOut32, LPVOID);
+ pdwCountOut32 = (DWORD *) pvCountOut32;
+ }
+
+ if ( lp32 == NULL )
+ {
+ vp16 = 0;
+ }
+ else if (dwCount == 0)
+ {
+ // If the count is zero then we can pass any valid 16-bit
+ // pointer
+
+#if DBG == 1
+ // In debug, make sure that no data is written back to the
+ // memory we pass on
+ vp16 = STACKALLOC16(sizeof(DWORD));
+
+ if ( vp16 == 0 )
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR(vp16, DWORD) = WATCH_VALUE;
+ RELVDMPTR(vp16);
+#else
+ vp16 = gdata16Data.atfnProxy1632Vtbl;
+#endif
+ }
+ else
+ {
+ if ((fThopInput && IsBadReadPtr(lp32, dwCount)) ||
+ (fThopOutput && IsBadWritePtr(lp32, dwCount)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vp16 = (VPVOID)WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
+ if ( vp16 == 0 )
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR(vp16, dwCount);
+ memcpy( lp16, lp32, dwCount );
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ if (fThopOutput)
+ {
+ // We always allocate storage so we can guarantee that we
+ // only copy the correct number of bytes.
+ vp16CountOut = STACKALLOC16(sizeof(DWORD));
+
+ if (vp16CountOut == 0)
+ {
+ return (DWORD) E_OUTOFMEMORY;
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "3216 BUFFER: %p -> %p, %u\n",
+ lp32, vp16, dwCount));
+
+ TO_STACK16(pti, vp16, VPVOID );
+ TO_STACK16(pti, dwCount, DWORD );
+
+ if (fThopOutput)
+ {
+ TO_STACK16(pti, vp16CountOut, VPVOID );
+ }
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( SUCCEEDED(dwResult) && fThopOutput )
+ {
+ // Count of bytes to copy into the output buffer
+ DWORD dwCountOut;
+
+ // Get the output data count
+ DWORD UNALIGNED *pdw16 = (DWORD UNALIGNED *)
+ WOWFIXVDMPTR(vp16CountOut, sizeof(DWORD));
+
+ // Save count to return to 32 bit caller.
+ dwCountOut = *pdw16;
+ if (pdwCountOut32)
+ {
+ // Note: this parameter can be a NULL pointer
+ *pdwCountOut32 = dwCountOut;
+ }
+
+ WOWRELVDMPTR(vp16CountOut);
+
+ // Copy data into output buffer if necessary.
+ if (dwCountOut > 0)
+ {
+ lp16 = (LPVOID) WOWFIXVDMPTR( vp16, dwCountOut );
+ memcpy( lp32, lp16, dwCountOut );
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+#if DBG == 1
+ if (vp16 != 0 && dwCount == 0)
+ {
+ thkAssert(*FIXVDMPTR(vp16, DWORD) == WATCH_VALUE &&
+ (RELVDMPTR(vp16), TRUE));
+ STACKFREE16(vp16, sizeof(DWORD));
+ }
+#endif
+
+ //
+ // Now free the buffers
+ //
+ if ( vp16 != 0 && dwCount > 0 )
+ {
+ WgtUnlockFree( vp16 );
+ }
+
+ if (fThopOutput && (vp16CountOut != 0))
+ {
+ STACKFREE16(vp16CountOut, sizeof(DWORD));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SNB_3216, public
+//
+// Synopsis: Converts 32-bit SNB to 16-bit SNB pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_SNB_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+
+ SNB snbSrc32; // Ptr to 32 bit Source SNB.
+ LPOLESTR FAR *lplpsTabSrc32; // Ptr into 32 bit Source ptr table.
+ LPOLESTR lpstr32; // Ptr into a Source Unicode data block.
+
+ VPVOID snbDest16s; // Seg:Ptr to 16 bit Destination SNB.
+ VPSTR UNALIGNED FAR *lpvpsTabDest16f; // Flat Ptr into 16 bit Dest ptr table.
+ char UNALIGNED *lpstrDest16f; // Flat Ptr into 16 bit Dest data block.
+ VPVOID lpstrDest16s; // Seg:Ptr into 16 bit Dest data block.
+
+ UINT cPointers; // Count of number of string pointers.
+ UINT cbStrings; // Count of number of bytes in data table.
+ UINT cLength;
+ UINT cChars;
+ UINT cbAlloc;
+ UINT i;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We don't have anything but unmodified SNBs
+ //
+ thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
+
+ GET_STACK32(pti, snbSrc32, LPOLESTR FAR *);
+
+ if ( snbSrc32 == NULL )
+ {
+ snbDest16s = 0;
+ }
+ else
+ {
+ //
+ // Count the strings in the 32-bit snb
+ //
+ lplpsTabSrc32 = snbSrc32;
+
+ cPointers = 0;
+ cbStrings = 0;
+ do
+ {
+ cPointers++;
+ if (IsBadReadPtr(lplpsTabSrc32, sizeof(LPOLESTR)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ lpstr32 = *lplpsTabSrc32++;
+
+ if ( lpstr32 == NULL )
+ {
+ break;
+ }
+
+ if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ cbStrings += lstrlenW(lpstr32)+1;
+ }
+ while ( TRUE );
+
+ //
+ // Allocate a table for the 16-bit snb
+ // cPointers is a count of pointers plus the NULL pointer at the end.
+ //
+ cbAlloc = cPointers*sizeof(VPSTR)+cbStrings;
+ snbDest16s = (VPVOID)STACKALLOC16(cbAlloc);
+ if (snbDest16s == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ //
+ // Set up the pointers to the destination table and string block.
+ // This gets a flat pointer to the pointer table, a both flat and
+ // segmented pointers to the data block.
+ //
+ lpvpsTabDest16f = (VPSTR UNALIGNED FAR *)WOWFIXVDMPTR( snbDest16s, cbAlloc );
+ lpstrDest16f = (char UNALIGNED *)
+ ((BYTE UNALIGNED *)lpvpsTabDest16f+cPointers*sizeof(VPSTR));
+ lpstrDest16s = (VPVOID)((DWORD)snbDest16s+cPointers*sizeof(VPSTR));
+
+ //
+ // Now convert the strings
+ //
+ cPointers -= 1;
+ lplpsTabSrc32 = snbSrc32;
+ for(i=0; i<cPointers; i++)
+ {
+ lpstr32 = *lplpsTabSrc32++;
+
+ thkAssert( lpstr32 != NULL && "Loop is processing end of snb\n" );
+
+ cLength = lstrlenW( lpstr32 ) + 1;
+
+ cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, lpstr32, cLength,
+ lpstrDest16f, cbStrings, NULL, NULL );
+
+ if ( cChars == 0 && cLength != 0 )
+ {
+ WOWRELVDMPTR(snbDest16s);
+ STACKFREE16(snbDest16s, cbAlloc);
+ return (DWORD)E_UNEXPECTED;
+ }
+
+ //
+ // Assign the Segmented pointer into the pointer table.
+ //
+ *lpvpsTabDest16f++ = lpstrDest16s;
+
+ //
+ // Advance both the flat and segmented data pointers.
+ //
+ lpstrDest16f += cChars;
+ lpstrDest16s = (VPVOID)((DWORD)lpstrDest16s + cChars);
+
+ //
+ // As we advance the Dest pointer the size of the remaining
+ // space in the buffer decreases.
+ //
+ cbStrings -= cChars;
+ }
+
+ // Terminate SNB
+ *lpvpsTabDest16f = NULL;
+
+ thkAssert( *lplpsTabSrc32 == NULL &&
+ "Loop is out of sync with count\n" );
+
+ WOWRELVDMPTR(snbDest16s);
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 SNB: %p -> %p\n", snbSrc32, snbDest16s));
+
+ TO_STACK16(pti, snbDest16s, VPVOID );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ //
+ // Free SNB data if necessary
+ //
+ if ( snbDest16s != 0 )
+ {
+ STACKFREE16( snbDest16s, cbAlloc );
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInterface3216, private
+//
+// Synopsis: Handles 32->16 interface thunking for THOP_IFACE and
+// THOP_IFACEGEN
+//
+// Arguments: [pti] - Thunking state information
+// [iidx] - Interface IID or index
+// [thop] - Thop being executed
+// [vpvOuter] - Controlling unknown or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Assumes pti->pThop is adjusted by caller
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInterface3216(THUNKINFO *pti,
+ IIDIDX iidx,
+ THOP thop,
+ VPVOID vpvOuter)
+{
+ DWORD dwResult;
+ void *pv;
+ VPVOID vpvOutParam;
+ VPVOID vpvThis16In, vpvThis16Out;
+ IUnknown *punkThis32;
+ IUnknown *punkIn;
+ THUNK3216OBJ *ptoPreAlloc = NULL;
+
+ dwResult = (DWORD)S_OK;
+
+ vpvOutParam = 0;
+ vpvThis16In = 0;
+
+ // Retrieve in or out interface pointer
+ GET_STACK32(pti, pv, void *);
+
+ // Out takes precedence over in for determining indirection depth
+
+ if ((thop & THOP_OUT) != 0 && pv != NULL)
+ {
+ if (IsBadReadPtr(pv, sizeof(void *)) ||
+ IsBadWritePtr(pv, sizeof(void *)))
+ {
+ thkDebugOut((DEB_WARN, "WARNING: failing - bad pointer %p\n", pv));
+ return (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ punkIn = *(IUnknown **)pv;
+ }
+ }
+ else
+ {
+ punkIn = (IUnknown *)pv;
+ }
+
+ if ((thop & THOP_IN) != 0)
+ {
+ if (punkIn == NULL)
+ {
+ vpvThis16In = 0;
+ }
+ else
+ {
+ if (!IsValidInterface(punkIn))
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "invalid interface %p\n", punkIn));
+ }
+ else
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // If the Interface is [In,Out] then we need to build a
+ // proxy with a "real" reference, rather than the
+ // "local" ref that is normally built for interfaces
+ // going [in]). Normaly only [out] parameters
+ // (which are build when the call is returning) have
+ // "real" references.
+ // To build a proxy with a "real" reference we trick
+ // "FindProxy1632" into believing it is building an
+ // [out] parameter.
+ THKSTATE thkstateSaved = pti->pThkMgr->GetThkState();
+
+ if ((thop & THOP_INOUT) == THOP_INOUT)
+ {
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+ }
+
+ vpvThis16In = pti->pThkMgr->FindProxy1632(NULL, punkIn, iidx,
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (vpvThis16In == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "Can't create proxy for %p\n", punkIn));
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 %s %p -> %p\n",
+ IidIdxString(iidx), punkIn, vpvThis16In));
+ }
+
+ if ((thop & THOP_OUT) != 0 && SUCCEEDED(dwResult) && pv != NULL)
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // Preallocate a proxy for the out parameter
+ if ((ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx)) == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "Cannot allocate proxy\n"));
+ }
+ else
+ {
+ vpvOutParam = STACKALLOC16(sizeof(VPVOID));
+ if (vpvOutParam == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ *FIXVDMPTR(vpvOutParam, VPVOID) = vpvThis16In;
+ RELVDMPTR(vpvOutParam);
+ TO_STACK16(pti, vpvOutParam, VPVOID);
+ }
+ }
+ }
+ else
+ {
+ TO_STACK16(pti, vpvThis16In, VPVOID);
+ }
+
+ if (SUCCEEDED((SCODE)dwResult))
+ {
+ // Assumes pThop is already adjusted
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if (vpvThis16In != 0)
+ {
+ // Note that if the routine called keeps the proxy around
+ // it should AddRef it so this won't really remove the object
+ pti->pThkMgr->FreeProxy1632(punkIn);
+
+ if ((thop & THOP_OPMASK) == THOP_IFACECLEAN)
+ {
+ // IRpcStubBuffer::DebugServerQueryInterface returns an
+ // interface non-addref'ed
+ // IRpcStubBuffer::DebugServerRelease cleans up a returned
+ // pointer from QI, so for it we have to clean up the proxy
+ // from QI
+
+ // We're assuming that punkIn is actually a proxy
+ pti->pThkMgr->ReleaseUnreferencedProxy3216((THUNK3216OBJ *)punkIn);
+ }
+ }
+
+ if ((thop & THOP_OUT) != 0 && pv != NULL)
+ {
+ punkThis32 = NULL;
+
+ if (SUCCEEDED((SCODE)dwResult))
+ {
+ vpvThis16Out = *FIXVDMPTR(vpvOutParam, VPVOID);
+ RELVDMPTR(vpvOutParam);
+
+ // BUGBUG - No easy way to check interface validity
+ // Requires a 16-bit transition
+
+ if (vpvThis16Out != 0)
+ {
+ // Get a 32-bit proxy object for the 16-bit object
+ if (vpvOuter != 0)
+ {
+ punkThis32 =
+ pti->pThkMgr->FindAggregate3216(ptoPreAlloc, vpvOuter,
+ vpvThis16Out, iidx);
+ }
+ else
+ {
+ punkThis32 =
+ pti->pThkMgr->FindProxy3216(ptoPreAlloc,
+ vpvThis16Out, iidx,
+ NULL);
+ }
+ if (punkThis32 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+ }
+ else if (ptoPreAlloc != NULL)
+ {
+ // Return our preallocated proxy because we don't need it
+ pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
+ }
+
+ // Set the out param
+ *(void **)pv = (void *)punkThis32;
+
+ thkDebugOut((DEB_ARGS, "Out3216 %s %p -> %p\n",
+ IidIdxString(iidx), vpvThis16Out, punkThis32));
+ }
+
+ if (vpvOutParam != 0)
+ {
+ STACKFREE16(vpvOutParam, sizeof(VPVOID));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACEGEN_3216, public
+//
+// Synopsis: Thunks riid,ppv pairs from 16->32
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACEGEN_3216(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvOuter;
+ IID const *piid;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert(thopOp == THOP_IFACEGEN ||
+ thopOp == THOP_IFACEGENOWNER);
+
+ // The current thop byte indicates how many bytes to look
+ // back in the stack to find the IID which identifies the
+ // interface being returned
+ INDEX_STACK32(pti, piid, IID const *, *pti->pThop);
+
+#if DBG == 1
+ if (!IsValidIid(*piid))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+#endif
+
+ pti->pThop++;
+
+ iidx = IidToIidIdx(*piid);
+ vpvOuter = 0;
+ if (thopOp == THOP_IFACEGENOWNER)
+ {
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
+ }
+
+ return ThunkInterface3216(pti, iidx, thop, vpvOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OIFI_3216, public
+//
+// Synopsis: Convert OLEINPLACEFRAMEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_OIFI_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpoifi16;
+ OIFI16 UNALIGNED *poifi16;
+ OLEINPLACEFRAMEINFO *poifi32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ // OIFIs are out-only parameters for their contents
+ // However, cb is in/out, so we need to copy cb on the way in
+ // Furthermore, cb may not be set to a valid value, in which
+ // case the documentation mentions that it should be assumed
+ // that this is an OLE 2.0 OIFI
+ // This thop simply ignores cb on the way in and always sets
+ // it to the OLE 2.0 size
+ // Since we're out-only, this always works since the number of
+ // fields we thunk is the size of the structure that we give out
+ // If OLEINPLACEFRAMEINFO is extended, this thop will break
+
+ // Assert that OLEINPLACEFRAMEINFO is what we expect it to be
+ thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
+
+ GET_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
+
+ vpoifi16 = 0;
+ if (poifi32 != NULL)
+ {
+ if (IsBadWritePtr(poifi32, sizeof(OLEINPLACEFRAMEINFO)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpoifi16 = STACKALLOC16(sizeof(OIFI16));
+ if (vpoifi16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // OIFI's may be an out only parameters but if the "cb" field is
+ // "in" RPC doesn't slice up structs, so the whole thing is "in"
+ // as well. We are Thoping here but if we want this to match
+ // the RPC sematics then we need to copy all the fields.
+
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ poifi16->cb = sizeof(OIFI16);
+ poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
+ poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
+ poifi16->cAccelEntries =
+ ClampULongToUShort(poifi32->cAccelEntries);
+
+ if (poifi32->haccel == NULL)
+ {
+ poifi16->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi16->haccel = HACCEL_16(poifi32->haccel);
+ if (poifi16->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+ RELVDMPTR(vpoifi16);
+ }
+
+ TO_STACK16(pti, vpoifi16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (vpoifi16 != NULL)
+ {
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
+ poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
+ poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
+ poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
+
+ if (poifi16->haccel == NULL)
+ {
+ poifi32->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+
+ // Check that the haccel is valid. We don't need to lock
+ // the pointer. We just want some means of validating it.
+ // HACCEL_32 faults in krnl386 if the handle is bad.
+
+ if(NULL != WOWGlobalLock16(poifi16->haccel))
+ {
+ poifi32->haccel = HACCEL_32(poifi16->haccel);
+ WOWGlobalUnlock16(poifi16->haccel);
+ }
+ else
+ {
+ poifi32->haccel = NULL;
+ }
+
+ if (poifi32->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+#if DBG == 1
+ if (SUCCEEDED(dwResult))
+ {
+ thkDebugOut((DEB_ARGS, "Out3216 OIFI: "
+ "%p {%d, %d, 0x%04X, 0x%04X, %d} -> "
+ "%p {%d, %d, 0x%p, 0x%p, %d}\n",
+ vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
+ (DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
+ poifi16->cAccelEntries,
+ poifi32, poifi32->cb, poifi32->fMDIApp,
+ poifi32->hwndFrame, poifi32->haccel,
+ poifi32->cAccelEntries));
+ }
+#endif
+ }
+
+ RELVDMPTR(vpoifi16);
+
+ if (FAILED(dwResult))
+ {
+ memset(poifi32, 0, sizeof(OLEINPLACEFRAMEINFO));
+ }
+
+ STACKFREE16(vpoifi16, sizeof(OIFI16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STGMEDIUM_3216, public
+//
+// Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
+// structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_STGMEDIUM_3216(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpstgmedium16;
+ STGMEDIUM *lpstgmedium32;
+ DWORD dwSize;
+ SCODE sc;
+ BOOL fReleaseParam;
+ BOOL fTransferOwnership;
+ FORMATETC *pfe;
+ THOP thopFeOffset;
+ DWORD vpIStream = 0;
+ STGMEDIUM UNALIGNED *psm16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We currently don't have any unmodified or inout thops for STGMEDIUMs
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "STGMEDIUM must be input or output only" );
+
+ // +2 thop byte indicates whether there's a FORMATETC to look at
+ // or not
+ // We need to reference this now before the stack is modified
+ // by argument recovery
+ thopFeOffset = *(pti->pThop+2);
+ if (thopFeOffset > 0)
+ {
+ INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
+ }
+ else
+ {
+ pfe = NULL;
+ }
+
+ GET_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
+
+ // Next thop byte indicates whether there's an ownership transfer
+ // argument or not
+ pti->pThop++;
+ fReleaseParam = (BOOL)*pti->pThop++;
+
+ if (fReleaseParam)
+ {
+ GET_STACK32(pti, fTransferOwnership, BOOL);
+ }
+ else
+ {
+ fTransferOwnership = FALSE;
+ }
+
+ // Skip FORMATETC offset thop
+ pti->pThop++;
+
+ vpstgmedium16 = 0;
+
+ if ( lpstgmedium32 != NULL )
+ {
+ if ((fThopInput && IsBadReadPtr(lpstgmedium32, sizeof(STGMEDIUM))) ||
+ (fThopOutput && IsBadWritePtr(lpstgmedium32, sizeof(STGMEDIUM))))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpstgmedium16 = STACKALLOC16(sizeof(STGMEDIUM));
+ if (vpstgmedium16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
+ pfe, fTransferOwnership, &dwSize);
+ if (SUCCEEDED(sc))
+ {
+ // Apparently if you pass TYMED_NULL into GetDataHere
+ // it's supposed to work like GetData, so switch input-only
+ // TYMED_NULLs to output
+ if (lpstgmedium32->tymed == TYMED_NULL &&
+ !fTransferOwnership)
+ {
+ fThopInput = FALSE;
+ fThopOutput = TRUE;
+ }
+ else if (lpstgmedium32->tymed == TYMED_ISTREAM)
+ {
+ //
+ // Excel has a bug in its Clipboard data object that when
+ // GetDataHere is done providing a IStream interface, it
+ // will create its own stream and pounce on the pointer
+ // being passed in. So, if the thing is input, and the
+ // TYMED is ISTREAM we need to stash away the original
+ // 16-bit stream pointer for use later.
+ //
+ psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ vpIStream = (DWORD)psm16->pstm;
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ else
+ {
+ STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
+ return (DWORD)sc;
+ }
+
+ }
+ else
+ {
+ if( !((TlsThkGetAppCompatFlags() & OACF_CORELTRASHMEM) &&
+ lpstgmedium32->tymed == 0x66666666 ))
+ {
+
+ // Even though this is an out parameter, some apps
+ // (Graph 5 is one) check its values and depend on it
+ // being zeroed out
+
+ // However, if we are in CorelDraw *and* we're being
+ // called by wGetMonikerAndClassFromObject (tymed set to
+ // all 6's), then we do not want to set the tymed to zero.
+ // Corel5 relies on the memory being trashed in order to
+ // prevent paste-link-to-yourself.
+
+ memset(FIXVDMPTR(vpstgmedium16, STGMEDIUM), 0,
+ sizeof(STGMEDIUM));
+ RELVDMPTR(vpstgmedium16);
+ }
+
+ }
+ }
+
+ TO_STACK16(pti, vpstgmedium16, VPVOID);
+
+ if (fReleaseParam)
+ {
+ TO_STACK16(pti, (SHORT)fTransferOwnership, SHORT);
+ }
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (lpstgmedium32 != NULL)
+ {
+ if (fThopInput)
+ {
+
+ if (SUCCEEDED(dwResult) &&
+ (lpstgmedium32->tymed == TYMED_ISTREAM) &&
+ (vpIStream != 0))
+ {
+ //
+ // To continue our Excel Clipboard GetDataHere hack, if the
+ // TYMED was ISTREAM, and the medium was input (as it is now)
+ // then we need to detect the case where the IStream pointer
+ // changed. If it did change, then we have a special function
+ // in the 16-bit world that will copy the contents of the
+ // 'new' stream into 'our' stream, and release the 'new'
+ // stream. This should make the clipboard work properly.
+ //
+ psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ if( (psm16->tymed == TYMED_ISTREAM) &&
+ (vpIStream != (DWORD)psm16->pstm))
+ {
+ BYTE b32Args[WCB16_MAX_CBARGS];
+ *(DWORD *)&b32Args[0] = vpIStream;
+ *(DWORD *)&b32Args[sizeof(DWORD)] = (DWORD)psm16->pstm;
+
+ RELVDMPTR(vpstgmedium16);
+
+ if( !CallbackTo16Ex(
+ (DWORD)gdata16Data.fnStgMediumStreamHandler16,
+ WCB16_PASCAL,
+ 2*sizeof(DWORD),
+ b32Args,
+ &dwResult) )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+
+ }
+ else
+ {
+ //
+ // Two possibilites
+ // The stream pointers are the same. Good news
+ // The tymed was changed. Bad news. There isn't anything
+ // we can safely do with the different tymed, so ignore
+ // the whole thing.
+ //
+
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+
+
+ if (!fTransferOwnership || FAILED(dwResult))
+ {
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ dwSize, TRUE, pfe);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ }
+ }
+ else if (SUCCEEDED(dwResult))
+ {
+
+ if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ 0, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+ }
+ else
+ {
+ thkAssert(fThopOutput);
+
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertStgMed1632(pti, vpstgmedium16, lpstgmedium32,
+ pfe, FALSE, &dwSize);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ CallbackTo16(gdata16Data.fnReleaseStgMedium16,
+ vpstgmedium16);
+ }
+ else if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ dwSize, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(lpstgmedium32, 0, sizeof(STGMEDIUM));
+ }
+ }
+ }
+
+ if (vpstgmedium16 != 0)
+ {
+ STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStatStg1632, public
+//
+// Synopsis: Converts a STATSTG
+//
+// Arguments: [pti] - Thunk info
+// [vpss16] - STATSTG
+// [pss32] - STATSTG
+// [posPreAlloc] - Preallocated string memory or NULL
+// [cchPreAlloc] - Amount preallocated
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pss32]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Assumes input STATSTG memory is valid
+// Assumes task memory for the string
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStatStg1632(THUNKINFO *pti,
+ VPVOID vpss16,
+ STATSTG *pss32,
+ LPOLESTR posPreAlloc,
+ UINT cchPreAlloc)
+{
+ STATSTG UNALIGNED *pss16;
+ SCODE sc;
+ LPOLESTR pos32;
+ VPSTR vpstr;
+
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ vpstr = (VPSTR)pss16->pwcsName;
+ RELVDMPTR(vpss16);
+
+ sc = ConvertTaskString1632(pti, vpstr,
+ posPreAlloc, cchPreAlloc,
+ &pos32);
+
+ if (SUCCEEDED(sc))
+ {
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ memcpy(pss32, pss16, sizeof(STATSTG));
+ pss32->pwcsName = pos32;
+ RELVDMPTR(vpss16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STATSTG_3216, public
+//
+// Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_STATSTG_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ STATSTG *lpstatstg32;
+ VPVOID vpstatstg16;
+ LPOLESTR lpstr32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
+
+ //
+ // We currently don't have any input thops for STATSTGs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
+ "STATSTG must be output only" );
+
+ GET_STACK32(pti, lpstatstg32, STATSTG FAR *);
+
+ if (IsBadWritePtr(lpstatstg32, sizeof(STATSTG)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpstatstg16 = STACKALLOC16(sizeof(STATSTG));
+ if (vpstatstg16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
+ if (lpstr32 == NULL)
+ {
+ STACKFREE16(vpstatstg16, sizeof(STATSTG));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ TO_STACK16(pti, vpstatstg16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (SUCCEEDED(dwResult))
+ {
+ SCODE sc;
+
+ sc = ConvertStatStg1632(pti, vpstatstg16, lpstatstg32,
+ lpstr32, CWCSTRINGPREALLOC);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree32(lpstr32);
+
+ memset(lpstatstg32, 0, sizeof(STATSTG));
+ }
+
+ STACKFREE16(vpstatstg16, sizeof(STATSTG));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_DVTARGETDEVICE_3216, public
+//
+// Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_DVTARGETDEVICE_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ DVTARGETDEVICE FAR *lpdv32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
+
+ //
+ // We currently don't have any output thops for DVTARGETDEVICEs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "DVTARGETDEVICE must be input only" );
+
+ //
+ // Processing for a DVTARGETDEVICE FAR * as input
+ //
+ GET_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
+
+ vpdv16 = 0;
+
+ if ( lpdv32 != NULL )
+ {
+ sc = ConvertDvtd3216(pti, lpdv32, ArStack16, FrStack16, &vpdv16,
+ &uiSize);
+ if (FAILED(sc))
+ {
+ return (DWORD)sc;
+ }
+ }
+
+ TO_STACK16(pti, vpdv16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( lpdv32 != NULL )
+ {
+ FrStack16((void *)vpdv16, uiSize);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FORMATETC_3216, public
+//
+// Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_FORMATETC_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpformatetc16;
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ LPFORMATETC lpformatetc32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ vpdv16 = 0;
+
+ //
+ // We have only input or output thops
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "formatetc must be input or output only" );
+
+ GET_STACK32(pti, lpformatetc32, LPFORMATETC);
+
+ if ( lpformatetc32 == NULL )
+ {
+ vpformatetc16 = 0;
+ }
+ else
+ {
+ if ((fThopInput && IsBadReadPtr(lpformatetc32, sizeof(LPFORMATETC))) ||
+ (fThopOutput && IsBadWritePtr(lpformatetc32, sizeof(LPFORMATETC))))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpformatetc16 = STACKALLOC16(sizeof(FORMATETC16));
+ if (vpformatetc16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, FALSE);
+ if (FAILED(sc))
+ {
+ STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
+ return (DWORD)sc;
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+
+ //
+ // The below memset is needed at least for the DATA_S_SAMEFORMATETC
+ // case. This allows it to be cleaned up because all its pointers
+ // will be null.
+ //
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ memset(lpformatetc16, 0, sizeof(FORMATETC16) );
+ RELVDMPTR(vpformatetc16);
+ }
+ }
+
+ TO_STACK16(pti, vpformatetc16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (fThopInput && vpformatetc16 != 0)
+ {
+ VPVOID vptd;
+
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ vptd = (VPVOID)lpformatetc16->ptd;
+ RELVDMPTR(vpformatetc16);
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+ }
+
+ if ( fThopOutput && lpformatetc32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, TRUE);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(lpformatetc32, 0, sizeof(FORMATETC));
+ }
+ }
+
+ if (vpformatetc16 != 0)
+ {
+ STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LOGPALETTE_3216, public
+//
+// Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
+// and converts 32-bit LOGPALETTE returned to 16-bit structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LOGPALETTE_3216 ( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ LPLOGPALETTE lplogpal32;
+ VPVOID vplogpal16;
+ LOGPALETTE UNALIGNED *lplogpal16;
+ LPLOGPALETTE *lplplogpal32;
+ VPVOID vpvplogpal16;
+ VPVOID UNALIGNED *lpvplogpal16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
+
+ //
+ // It must be either an input or output LOGPALETTE
+ //
+ thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
+ "Hey, LOGPALETTE can't be input and output!" );
+
+ if ( (*pti->pThop & THOP_IN) != 0 )
+ {
+ //
+ // Processing for a LPLOGPALETTE as input
+ //
+ GET_STACK32(pti, lplogpal32, LPLOGPALETTE);
+
+ if ( lplogpal32 == NULL )
+ {
+ vplogpal16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(lplogpal32, sizeof(LOGPALETTE)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ uiSize = CBPALETTE(lplogpal32->palNumEntries);
+
+ if (IsBadReadPtr(lplogpal32, uiSize))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vplogpal16 = STACKALLOC16(uiSize);
+ if (vplogpal16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lplogpal16 = (LOGPALETTE UNALIGNED *)
+ WOWFIXVDMPTR( vplogpal16, uiSize );
+
+ memcpy( lplogpal16, lplogpal32, uiSize );
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+
+ TO_STACK16(pti, vplogpal16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( vplogpal16 != 0 )
+ {
+ STACKFREE16(vplogpal16, uiSize);
+ }
+ }
+ else
+ {
+ //
+ // Processing for LPLPLOGPALETTE as output
+ //
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ GET_STACK32(pti, lplplogpal32, LPLOGPALETTE FAR *);
+ if (IsBadWritePtr(lplplogpal32, sizeof(LPLOGPALETTE)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpvplogpal16 = (VPVOID)STACKALLOC16(sizeof(LPLOGPALETTE));
+ if (vpvplogpal16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lplogpal32 = (LPLOGPALETTE)TaskMalloc32(CBPALETTE(NPALETTEPREALLOC));
+ if (lplogpal32 == NULL)
+ {
+ STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ //
+ // We DO need to zero out the pointer on the way in.
+ //
+ *FIXVDMPTR(vpvplogpal16, LPLOGPALETTE) = 0;
+ RELVDMPTR(vpvplogpal16);
+
+ TO_STACK16(pti, vpvplogpal16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (SUCCEEDED(dwResult))
+ {
+ lpvplogpal16 = FIXVDMPTR( vpvplogpal16, VPVOID);
+ vplogpal16 = *lpvplogpal16;
+ RELVDMPTR(vpvplogpal16);
+
+ if ( vplogpal16 == 0 )
+ {
+ TaskFree32(lplogpal32);
+ lplogpal32 = NULL;
+ }
+ else
+ {
+ lplogpal16 = FIXVDMPTR( vplogpal16, LOGPALETTE );
+
+ //
+ // Copy the returned LOGPALETTE into 16-bit memory
+ //
+ uiSize = CBPALETTE(lplogpal16->palNumEntries);
+ if (uiSize > CBPALETTE(NPALETTEPREALLOC))
+ {
+ TaskFree32(lplogpal32);
+
+ lplogpal32 = (LPLOGPALETTE)TaskMalloc32(uiSize);
+ if ( lplogpal32 == NULL )
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ if (lplogpal32 != NULL)
+ {
+ memcpy( lplogpal32, lplogpal16, uiSize );
+ }
+
+ RELVDMPTR(vplogpal16);
+
+ TaskFree16( vplogpal16 );
+ }
+ }
+ else
+ {
+ TaskFree32(lplogpal32);
+ lplogpal32 = NULL;
+ }
+
+ //
+ // Update the value pointed to by the parameter on the 16-bit stack
+ //
+ *lplplogpal32 = lplogpal32;
+
+ if (vpvplogpal16 != 0)
+ {
+ STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
+ }
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CRGIID_3216, public
+//
+// Synopsis: Converts 32-bit CRGIID to 16-bit CRGIID structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_CRGIID_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ DWORD dwCount;
+ VPVOID vpiid16;
+ IID UNALIGNED *lpiid16;
+ IID *lpiid32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
+
+ //
+ // We currently don't have any output thops for CRGIIDs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "CRGIID must be unmodified only" );
+
+ GET_STACK32(pti, dwCount, DWORD);
+ GET_STACK32(pti, lpiid32, IID FAR *);
+
+ if ( lpiid32 == NULL )
+ {
+ vpiid16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(lpiid32, dwCount*sizeof(IID)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpiid16 = STACKALLOC16( dwCount * sizeof(IID) );
+ if (vpiid16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpiid16 = (IID UNALIGNED *)
+ WOWFIXVDMPTR( vpiid16, dwCount*sizeof(IID) );
+
+ memcpy( lpiid16, lpiid32, dwCount*sizeof(IID) );
+
+ WOWRELVDMPTR(vpiid16);
+ }
+
+ TO_STACK16(pti, dwCount, DWORD);
+ TO_STACK16(pti, vpiid16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( vpiid16 != 0 )
+ {
+ STACKFREE16( vpiid16, dwCount * sizeof(IID) );
+ }
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_INTERFACEINFO_3216, public
+//
+// Synopsis: Converts an INTERFACEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 19-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_INTERFACEINFO_3216(THUNKINFO *pti)
+{
+ INTERFACEINFO *pii32;
+ INTERFACEINFO16 UNALIGNED *pii16;
+ VPVOID vpii16;
+ DWORD dwResult;
+ VPVOID vpunk16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
+ thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
+
+ vpunk16 = 0;
+
+ GET_STACK32(pti, pii32, INTERFACEINFO *);
+ if (pii32 == NULL)
+ {
+ vpii16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(pii32, sizeof(INTERFACEINFO)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpii16 = STACKALLOC16(sizeof(INTERFACEINFO16));
+ if (vpii16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if (pii32->pUnk != NULL)
+ {
+ vpunk16 = pti->pThkMgr->FindProxy1632(NULL, pii32->pUnk,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (vpunk16 == 0)
+ {
+ STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ pii16->pUnk = vpunk16;
+ pii16->iid = pii32->iid;
+ pii16->wMethod = pii32->wMethod;
+
+ thkDebugOut((DEB_ARGS,
+ "In3216 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
+ pii32, vpii16, pii16->pUnk, pii32->pUnk,
+ IidOrInterfaceString(&pii16->iid), pii16->wMethod));
+
+ RELVDMPTR(vpii16);
+ }
+
+ TO_STACK16(pti, vpii16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (vpunk16 != 0)
+ {
+ pti->pThkMgr->FreeProxy1632(pii32->pUnk);
+ }
+
+ if (vpii16 != 0)
+ {
+ STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RETURNTYPE_3216, public
+//
+// Synopsis: Thunks the return value of a call
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+// Notes: This thunk assumes that the return value will always fit
+// in 32 bits and that the thops for it are only one thop
+// long. This fits the existing APIs and methods
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_RETURNTYPE_3216(THUNKINFO *pti)
+{
+ THOP thops[2];
+ DWORD dwResult;
+ THUNK3216OBJ *ptoPreAlloc = NULL;
+ IIDIDX iidx;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RETURNTYPE);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->fResultThunked = TRUE;
+
+ pti->pThop++;
+
+ // Remember return type thop
+ thops[0] = *pti->pThop++;
+ if ((thops[0] & THOP_OPMASK) == THOP_COPY ||
+ (thops[0] & THOP_OPMASK) == THOP_IFACE ||
+ (thops[0] & THOP_OPMASK) == THOP_ALIAS32)
+ {
+ thops[1] = *pti->pThop++;
+ }
+
+ // Preallocate any necessary resources
+ switch(thops[0])
+ {
+ case THOP_IFACE | THOP_IN:
+ iidx = INDEX_IIDIDX(thops[1]);
+ if ((ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx)) == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ break;
+ }
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ // Now that we have the return value thunk it from 16->32
+
+ switch(thops[0])
+ {
+ case THOP_COPY:
+ // Only handle DWORD copies
+ thkAssert(thops[1] == sizeof(DWORD));
+ break;
+
+ case THOP_SHORTLONG:
+ // For boolean results, not necessary to clamp
+ dwResult = (DWORD)(LONG)*(SHORT *)&dwResult;
+ break;
+
+ case THOP_IFACE | THOP_IN:
+ if (dwResult != 0)
+ {
+ // BUGBUG - What if another thop failed and returned an HRESULT?
+ // This will break
+ dwResult =
+ (DWORD)pti->pThkMgr->FindProxy3216(ptoPreAlloc, dwResult,
+ iidx, NULL);
+ thkAssert(dwResult != 0);
+
+ thkDebugOut((DEB_ARGS, "Ret3216 %s %p\n",
+ inInterfaceNames[thops[1]].pszInterface,
+ dwResult));
+ }
+ else
+ {
+ pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
+ }
+ break;
+
+ default:
+ thkAssert(!"Unhandled 3216 return type");
+ break;
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACE_3216, public
+//
+// Synopsis: Thunks a known interface pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACE_3216(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvOuter;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert( thopOp == THOP_IFACE
+ || thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACECLEAN);
+
+ iidx = INDEX_IIDIDX(*pti->pThop++);
+ // There's a bit of a special case here in that IMalloc is
+ // not thunked so it doesn't have a real index but it's used
+ // in thop strings so it has a fake index to function as a placeholder
+ // The fake index is THI_COUNT so allow that in the assert
+ thkAssert(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) <= THI_COUNT);
+
+ vpvOuter = 0;
+ if (thopOp == THOP_IFACEOWNER)
+ {
+ // For cases where the controlling unknown is known,
+ // index back on the stack and find the 32-bit unknown
+ // pointer to use
+ thopWeakOffset = *pti->pThop++;
+
+ INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
+
+ }
+
+ return ThunkInterface3216(pti, iidx, thop, vpvOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ALIAS32_3216, public
+//
+// Synopsis: Handles 16-bit aliases to 32-bit quantities
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ALIAS32_3216(THUNKINFO *pti)
+{
+ ALIAS alias;
+ DWORD dwValue;
+ THOP thopAction;
+ BOOL fTemporary = FALSE;
+ DWORD dwResult;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->pThop++;
+
+ GET_STACK32(pti, dwValue, DWORD);
+
+ // Second byte indicates how the alias should be handled
+ thopAction = *pti->pThop++;
+
+ if (dwValue != 0)
+ {
+ switch(thopAction)
+ {
+ case ALIAS_RESOLVE:
+ alias = gAliases32.ValueAlias(dwValue);
+
+ // There may be cases where there is no existing alias
+ // for a value (for example, remoted SetMenu calls where
+ // the HOLEMENU is a temporary RPC object)
+ // so create a temporary one
+ if (alias == INVALID_ALIAS)
+ {
+ alias = gAliases32.AddValue(dwValue);
+ if (alias == INVALID_ALIAS)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ fTemporary = TRUE;
+ }
+ break;
+
+ default:
+ thkAssert(!"Default hit in Thop_ALIAS32_3216");
+ break;
+ }
+ }
+ else
+ {
+ alias = 0;
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 ALIAS32: 0x%08lX -> 0x%04X\n",
+ dwValue, alias));
+
+ TO_STACK16(pti, alias, ALIAS);
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (fTemporary)
+ {
+ gAliases32.RemoveAlias(alias);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RPCOLEMESSAGE_3216, public
+//
+// Synopsis: Converts 32-bit RPCOLEMESSAGE to 16-bit RPCOLEMESSAGE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_RPCOLEMESSAGE_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ PRPCOLEMESSAGE prom32;
+ VPVOID vprom16;
+ RPCOLEMESSAGE UNALIGNED *prom16;
+ VPVOID vpvBuffer16;
+ LPVOID lp16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
+
+ //
+ // We currently have only IN/OUT RPCOLEMESSAGE
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
+ "RPCOLEMESSAGE must be input/output only" );
+
+ vprom16 = 0;
+ vpvBuffer16 = 0;
+
+ //
+ // Processing for a RPCOLEMESSAGE FAR * as input/output
+ //
+ GET_STACK32(pti, prom32, RPCOLEMESSAGE *);
+ if ( prom32 != 0 )
+ {
+ // Copy over the input RPCOLEMESSAGE structure
+
+ vprom16 = STACKALLOC16(sizeof(RPCOLEMESSAGE));
+ if (vprom16 == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ *prom16 = *prom32;
+ ROM_THUNK_FIELD(prom16) = (void *)prom32;
+ RELVDMPTR(vprom16);
+
+ // If there's a buffer, copy it
+ if (prom32->cbBuffer != 0)
+ {
+ vpvBuffer16 = TaskMalloc16(prom32->cbBuffer);
+ if (vpvBuffer16 == NULL)
+ {
+ STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ prom16->Buffer = (LPVOID) vpvBuffer16;
+ lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer16, prom32->cbBuffer);
+ memcpy( lp16, prom32->Buffer, prom32->cbBuffer );
+ WOWRELVDMPTR(vpvBuffer16);
+ RELVDMPTR(vprom16);
+ }
+ }
+
+ TO_STACK16(pti, vprom16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ prom16 = (PRPCOLEMESSAGE)FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ if (prom16 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ VPVOID vpvBuffer;
+
+ vpvBuffer = (VPVOID)prom16->Buffer;
+ RELVDMPTR(vprom16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ if ( prom32->Buffer != NULL )
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer, prom16->cbBuffer);
+ if (lp16 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( prom32->Buffer, lp16, prom16->cbBuffer );
+
+ WOWRELVDMPTR(vpvBuffer);
+ }
+ }
+ }
+
+ if ( vpvBuffer16 != 0 )
+ {
+ // We'd better have a buffer at this point
+ thkAssert( vpvBuffer != 0);
+
+ // Free up the buffer that we've been dealing with
+ TaskFree16(vpvBuffer);
+ }
+ }
+
+ if ( vprom16 != 0 )
+ {
+ STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
+ }
+
+ return dwResult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ENUM_3216, public
+//
+// Synopsis: Thunks Enum::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is the start of a 2-byte thop. The next thop
+// byte references a function in the enumerator table, rather
+// than the standard thop table.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ENUM_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ //
+ // Get then next thop byte and execute it as a Enum thop
+ //
+ pti->pThop++;
+ return EXECUTE_ENUMTHOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallbackProcessing_3216, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+typedef struct tagCallbackControl
+{
+ DWORD dwContinue;
+ LPVOID lpfn32;
+} CALLBACKCONTROL;
+
+
+STDAPI_(BOOL) CallbackProcessing_3216( DWORD dwContinue, DWORD dw1, DWORD dw2 )
+{
+ BOOL fResult;
+ CALLBACKCONTROL *lpcbc;
+ BOOL (*lpfn32)(DWORD);
+
+ lpcbc = (CALLBACKCONTROL *)dwContinue;
+
+ lpfn32 = (BOOL (*)(DWORD))lpcbc->lpfn32;
+
+ fResult = (*lpfn32)(lpcbc->dwContinue);
+
+ if ( fResult ) // This maps DWORD sized BOOLs into WORD sized BOOLs
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CALLBACK_3216, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CALLBACK_3216(THUNKINFO *pti)
+{
+ LPVOID lpfn32;
+ DWORD dwContinue;
+ CALLBACKCONTROL cbc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK32(pti, lpfn32, LPVOID);
+ GET_STACK32(pti, dwContinue, DWORD);
+
+ if ( lpfn32 == 0 )
+ {
+ TO_STACK16(pti, NULL, VPVOID);
+ TO_STACK16(pti, dwContinue, DWORD);
+ }
+ else
+ {
+ cbc.lpfn32 = lpfn32;
+ cbc.dwContinue = dwContinue;
+
+ TO_STACK16(pti, gdata16Data.fnCallbackHandler, DWORD);
+ TO_STACK16(pti, (DWORD)&cbc, DWORD);
+ }
+
+ pti->pThop++;
+ return EXECUTE_THOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CLSCONTEXT_3216, public
+//
+// Synopsis: Converts a class context flags DWORD
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CLSCONTEXT_3216(THUNKINFO *pti)
+{
+ DWORD dwClsContext;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ // When passing a 32-bit class context to 16-bits nothing
+ // nothing special needs to be done
+
+ GET_STACK32(pti, dwClsContext, DWORD);
+ TO_STACK16(pti, dwClsContext, DWORD);
+
+ pti->pThop++;
+ return EXECUTE_THOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FILENAME_3216, public
+//
+// Synopsis: Converts a filename string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FILENAME_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
+
+ // Can be in or out only
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ if ((*pti->pThop & THOP_IN) != 0)
+ {
+ // Convert filenames going from 32->16 to short filenames
+ // to avoid any possible problems with non-8.3 names.
+
+ return ThunkInString3216(pti, TRUE, 0);
+ }
+ else
+ {
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ // No special processing is necessary for filenames going
+ // from 16->32 since it isn't possible for 16-bit code to
+ // generate a filename which can't be handled in 32-bits
+
+ return ThunkOutString3216(pti);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SIZEDSTRING_3216, public
+//
+// Synopsis: Converts strings which cannot exceed a given length
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 02-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_SIZEDSTRING_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
+
+ // Advance once to account for the length byte
+ // ThunkInString will advance again
+ pti->pThop++;
+ return ThunkInString3216(pti, FALSE, *pti->pThop);
+}
+
+#define THOP_FN(x) Thop_ ## x ## _3216
+
+DWORD (* CONST aThopFunctions3216[])(THUNKINFO *) =
+{
+
+ // x = Implemented
+ // ? = Mysteriously not needed
+ // = Left to do
+ //
+ // ^
+ // |
+ // +===+
+ // |
+ // v
+ //
+ ThunkCall3216, // x Terminating THOP
+ Thop_ShortToLong_3216, // x SHORTLONG
+ Thop_WordToDword_3216, // x WORDDWORD
+ Thop_Copy_3216, // x COPY
+ THOP_FN(LPSTR), // x LPSTR
+ THOP_FN(LPLPSTR), // x LPLPSTR
+ THOP_FN(BUFFER), // x BUFFER
+ Thop_UserHandle_3216, // x HUSER
+ Thop_GdiHandle_3216, // x HGDI
+ THOP_FN(SIZE), // x SIZE
+ THOP_FN(RECT), // x RECT
+ THOP_FN(MSG), // x MSG
+ THOP_FN(HRESULT), // x HRESULT
+ THOP_FN(STATSTG), // x STATSTG
+ THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
+ THOP_FN(STGMEDIUM), // x STGMEDIUM
+ THOP_FN(FORMATETC), // x FORMATETC
+ THOP_FN(HACCEL), // x HACCEL
+ THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
+ THOP_FN(BINDOPTS), // x BIND_OPTS
+ THOP_FN(LOGPALETTE), // x LOGPALETTE
+ THOP_FN(SNB), // x SNB
+ THOP_FN(CRGIID), // x CRGIID
+ Thop_ERROR_3216, // x OLESTREAM (only 16-bit)
+ THOP_FN(HTASK), // x HTASK
+ THOP_FN(INTERFACEINFO), // x INTERFACEINFO
+ THOP_FN(IFACE), // x IFACE
+ THOP_FN(IFACE), // x IFACEOWNER
+ THOP_FN(IFACE), // x IFACENOADDREF
+ THOP_FN(IFACE), // x IFACECLEAN
+ THOP_FN(IFACEGEN), // x IFACEGEN
+ THOP_FN(IFACEGEN), // x IFACEGENOWNER
+ Thop_ERROR_3216, // x ROUTINE_INDEX
+ THOP_FN(RETURNTYPE), // x RETURN_TYPE
+ THOP_FN(NULL), // x NULL
+ Thop_ERROR_3216, // x ERROR
+ THOP_FN(ENUM), // x ENUM
+ THOP_FN(CALLBACK), // x CALLBACK
+ THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
+ THOP_FN(ALIAS32), // x ALIAS32
+ THOP_FN(CLSCONTEXT), // x CLSCONTEXT
+ THOP_FN(FILENAME), // x FILENAME
+ THOP_FN(SIZEDSTRING), // x SIZEDSTRING
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: General_Enum_3216, private
+//
+// Synopsis: Thunking for standard OLE enumerator interface ::Next member
+// function.
+//
+// Arguments: [pti] - Thunk state information
+// [uiSize32] - 32-bit information size
+// [uiSize16] - 16-bit information size
+// [pfnCallback] - Data thunking callback
+// [pfnCleanup] - Thunking cleanup
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This handler is called from many IXXXEnum::Next handlers thop
+// thunks to do the standard sorts of "buffer of structures"
+// processing.
+//
+//----------------------------------------------------------------------------
+#define MAX_ALLOCA_STRUCT 5 // 16-bit stacks are precious
+
+DWORD General_Enum_3216(
+ THUNKINFO *pti,
+ UINT uiSize32,
+ UINT uiSize16,
+ SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
+ void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
+{
+ DWORD dwResult;
+ ULONG ulCount;
+ VPVOID vpstruct16;
+ VPVOID vpfetched16;
+ LPVOID lpstruct32;
+ LPVOID lpstruct32Iterate;
+ VPVOID vpstruct16Iterate;
+ ULONG *lpfetched32;
+ ULONG UNALIGNED *lpfetched16;
+ ULONG ulFetched16;
+ ULONG ulIterate;
+ BOOL fError;
+ SCODE sc;
+ LPVOID pvArg32;
+
+ dwResult = (DWORD)S_OK;
+
+ GET_STACK32(pti, ulCount, ULONG );
+ GET_STACK32(pti, lpstruct32, LPVOID );
+ GET_STACK32(pti, lpfetched32, ULONG FAR *);
+
+ vpfetched16 = STACKALLOC16(sizeof(ULONG));
+ if (vpfetched16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ // Zero this out so that we don't have a random value sitting
+ // underneath
+ // when bad apps like 16-bit MsWorks don't return the number of items
+ // in the returned enumeration.
+
+ lpfetched16 = FIXVDMPTR(vpfetched16, ULONG);
+ *lpfetched16 = 0;
+ RELVDMPTR(vpfetched16);
+ }
+
+ pvArg32 = NULL;
+ vpstruct16 = 0;
+
+ if ( lpstruct32 != NULL )
+ {
+ if ( ulCount == 0 )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ if (IsBadWritePtr(lpstruct32, ulCount*uiSize32))
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ pvArg32 = lpstruct32;
+
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ vpstruct16 = WgtAllocLock( GMEM_MOVEABLE,
+ ulCount * uiSize16,
+ NULL );
+ }
+ else
+ {
+ vpstruct16 = STACKALLOC16( ulCount * uiSize16 );
+ }
+
+ if (vpstruct16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ TO_STACK16(pti, ulCount, ULONG);
+ TO_STACK16(pti, vpstruct16, VPVOID);
+ TO_STACK16(pti, vpfetched16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if ( SUCCEEDED(dwResult) )
+ {
+ lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
+ ulFetched16 = *lpfetched16;
+ RELVDMPTR(vpfetched16);
+
+ if ( lpstruct32 != NULL )
+ {
+ // Some apps (MsWorks3 is one) return S_FALSE and do not return
+ // the number of elements retrieved. The only thing we can
+ // do is ignore the enumeration since we don't know how many
+ // were actually set. Of course, we can't ignore all enumerations
+ // when the return is S_FALSE so we only handle the case
+ // where S_FALSE was returned on a enumeration of one element,
+ // in which we can be sure there isn't any valid data
+ if (dwResult == (DWORD)S_FALSE && ulCount == 1)
+ {
+ ulFetched16 = 0;
+ }
+
+ //
+ // Iterate through all of the structures, converting them
+ // into 16-bit
+ //
+ fError = FALSE;
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate < ulFetched16 )
+ {
+ //
+ // Callback to the callback function to do any specific
+ // processing
+ //
+ sc = (*pfnCallback)( pti, lpstruct32Iterate,
+ vpstruct16Iterate );
+
+ if ( FAILED(sc) )
+ {
+ fError = TRUE;
+ dwResult = sc;
+ }
+
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+
+ if ( fError )
+ {
+ //
+ // Cleanup all these guys
+ //
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate <= ulFetched16 )
+ {
+ (*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+ }
+ }
+ }
+
+ if (FAILED(dwResult) && pvArg32 != NULL)
+ {
+ memset(pvArg32, 0, ulCount*uiSize32);
+ }
+
+ if ( lpfetched32 != NULL )
+ {
+ *lpfetched32 = ulFetched16;
+ }
+
+ //
+ // Free up any space we've allocated
+ //
+ if (vpstruct16 != 0)
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ WgtUnlockFree( vpstruct16 );
+ }
+ else
+ {
+ STACKFREE16( vpstruct16, ulCount * uiSize16 );
+ }
+ }
+
+ if (vpfetched16 != 0)
+ {
+ STACKFREE16(vpfetched16, sizeof(ULONG));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STRING_3216, public
+//
+// Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
+// space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR vpstr;
+
+ *(LPOLESTR *)lp32 = NULL;
+ vpstr = *FIXVDMPTR(vp16, VPSTR);
+ RELVDMPTR(vp16);
+ return ConvertTaskString1632(pti, vpstr, NULL, 0, (LPOLESTR *)lp32);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STRING_3216, public
+//
+// Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPOLESTR lpstr32;
+
+ lpstr32 = *(LPOLESTR *)lp32;
+ if ( lpstr32 != NULL )
+ {
+ TaskFree32( lpstr32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STRING_3216, public
+//
+// Synopsis: Thunks IEnumSTRING::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STRING_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPOLESTR),
+ sizeof(VPSTR),
+ Callback_STRING_3216,
+ Cleanup_STRING_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_UNKNOWN_3216, public
+//
+// Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc = S_OK;
+ VPVOID vpunknown16;
+ IUnknown *punkThis32;
+
+ vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+
+ punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpunknown16,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *(LPUNKNOWN *)lp32 = (LPUNKNOWN)punkThis32;
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_UNKNOWN_3216, public
+//
+// Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPUNKNOWN lpunknown32;
+ VPVOID vpv;
+
+ lpunknown32 = *(LPUNKNOWN *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (lpunknown32 != NULL)
+ {
+ vpv = *FIXVDMPTR(vp16, VPVOID);
+ RELVDMPTR(vp16);
+ pti->pThkMgr->FreeProxy3216(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_UNKNOWN_3216, public
+//
+// Synopsis: Thunks IEnumUNKNOWN::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_UNKNOWN_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPUNKNOWN),
+ sizeof(LPUNKNOWN),
+ Callback_UNKNOWN_3216,
+ Cleanup_UNKNOWN_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATSTG_3216, public
+//
+// Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ ((STATSTG *)lp32)->pwcsName = NULL;
+ return ConvertStatStg1632(pti, vp16, (STATSTG *)lp32,
+ NULL, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATSTG_3216, public
+//
+// Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATSTG FAR *lpstatstg32;
+
+ lpstatstg32 = (STATSTG FAR *)lp32;
+
+ if ( lpstatstg32->pwcsName != NULL )
+ {
+ TaskFree32( lpstatstg32->pwcsName );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATSTG_3216, public
+//
+// Synopsis: Thunks IEnumSTATSTG::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATSTG_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(STATSTG),
+ sizeof(STATSTG),
+ Callback_STATSTG_3216,
+ Cleanup_STATSTG_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_FORMATETC_3216, public
+//
+// Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ ((FORMATETC *)lp32)->ptd = NULL;
+ return ConvertFetc1632(pti, vp16, (FORMATETC *)lp32, TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_FORMATETC_3216, public
+//
+// Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ FORMATETC FAR *lpformatetc32;
+
+ lpformatetc32 = (FORMATETC FAR *)lp32;
+
+ if ( lpformatetc32->ptd != NULL )
+ {
+ TaskFree32( lpformatetc32->ptd );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_FORMATETC_3216, public
+//
+// Synopsis: Thunks IEnumFORMATETC::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_FORMATETC_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(FORMATETC),
+ sizeof(FORMATETC16),
+ Callback_FORMATETC_3216,
+ Cleanup_FORMATETC_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATDATA_3216, public
+//
+// Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+SCODE Callback_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ LPSTATDATA lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ LPADVISESINK lpadv32;
+ VPVOID vpadv16;
+ IUnknown *punkThis32;
+
+ sc = S_OK;
+
+ lpstatdata32 = (LPSTATDATA)lp32;
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ vpadv16 = lpstatdata16->pAdvSink;
+ RELVDMPTR(vp16);
+
+ if ( vpadv16 != 0)
+ {
+ // We don't know whether it's an AdviseSink or
+ // an AdviseSink2, so pass AdviseSink2 since it's
+ // a superset of AdviseSink and will work for both
+
+ punkThis32 =
+ pti->pThkMgr->FindProxy3216(NULL, vpadv16,
+ INDEX_IIDIDX(THI_IAdviseSink2),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ lpadv32 = (LPADVISESINK)punkThis32;
+ }
+ else
+ {
+ lpadv32 = NULL;
+ }
+
+ lpstatdata32->formatetc.ptd = NULL;
+ if (SUCCEEDED(sc))
+ {
+ // If this fails the AdviseSink proxy will be cleaned up in
+ // the cleanup function later
+
+ sc = ConvertFetc1632(pti,
+ vp16+FIELD_OFFSET(STATDATA16, formatetc),
+ &lpstatdata32->formatetc, TRUE);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ lpstatdata32->advf = lpstatdata16->advf;
+ lpstatdata32->pAdvSink = lpadv32;
+ lpstatdata32->dwConnection = lpstatdata16->dwConnection;
+ RELVDMPTR(vp16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATDATA_3216, public
+//
+// Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATDATA FAR *lpstatdata32;
+ VPVOID vpvSink;
+
+ lpstatdata32 = (STATDATA FAR *)lp32;
+
+ if ( lpstatdata32->formatetc.ptd != NULL )
+ {
+ TaskFree32( lpstatdata32->formatetc.ptd );
+ }
+
+ if ( lpstatdata32->pAdvSink != NULL )
+ {
+ // BUGBUG - What is the proper cleanup for interfaces?
+ // Should the objects be released or only the proxies we
+ // created?
+ vpvSink = (FIXVDMPTR( vp16, STATDATA16 ))->pAdvSink;
+ RELVDMPTR(vp16);
+
+ pti->pThkMgr->FreeProxy3216(vpvSink);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATDATA_3216, public
+//
+// Synopsis: Thunks IEnumSTATDATA::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATDATA_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(STATDATA),
+ sizeof(STATDATA16),
+ Callback_STATDATA_3216,
+ Cleanup_STATDATA_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_MONIKER_3216, public
+//
+// Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpmoniker16;
+ IUnknown *punkThis32;
+ SCODE sc = S_OK;
+
+ vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+
+ punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpmoniker16,
+ INDEX_IIDIDX(THI_IMoniker),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *(LPMONIKER *)lp32 = (LPMONIKER)punkThis32;
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_MONIKER_3216, public
+//
+// Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPMONIKER lpmoniker32;
+ VPVOID vpv;
+
+ lpmoniker32 = *(LPMONIKER *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (lpmoniker32 != NULL)
+ {
+ vpv = *FIXVDMPTR(vp16, VPVOID);
+ RELVDMPTR(vp16);
+ pti->pThkMgr->FreeProxy3216(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_MONIKER_3216, public
+//
+// Synopsis: Thunks IEnumMONIKER::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_MONIKER_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPMONIKER),
+ sizeof(LPMONIKER),
+ Callback_MONIKER_3216,
+ Cleanup_MONIKER_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_OLEVERB_3216, public
+//
+// Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ OLEVERB *lpoleverb32;
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPSTR vpstr;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ vpstr = (VPSTR)lpoleverb16->lpszVerbName;
+ RELVDMPTR(vp16);
+
+ lpoleverb32->lpszVerbName = NULL;
+ sc = ConvertTaskString1632(pti, vpstr, NULL, 0,
+ &lpoleverb32->lpszVerbName);
+ if (SUCCEEDED(sc))
+ {
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ lpoleverb32->lVerb = lpoleverb16->lVerb;
+ lpoleverb32->fuFlags = lpoleverb16->fuFlags;
+ lpoleverb32->grfAttribs = lpoleverb16->grfAttribs;
+ RELVDMPTR(vp16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_OLEVERB_3216, public
+//
+// Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ OLEVERB FAR *lpoleverb32;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+
+ if ( lpoleverb32->lpszVerbName != NULL )
+ {
+ TaskFree32( lpoleverb32->lpszVerbName );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_OLEVERB_3216, public
+//
+// Synopsis: Thunks IEnumOLEVERB::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_OLEVERB_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(OLEVERB),
+ sizeof(OLEVERB),
+ Callback_OLEVERB_3216,
+ Cleanup_OLEVERB_3216 );
+}
+
+#define THOP_EFN(x) Thop_Enum_ ## x ## _3216
+
+DWORD (*CONST aThopEnumFunctions3216[])(THUNKINFO *) =
+{
+ THOP_EFN(STRING), // STRING
+ THOP_EFN(UNKNOWN), // UNKNOWN
+ THOP_EFN(STATSTG), // STATSTG
+ THOP_EFN(FORMATETC), // FORMATETC
+ THOP_EFN(STATDATA), // STATDATA
+ THOP_EFN(MONIKER), // MONIKER
+ THOP_EFN(OLEVERB), // OLEVERB
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/thopapi.hxx b/private/ole32/olethunk/olethk32/thopapi.hxx
new file mode 100644
index 000000000..f4bcf22d4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopapi.hxx
@@ -0,0 +1,37 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopapi.hxx
+//
+// Contents: API thops header
+//
+// History: 22-Feb-94 DrewB Created
+//
+// Notes: This file declares generated tables found in
+// thtblapi.cxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPAPI_HXX__
+#define __THOPAPI_HXX__
+
+// These are declared extern "C" because there was a bug in the
+// PPC compiler (aug '95) where the const related decorations on
+// the global data symbols was not done consistantly. By using
+// extern "C" the bug is simply avoided.
+
+extern "C" THOP CONST * CONST apthopsApiThops[];
+extern VTBLFN CONST apfnApiFunctions[];
+
+// These two routines aren't in the public headers but are needed
+// in vtblapi.cxx
+STDAPI ReadOleStg
+ (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
+ DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut);
+STDAPI WriteOleStg
+ (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut);
+
+#endif // #ifndef __THOPAPI_HXX__
diff --git a/private/ole32/olethunk/olethk32/thopiint.cxx b/private/ole32/olethunk/olethk32/thopiint.cxx
new file mode 100644
index 000000000..f979594cf
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopiint.cxx
@@ -0,0 +1,83 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopiint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "thopsint.cxx"
+#include "thtblint.cxx"
+#include "vtblifn.cxx"
+#include "vtblint.cxx"
+#include "fntomthd.cxx"
+
+THOPI CONST athopiInterfaceThopis[] =
+{
+ apthopsIUnknown, 3, tfnIUnknown, NULL
+, apthopsIClassFactory, 5, tfnIClassFactory, ftmIClassFactory
+, apthopsIMarshal, 9, tfnIMarshal, ftmIMarshal
+, apthopsIStdMarshalInfo, 4, tfnIStdMarshalInfo, ftmIStdMarshalInfo
+, apthopsIMessageFilter, 6, tfnIMessageFilter, ftmIMessageFilter
+, apthopsIExternalConnection, 5, tfnIExternalConnection, ftmIExternalConnection
+, apthopsIEnumString, 7, tfnIEnumString, ftmIEnumString
+, apthopsIEnumUnknown, 7, tfnIEnumUnknown, ftmIEnumUnknown
+, apthopsIEnumSTATSTG, 7, tfnIEnumSTATSTG, ftmIEnumSTATSTG
+, apthopsILockBytes, 10, tfnILockBytes, ftmILockBytes
+, apthopsIStream, 14, tfnIStream, ftmIStream
+, apthopsIStorage, 18, tfnIStorage, ftmIStorage
+, apthopsIRootStorage, 4, tfnIRootStorage, ftmIRootStorage
+, apthopsIEnumFORMATETC, 7, tfnIEnumFORMATETC, ftmIEnumFORMATETC
+, apthopsIEnumSTATDATA, 7, tfnIEnumSTATDATA, ftmIEnumSTATDATA
+, apthopsIDataObject, 12, tfnIDataObject, ftmIDataObject
+, apthopsIViewObject, 9, tfnIViewObject, ftmIViewObject
+, apthopsIViewObject2, 10, tfnIViewObject2, ftmIViewObject2
+, apthopsIAdviseSink, 8, tfnIAdviseSink, ftmIAdviseSink
+, apthopsIAdviseSink2, 9, tfnIAdviseSink2, ftmIAdviseSink2
+, apthopsIDataAdviseHolder, 7, tfnIDataAdviseHolder, ftmIDataAdviseHolder
+, apthopsIOleCache, 8, tfnIOleCache, ftmIOleCache
+, apthopsIOleCache2, 10, tfnIOleCache2, ftmIOleCache2
+, apthopsIOleCacheControl, 5, tfnIOleCacheControl, ftmIOleCacheControl
+, apthopsIDropTarget, 7, tfnIDropTarget, ftmIDropTarget
+, apthopsIDropSource, 5, tfnIDropSource, ftmIDropSource
+, apthopsIPersist, 4, tfnIPersist, ftmIPersist
+, apthopsIPersistStorage, 10, tfnIPersistStorage, ftmIPersistStorage
+, apthopsIPersistStream, 8, tfnIPersistStream, ftmIPersistStream
+, apthopsIPersistFile, 9, tfnIPersistFile, ftmIPersistFile
+, apthopsIBindCtx, 13, tfnIBindCtx, ftmIBindCtx
+, apthopsIMoniker, 23, tfnIMoniker, ftmIMoniker
+, apthopsIRunningObjectTable, 10, tfnIRunningObjectTable, ftmIRunningObjectTable
+, apthopsIEnumMoniker, 7, tfnIEnumMoniker, ftmIEnumMoniker
+, apthopsIEnumOLEVERB, 7, tfnIEnumOLEVERB, ftmIEnumOLEVERB
+, apthopsIOleObject, 24, tfnIOleObject, ftmIOleObject
+, apthopsIOleClientSite, 9, tfnIOleClientSite, ftmIOleClientSite
+, apthopsIRunnableObject, 8, tfnIRunnableObject, ftmIRunnableObject
+, apthopsIParseDisplayName, 4, tfnIParseDisplayName, ftmIParseDisplayName
+, apthopsIOleContainer, 6, tfnIOleContainer, ftmIOleContainer
+, apthopsIOleItemContainer, 9, tfnIOleItemContainer, ftmIOleItemContainer
+, apthopsIOleAdviseHolder, 9, tfnIOleAdviseHolder, ftmIOleAdviseHolder
+, apthopsIOleLink, 14, tfnIOleLink, ftmIOleLink
+, apthopsIOleWindow, 5, tfnIOleWindow, ftmIOleWindow
+, apthopsIOleInPlaceObject, 9, tfnIOleInPlaceObject, ftmIOleInPlaceObject
+, apthopsIOleInPlaceActiveObject, 10, tfnIOleInPlaceActiveObject, ftmIOleInPlaceActiveObject
+, apthopsIOleInPlaceUIWindow, 9, tfnIOleInPlaceUIWindow, ftmIOleInPlaceUIWindow
+, apthopsIOleInPlaceFrame, 15, tfnIOleInPlaceFrame, ftmIOleInPlaceFrame
+, apthopsIOleInPlaceSite, 15, tfnIOleInPlaceSite, ftmIOleInPlaceSite
+, apthopsIRpcChannelBuffer, 8, tfnIRpcChannelBuffer, ftmIRpcChannelBuffer
+, apthopsIRpcProxyBuffer, 5, tfnIRpcProxyBuffer, ftmIRpcProxyBuffer
+, apthopsIRpcStubBuffer, 10, tfnIRpcStubBuffer, ftmIRpcStubBuffer
+, apthopsIPSFactoryBuffer, 5, tfnIPSFactoryBuffer, ftmIPSFactoryBuffer
+, apthopsIRpcChannel, 7, tfnIRpcChannel, ftmIRpcChannel
+, apthopsIRpcProxy, 5, tfnIRpcProxy, ftmIRpcProxy
+, apthopsIRpcStub, 8, tfnIRpcStub, ftmIRpcStub
+, apthopsIPSFactory, 5, tfnIPSFactory, ftmIPSFactory
+};
diff --git a/private/ole32/olethunk/olethk32/thopint.hxx b/private/ole32/olethunk/olethk32/thopint.hxx
new file mode 100644
index 000000000..5d5eea987
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopint.hxx
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopint.hxx
+//
+// Contents: Interface thops header file
+//
+// History: 22-Feb-94 DrewB Created
+//
+// Notes: This file declares generated tables found in
+// thtblint.cxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPINT_HXX__
+#define __THOPINT_HXX__
+
+typedef DWORD (*THUNK3216FN)(THUNK3216OBJ *ptoThis);
+
+typedef struct tagTHOPI
+{
+ THOP CONST * CONST * ppThops;
+ UINT uiSize;
+ THUNK3216FN CONST * pt3216fn;
+ BYTE CONST * pftm;
+} THOPI;
+
+typedef struct tagIIDTOTHI
+{
+ IID CONST * piid;
+ int iThi;
+} IIDTOTHI;
+
+extern THOPI CONST athopiInterfaceThopis[];
+extern IIDTOTHI CONST aittIidToThi[];
+
+#endif // #ifndef __THOPINT_HXX__
diff --git a/private/ole32/olethunk/olethk32/thopsapi.cxx b/private/ole32/olethunk/olethk32/thopsapi.cxx
new file mode 100644
index 000000000..5493fb3d9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopsapi.cxx
@@ -0,0 +1,427 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopsapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST thopsCoInitialize[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMalloc, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoUninitialize[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoGetClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_CLSCONTEXT, THOP_NULL | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCoRegisterClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_CLSCONTEXT, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCoRevokeClassObject[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoMarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsCoUnmarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoReleaseMarshalData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoDisconnectObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoLockObjectExternal[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoGetStandardMarshal[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMarshal, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsCoIsHandlerConnected[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoFreeAllLibraries[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoFreeUnusedLibraries[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoCreateInstance[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_CLSCONTEXT, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCLSIDFromString[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoIsOle1Class[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsProgIDFromCLSID[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCLSIDFromProgID[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoCreateGuid[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoFileTimeToDosDateTime[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 8, THOP_WORDDWORD | THOP_OUT, THOP_WORDDWORD | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoDosDateTimeToFileTime[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_WORDDWORD, THOP_WORDDWORD, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 8
+};
+THOP CONST thopsCoFileTimeNow[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoRegisterMessageFilter[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMessageFilter, THOP_IFACE | THOP_OUT, THI_IMessageFilter, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoGetTreatAsClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoTreatAsClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsDllGetClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsStgCreateDocfile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsStgCreateDocfileOnILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsStgOpenStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsStgOpenStorageOnILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsStgIsStorageFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsStgIsStorageILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsStgSetTimes[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsCreateDataAdviseHolder[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IDataAdviseHolder, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCreateDataCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 12, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsBindMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY, 4, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMkParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMonikerRelativePathTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMonikerCommonPrefixWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateBindCtx[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateGenericComposite[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsGetClassFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateFileMoniker[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateItemMoniker[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateAntiMoniker[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCreatePointerMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsGetRunningObjectTable[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IRunningObjectTable, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadClassStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteClassStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadClassStm[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteClassStm[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteFmtUserTypeStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 19
+};
+THOP CONST thopsReadFmtUserTypeStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD | THOP_OUT, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleInitialize[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMalloc, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleUninitialize[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsOleQueryLinkFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleQueryCreateFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreate[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLinkFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateStaticFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLink[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLinkToFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateFromFile[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END,
+ THOP_ROUTINEINDEX, 20
+};
+THOP CONST thopsOleLoad[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACEGEN | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleSave[] =
+{
+ THOP_IFACE | THOP_IN, THI_IPersistStorage, THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleLoadFromStream[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleSaveToStream[] =
+{
+ THOP_IFACE | THOP_IN, THI_IPersistStream, THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetContainedObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleNoteObjectVisible[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsRegisterDragDrop[] =
+{
+ THOP_HUSER, THOP_IFACE | THOP_IN, THI_IDropTarget, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsRevokeDragDrop[] =
+{
+ THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsDoDragDrop[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_IFACE | THOP_IN, THI_IDropSource, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleSetClipboard[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleGetClipboard[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleFlushClipboard[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsOleIsCurrentClipboard[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreateMenuDescriptor[] =
+{
+ THOP_RETURNTYPE, THOP_ALIAS32, ALIAS_CREATE, THOP_HUSER, THOP_COPY | THOP_IN, 24, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetMenuDescriptor[] =
+{
+ THOP_ALIAS32, ALIAS_RESOLVE, THOP_HUSER, THOP_HUSER, THOP_IFACE | THOP_IN, THI_IOleInPlaceFrame, THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsOleDestroyMenuDescriptor[] =
+{
+ THOP_ALIAS32, ALIAS_REMOVE, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleDraw[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_HGDI, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleRun[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleIsRunning[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IOleObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleLockRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateOleAdviseHolder[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleAdviseHolder, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreateDefaultHandler[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleCreateEmbeddingHelper[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IClassFactory, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 16, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsOleRegGetUserType[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegGetMiscStatus[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegEnumFormatEtc[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegEnumVerbs[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleConvertIStorageToOLESTREAM[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_OLESTREAM | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleConvertOLESTREAMToIStorage[] =
+{
+ THOP_OLESTREAM | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IStorage, THOP_DVTARGETDEVICE | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleConvertIStorageToOLESTREAMEx[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_STGMEDIUM | THOP_IN, 0, 0, THOP_OLESTREAM | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 21
+};
+THOP CONST thopsOleConvertOLESTREAMToIStorageEx[] =
+{
+ THOP_OLESTREAM | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD | THOP_OUT, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_STGMEDIUM | THOP_IN, 0, 0, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleDoAutoConvert[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleGetAutoConvert[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetAutoConvert[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsGetConvertStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsSetConvertStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadOleStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsWriteOleStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACE | THOP_IN, THI_IOleObject, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 2
+};
diff --git a/private/ole32/olethunk/olethk32/thopsint.cxx b/private/ole32/olethunk/olethk32/thopsint.cxx
new file mode 100644
index 000000000..9b0a06cf1
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopsint.cxx
@@ -0,0 +1,1313 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopsint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST thopsIClassFactory_CreateInstance[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIClassFactory_LockServer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMarshal_GetUnmarshalClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_GetMarshalSizeMax[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_MarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_UnmarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMarshal_ReleaseMarshalData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMarshal_DisconnectObject[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStdMarshalInfo_GetClassForHandler[] =
+{
+ THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMessageFilter_HandleInComingCall[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_INTERFACEINFO | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMessageFilter_RetryRejectedCall[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMessageFilter_MessagePending[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIExternalConnection_AddConnection[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIExternalConnection_ReleaseConnection[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumString_Next[] =
+{
+ THOP_ENUM, THE_IEnumString, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumString_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumString_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumString_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumString, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumUnknown_Next[] =
+{
+ THOP_ENUM, THE_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumUnknown_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumUnknown_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumUnknown_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATSTG_Next[] =
+{
+ THOP_ENUM, THE_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumSTATSTG_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATSTG_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumSTATSTG_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+
+// Note: THOP_BUFFER | THOP_OUT takes care of the size of the input buffer
+// and the size of the output buffer.
+THOP CONST thopsILockBytes_ReadAt[] =
+{
+ THOP_COPY, 8, THOP_BUFFER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 9
+};
+THOP CONST thopsILockBytes_WriteAt[] =
+{
+ THOP_COPY, 8, THOP_BUFFER | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 9
+};
+THOP CONST thopsILockBytes_Flush[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsILockBytes_SetSize[] =
+{
+ THOP_COPY, 8, THOP_END, THOP_ROUTINEINDEX, 10
+};
+THOP CONST thopsILockBytes_LockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsILockBytes_UnlockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsILockBytes_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+
+// Note: THOP_BUFFER | THOP_OUT takes care of the size of the input buffer
+// and the size of the output buffer.
+THOP CONST thopsIStream_Read[] =
+{
+ THOP_BUFFER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 2
+};
+
+THOP CONST thopsIStream_Write[] =
+{
+ THOP_BUFFER | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIStream_Seek[] =
+{
+ THOP_COPY, 8, THOP_COPY, 4, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 12
+};
+THOP CONST thopsIStream_SetSize[] =
+{
+ THOP_COPY, 8, THOP_END, THOP_ROUTINEINDEX, 10
+};
+THOP CONST thopsIStream_CopyTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY, 8, THOP_COPY | THOP_OUT, 8, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 13
+};
+THOP CONST thopsIStream_Commit[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStream_Revert[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIStream_LockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsIStream_UnlockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsIStream_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStream_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_CreateStream[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_OpenStream[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_CreateStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_OpenStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIStorage_CopyTo[] =
+{
+ THOP_CRGIID, THOP_SNB, THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_MoveElementTo[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_Commit[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_Revert[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIStorage_EnumElements[] =
+{
+ THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_DestroyElement[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_RenameElement[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStorage_SetElementTimes[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_SetClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_SetStateBits[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStorage_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRootStorage_SwitchToFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumFORMATETC_Next[] =
+{
+ THOP_ENUM, THE_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumFORMATETC_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumFORMATETC_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumFORMATETC_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATDATA_Next[] =
+{
+ THOP_ENUM, THE_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumSTATDATA_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATDATA_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumSTATDATA_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_GetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_OUT, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_GetDataHere[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_QueryGetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_GetCanonicalFormatEtc[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_FORMATETC | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIDataObject_EnumFormatEtc[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_DAdvise[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIDataObject_DUnadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_EnumDAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject_Draw[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_HGDI, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_CALLBACK, THOP_END, THOP_ROUTINEINDEX, 14
+};
+THOP CONST thopsIViewObject_GetColorSet[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_LOGPALETTE | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIViewObject_Freeze[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIViewObject_Unfreeze[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject_SetAdvise[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject_GetAdvise[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_Draw[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_HGDI, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_CALLBACK, THOP_END, THOP_ROUTINEINDEX, 14
+};
+THOP CONST thopsIViewObject2_GetColorSet[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_LOGPALETTE | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIViewObject2_Freeze[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIViewObject2_Unfreeze[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject2_SetAdvise[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_GetAdvise[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_GetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_DVTARGETDEVICE | THOP_IN, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIAdviseSink_OnDataChange[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink_OnViewChange[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink_OnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIAdviseSink_OnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink_OnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnDataChange[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink2_OnViewChange[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink2_OnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIAdviseSink2_OnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnLinkSrcChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIDataAdviseHolder_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_SendOnDataChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache_Cache[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache_Uncache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_EnumCache[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_InitCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_Cache[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_Uncache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_EnumCache[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_InitCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_UpdateCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_DiscardCache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCacheControl_OnRun[] =
+{
+ THOP_IFACENOADDREF | THOP_IN, THI_IDataObject, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCacheControl_OnStop[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIDropTarget_DragEnter[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 15
+};
+THOP CONST thopsIDropTarget_DragOver[] =
+{
+ THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 16
+};
+THOP CONST thopsIDropTarget_DragLeave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIDropTarget_Drop[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 15
+};
+THOP CONST thopsIDropSource_QueryContinueDrag[] =
+{
+ THOP_SHORTLONG, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDropSource_GiveFeedback[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersist_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStorage_InitNew[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistStorage_SaveCompleted[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_HandsOffStorage[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStream_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStream_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStream_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStream_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistStream_GetSizeMax[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistFile_Load[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistFile_Save[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistFile_SaveCompleted[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_GetCurFile[] =
+{
+ THOP_FILENAME | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RegisterObjectBound[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RevokeObjectBound[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_ReleaseBoundObjects[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIBindCtx_SetBindOptions[] =
+{
+ THOP_BINDOPTS | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_GetBindOptions[] =
+{
+ THOP_BINDOPTS | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_GetRunningObjectTable[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IRunningObjectTable, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RegisterObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIBindCtx_GetObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIBindCtx_EnumObjectParam[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumString, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RevokeObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIMoniker_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_GetSizeMax[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_BindToObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_BindToStorage[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_Reduce[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY, 4, THOP_IFACE | THOP_INOUT, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_ComposeWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_SHORTLONG, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_Enum[] =
+{
+ THOP_SHORTLONG, THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_IsEqual[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_Hash[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_IsRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_GetTimeOfLastChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_Inverse[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_CommonPrefixWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_RelativePathTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_GetDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIMoniker_IsSystemMoniker[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_Register[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIRunningObjectTable_Revoke[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_IsRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_GetObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_NoteChangeTime[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_GetTimeOfLastChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_EnumRunning[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumMoniker_Next[] =
+{
+ THOP_ENUM, THE_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumMoniker_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumMoniker_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumMoniker_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumOLEVERB_Next[] =
+{
+ THOP_ENUM, THE_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumOLEVERB_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumOLEVERB_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumOLEVERB_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_SetClientSite[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetClientSite[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleClientSite, THOP_END, THOP_ROUTINEINDEX, 3
+};
+/*
+ The eighty character limit was arrived at by trial and error
+ with ClipArt Gallery. It faults at 90 characters.
+ */
+THOP CONST thopsIOleObject_SetHostNames[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_SIZEDSTRING | THOP_IN, 80, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Close[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_SetMoniker[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_GetMoniker[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleObject_InitFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_SHORTLONG, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleObject_GetClipboardData[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_DoVerb[] =
+{
+ THOP_COPY, 4, THOP_MSG | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_COPY, 4, THOP_HUSER, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIOleObject_EnumVerbs[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_Update[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleObject_IsUpToDate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleObject_GetUserClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetUserType[] =
+{
+ THOP_COPY, 4, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_SetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_GetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetMiscStatus[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_SetColorScheme[] =
+{
+ THOP_LOGPALETTE | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_SaveObject[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleClientSite_GetMoniker[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleClientSite_GetContainer[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleContainer, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_ShowObject[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleClientSite_OnShowWindow[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_RequestNewObjectLayout[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRunnableObject_GetRunningClass[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunnableObject_Run[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunnableObject_IsRunning[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRunnableObject_LockRunning[] =
+{
+ THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunnableObject_SetContainedObject[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIParseDisplayName_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleContainer_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleContainer_EnumObjects[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleContainer_LockContainer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleItemContainer_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleItemContainer_EnumObjects[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleItemContainer_LockContainer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleItemContainer_GetObject[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIOleItemContainer_GetObjectStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleItemContainer_IsRunning[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleAdviseHolder_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_SendOnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_SendOnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleAdviseHolder_SendOnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_SetUpdateOptions[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_GetUpdateOptions[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_SetSourceMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleLink_GetSourceMoniker[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_SetSourceDisplayName[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_GetSourceDisplayName[] =
+{
+ THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_BindToSource[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleLink_BindIfRunning[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_GetBoundSource[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_UnbindSource[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_Update[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleWindow_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleWindow_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_InPlaceDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceObject_UIDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceObject_SetObjectRects[] =
+{
+ THOP_RECT | THOP_IN, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceObject_ReactivateAndUndo[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceActiveObject_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_TranslateAccelerator[] =
+{
+ THOP_MSG | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_OnFrameWindowActivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_OnDocWindowActivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_ResizeBorder[] =
+{
+ THOP_RECT | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleInPlaceFrame, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleInPlaceActiveObject_EnableModeless[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_GetBorder[] =
+{
+ THOP_RECT | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_RequestBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_SetBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_SetActiveObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_GetBorder[] =
+{
+ THOP_RECT | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_RequestBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetActiveObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_InsertMenus[] =
+{
+ THOP_HUSER, THOP_COPY | THOP_INOUT, 24, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_SetMenu[] =
+{
+ THOP_HUSER, THOP_ALIAS32, ALIAS_RESOLVE, THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleInPlaceFrame_RemoveMenus[] =
+{
+ THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetStatusText[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_EnableModeless[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_TranslateAccelerator[] =
+{
+ THOP_MSG | THOP_IN, THOP_WORDDWORD, THOP_END, THOP_ROUTINEINDEX, 17
+};
+THOP CONST thopsIOleInPlaceSite_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_CanInPlaceActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnInPlaceActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnUIActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_GetWindowContext[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleInPlaceFrame, THOP_IFACE | THOP_OUT, THI_IOleInPlaceUIWindow, THOP_RECT | THOP_OUT, THOP_RECT | THOP_OUT, THOP_OIFI | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIOleInPlaceSite_Scroll[] =
+{
+ THOP_SIZE, THOP_END, THOP_ROUTINEINDEX, 18
+};
+THOP CONST thopsIOleInPlaceSite_OnUIDeactivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_OnInPlaceDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_DiscardUndoState[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_DeactivateAndUndo[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnPosRectChange[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannelBuffer_GetBuffer[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_SendReceive[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_FreeBuffer[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannelBuffer_GetDestCtx[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_NULL | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_IsConnected[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcProxyBuffer_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IRpcChannelBuffer, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcProxyBuffer_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_Invoke[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IRpcChannelBuffer, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcStubBuffer_IsIIDSupported[] =
+{
+ THOP_RETURNTYPE, THOP_IFACE | THOP_IN, THI_IRpcStubBuffer, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_CountRefs[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_DebugServerQueryInterface[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_DebugServerRelease[] =
+{
+ THOP_IFACECLEAN | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPSFactoryBuffer_CreateProxy[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEOWNER | THOP_OUT, THI_IRpcProxyBuffer, 8, THOP_IFACEGENOWNER | THOP_OUT, 8, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIPSFactoryBuffer_CreateStub[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACEOWNER | THOP_OUT, THI_IRpcStubBuffer, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIRpcChannel_GetStream[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_SHORTLONG, THOP_SHORTLONG, THOP_SHORTLONG, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIRpcChannel_Call[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannel_GetDestCtx[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_NULL | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannel_IsConnected[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcProxy_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IRpcChannel, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcProxy_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStub_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStub_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStub_Invoke[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIRpcStub_IsIIDSupported[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStub_CountRefs[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPSFactory_CreateProxy[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEOWNER | THOP_OUT, THI_IRpcProxy, 8, THOP_IFACEGENOWNER | THOP_OUT, 8, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIPSFactory_CreateStub[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACEOWNER | THOP_OUT, THI_IRpcStub, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
diff --git a/private/ole32/olethunk/olethk32/thoputil.cxx b/private/ole32/olethunk/olethk32/thoputil.cxx
new file mode 100644
index 000000000..da4f424b6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thoputil.cxx
@@ -0,0 +1,4547 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thoputil.cxx
+//
+// Contents: Utility routines for thunking
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stdio.h>
+#include <limits.h>
+
+#include <vdmdbg.h>
+#include <valid.h>
+
+//
+// Chicago doesn't support the NT ExpLdr API, use the new Chicago
+// WOWGetDescriptor that copies the LDT info to a provided buffer.
+//
+#if defined(_CHICAGO_)
+extern "C" WOWGetDescriptor(VPVOID, VDMLDT_ENTRY *);
+#else
+extern "C" DECLSPEC_IMPORT VDMLDT_ENTRY *ExpLdt;
+#endif
+
+#include "struct16.hxx"
+
+#define CF_INVALID ((CLIPFORMAT)0)
+
+#define OBJDESC_CF(cf) \
+ ((cf) == g_cfObjectDescriptor || (cf) == g_cfLinkSourceDescriptor)
+
+// Alias manager for THOP_ALIAS32
+CAliases gAliases32;
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidToIidIdx, public
+//
+// Synopsis: Looks up an interface index by IID
+// If it's not found, it returns the IID pointer
+//
+// Arguments: [riid] - IID
+//
+// Returns: Index or IID
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+IIDIDX IidToIidIdx(REFIID riid)
+{
+ int idx;
+
+ for (idx = 0; idx < THI_COUNT; idx++)
+ {
+ if (IsEqualIID(riid, *aittIidToThi[idx].piid))
+ {
+ return INDEX_IIDIDX(aittIidToThi[idx].iThi);
+ }
+ }
+
+ return IID_IIDIDX(&riid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskMalloc32, public
+//
+// Synopsis: Task allocation for 32-bits
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Temporary until CoTaskMemAlloc is hooked up
+//
+//----------------------------------------------------------------------------
+
+#ifndef COTASK_DEFINED
+LPVOID TaskMalloc32(DWORD cb)
+{
+ IMalloc *pm;
+ LPVOID pv;
+
+ if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
+ {
+ return NULL;
+ }
+ else
+ {
+ pv = pm->Alloc(cb);
+ pm->Release();
+ }
+ return pv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskFree32, public
+//
+// Synopsis: Task free for 32-bits
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Temporary until CoTaskMemAlloc is hooked up
+//
+//----------------------------------------------------------------------------
+
+void TaskFree32(LPVOID pv)
+{
+ IMalloc *pm;
+
+ if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
+ {
+ thkAssert(!"CoGetMalloc failed");
+ }
+ else
+ {
+ pm->Free(pv);
+ pm->Release();
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskMalloc16, public
+//
+// Synopsis: Allocates 16-bit task memory
+//
+// Arguments: [uiSize] - Amount of memory to allocate
+//
+// Returns: VPVOID for memory allocated
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD TaskMalloc16( UINT uiSize )
+{
+ return CallbackTo16(gdata16Data.fnTaskAlloc, uiSize);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskFree16, public
+//
+// Synopsis: Frees 16-bit task memory
+//
+// Arguments: [vpvoid] - VPVOID of allocated memory
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void TaskFree16( DWORD vpvoid )
+{
+ CallbackTo16(gdata16Data.fnTaskFree, vpvoid);
+}
+
+// List of 16/32 HRESULT mappings for mapping functions
+struct SHrMapping
+{
+ HRESULT hr16;
+ HRESULT hr32;
+};
+
+// Since we're including 32-bit headers in this code we can use
+// the defines for the 32-bit values but we must specify the
+// 16-bit values explicitly
+static SHrMapping hmMappings[] =
+{
+ 0x80000001, E_NOTIMPL,
+ 0x80000002, E_OUTOFMEMORY,
+ 0x80000003, E_INVALIDARG,
+ 0x80000004, E_NOINTERFACE,
+ 0x80000005, E_POINTER,
+ 0x80000006, E_HANDLE,
+ 0x80000007, E_ABORT,
+ 0x80000008, E_FAIL,
+ 0x80000009, E_ACCESSDENIED
+};
+#define NMAPPINGS (sizeof(hmMappings)/sizeof(hmMappings[0]))
+
+#define HR16_ERROR 0x80000000
+#define HR16_MAP_FIRST 1
+#define HR16_MAP_LAST 9
+
+//+---------------------------------------------------------------------------
+//
+// Function: TransformHRESULT_1632, public
+//
+// Synopsis: Translates a 16-bit hresult into a 32-bit hresult
+//
+// Arguments: [hresult] - 16-bit hresult to transform
+//
+// History: 15-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult )
+{
+ ULONG ulIndex;
+
+ // We only map error codes
+ if (hresult & HR16_ERROR)
+ {
+ // The 16-bit HRESULTs to be mapped are known quantities
+ // whose values are sequential, so we can map directly from
+ // the value to an array index
+
+ ulIndex = hresult & ~HR16_ERROR;
+ if (ulIndex >= HR16_MAP_FIRST && ulIndex <= HR16_MAP_LAST)
+ {
+ // Known value, index array to find 32-bit HRESULT
+ return hmMappings[ulIndex-HR16_MAP_FIRST].hr32;
+ }
+ }
+
+ // No mapping found, so return the original
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TransformHRESULT_3216, public
+//
+// Synopsis: Translates a 32-bit hresult into a 16-bit hresult
+//
+// Arguments: [hresult] - 32-bit hresult to transform
+//
+// History: 15-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult )
+{
+ int i;
+ SHrMapping *phm;
+
+ // We don't know the true values of 32-bit HRESULTs since we're
+ // using the defines and they may change, so we have to look up
+ // the hard way
+
+ phm = hmMappings;
+ for (i = 0; i < NMAPPINGS; i++)
+ {
+ if (phm->hr32 == (HRESULT)hresult)
+ {
+ return phm->hr16;
+ }
+
+ phm++;
+ }
+
+ // No mapping found, so return the original
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RecordStackState, public debug
+//
+// Synopsis: Records the current state of the stack
+//
+// Arguments: [psr] - Storage space for information
+//
+// Modifies: [psr]
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void RecordStackState16(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack16();
+ psa->RecordState(psr);
+}
+
+void RecordStackState32(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack32();
+ psa->RecordState(psr);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckStackState, public debug
+//
+// Synopsis: Checks recorded information about the stack against its
+// current state
+//
+// Arguments: [psr] - Recorded information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CheckStackState16(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack16();
+ psa->CheckState(psr);
+}
+
+void CheckStackState32(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack32();
+ psa->CheckState(psr);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_VPSTR_to_LPOLESTR
+//
+// Synopsis: Converts 16-bit VPSTR to 32-bit LPOLESTR pointer
+//
+// Arguments: [vpstr] - VPSTR
+// [lpOleStr] - OLESTR
+// [uiSizeInPlace] - Amount of data available in [lpOleStr]
+// for in-place conversion (in characters, not bytes)
+// including nul
+//
+// Returns: Pointer to LPOLESTR with data
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+LPOLESTR Convert_VPSTR_to_LPOLESTR(
+ THUNKINFO *pti,
+ VPSTR vpstr,
+ LPOLESTR lpOleStr,
+ UINT uiSizeInPlace
+)
+{
+ LPSTR lpstr;
+ UINT uiSize;
+ LPOLESTR lpOleStrResult;
+ UINT cChars;
+
+ // We shouldn't be calling here for null strings
+ thkAssert( vpstr != NULL );
+
+ lpstr = GetStringPtr16(pti, vpstr, CCHMAXSTRING, &uiSize);
+ if ( lpstr == NULL )
+ {
+ //
+ // GetStringPtr will have filled in the pti->scResult
+ //
+ return( NULL );
+ }
+
+ // The string has to have at least one character in it
+ // because it must be null-terminated to be valid
+ thkAssert(uiSize > 0);
+
+ lpOleStrResult = lpOleStr;
+
+ if ( uiSize > uiSizeInPlace )
+ {
+ lpOleStrResult = (LPOLESTR)TaskMalloc32(uiSize*sizeof(OLECHAR));
+ if (lpOleStrResult == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ return NULL;
+ }
+ }
+
+ cChars = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ lpstr,
+ uiSize,
+ lpOleStrResult,
+ uiSize );
+
+ WOWRELVDMPTR(vpstr);
+
+ if ( cChars == 0 )
+ {
+ if (lpOleStrResult != lpOleStr)
+ {
+ TaskFree32(lpOleStrResult);
+ }
+
+ pti->scResult = E_UNEXPECTED;
+ return( NULL );
+ }
+ else
+ {
+ return( lpOleStrResult );
+ }
+}
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_LPOLESTR_to_VPSTR
+//
+// Synopsis: Converts 32-bit LPOLESTR to 16-bit VPSTR pointer
+//
+// Arguments: [lpOleStr] - OLESTR
+// [vpstr] - VPSTR
+// [uiSize32] - Length of OLESTR in characters (not bytes)
+// including nul
+// [uiSize16] - Byte length of buffer referred to by VPSTR
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+// Notes: Always converts in place
+//
+//----------------------------------------------------------------------------
+
+SCODE Convert_LPOLESTR_to_VPSTR(
+ LPCOLESTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16
+)
+{
+ LPSTR lpstr;
+ UINT cChars;
+ SCODE sc;
+
+ sc = S_OK;
+
+ lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
+
+ cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ lpOleStr,
+ uiSize32,
+ lpstr,
+ uiSize16,
+ NULL,
+ NULL );
+
+ if ( cChars == 0 && uiSize32 != 0 )
+ {
+ sc = E_UNEXPECTED;
+ }
+
+ WOWRELVDMPTR(vpstr);
+
+ return sc;
+}
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_LPSTR_to_VPSTR
+//
+// Synopsis: Converts 32-bit LPSTR to 16-bit VPSTR pointer
+//
+// Arguments: [lpOleStr] - LPSTR
+// [vpstr] - VPSTR
+// [uiSize32] - Length of LPSTR in bytes including nul
+// [uiSize16] - Byte length of buffer referred to by VPSTR
+//
+// Returns: Appropriate status code
+//
+// History: 10-21-95 KevinRo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE Convert_LPSTR_to_VPSTR(
+ LPCSTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16
+)
+{
+ LPSTR lpstr;
+
+ lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
+
+ memcpy(lpstr,lpOleStr,uiSize32);
+
+ WOWRELVDMPTR(vpstr);
+
+ return S_OK;
+}
+#endif // _CHICAGO_
+
+// Selector bit constants
+#define SEL_TI 0x0004
+#define SEL_RPL 0x0003
+#define SEL_INDEX 0xfff8
+
+#define IS_LDT_SELECTOR(sel) (((sel) & SEL_TI) == SEL_TI)
+
+// LDT bit constants
+#define LTYPE_APP 0x0010
+#define LTYPE_CODE 0x0008
+#define LTYPE_CREAD 0x0002
+#define LTYPE_DDOWN 0x0004
+#define LTYPE_DWRITE 0x0002
+
+// Pointer access types, or'able
+// Defined to be the same as thop in/out so that no translation
+// is necessary for checks on thop memory access
+#define PACC_READ THOP_IN
+#define PACC_WRITE THOP_OUT
+#define PACC_CODE 1 // Special for CODE PTRs
+
+// Information about a VDM pointer
+typedef struct _VPTRDESC
+{
+ BYTE *pbFlat;
+ DWORD dwLengthLeft;
+} VPTRDESC;
+
+// VDM memory is always zero-based on Win95
+#ifndef _CHICAGO_
+DWORD dwBaseVDMMemory = 0xFFFFFFFF;
+#else
+#define dwBaseVDMMemory 0
+#endif
+
+// Extended success returns from GetPtr16Description
+#define S_GDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+#define S_SYSLDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 2)
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetPtr16Description, public
+//
+// Synopsis: Validates access for a VDM pointer and returns
+// information about it
+// Also forces not-present segments into memory by
+// touching them
+//
+// Arguments: [vp] - VDM pointer
+// [grfAccess] - Desired access
+// [dwSize] - Desired size of access, must be >= 1
+// [pvpd] - VPTRDESC out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pvpd]
+//
+// History: 26-Apr-94 DrewB Created
+//
+// Notes: Returns fixed memory
+//
+//----------------------------------------------------------------------------
+
+SCODE GetPtr16Description(VPVOID vp,
+ WORD grfAccess,
+ DWORD dwSize,
+ VPTRDESC *pvpd)
+{
+ VDMLDT_ENTRY *vle;
+#if defined(_CHICAGO_)
+ VDMLDT_ENTRY LdtEntry;
+#endif
+ WORD wSel;
+ WORD wOff;
+ DWORD dwLength;
+
+ thkAssert(vp != 0);
+ thkAssert(dwSize > 0);
+ thkAssert(grfAccess != 0);
+
+ wSel = (WORD)(vp >> 16);
+ wOff = (WORD)(vp & 0xffff);
+
+ pvpd->dwLengthLeft = 0xffff-wOff+1; // Default length remaining
+
+ if (!IS_LDT_SELECTOR(wSel))
+ {
+ // According to the WOW developers, the only GDT selector
+ // is for the BIOS data area so we should never see one
+
+ thkDebugOut((DEB_ERROR, "GDT selector: 0x%04X\n", wSel));
+
+ // Handle it just in case
+ pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
+
+ return S_GDTENTRY;
+ }
+
+#if defined(_CHICAGO_)
+ vle = &LdtEntry;
+ if (!WOWGetDescriptor(vp, vle))
+ {
+ return E_INVALIDARG;
+ }
+#else
+ vle = (VDMLDT_ENTRY *)((BYTE *)(ExpLdt)+(wSel & SEL_INDEX));
+#endif
+
+ if ((vle->HighWord.Bits.Type & LTYPE_APP) == 0)
+ {
+ // According to the WOW developers, they don't use
+ // system segments so we should never see one
+
+ thkDebugOut((DEB_ERROR, "System descriptor: 0x%04X\n", wSel));
+
+ // Handle it just in case
+ pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
+
+ return S_SYSLDTENTRY;
+ }
+
+ // Do as much up-front validation as possible
+ // Since the segment may not be present, we are restricted to
+ // only checking the access permissions
+
+ if (vle->HighWord.Bits.Type & LTYPE_CODE)
+ {
+ // Validate access for code segments
+ // Code segments are never writable
+
+ if (((grfAccess & PACC_READ) &&
+ (vle->HighWord.Bits.Type & LTYPE_CREAD) == 0) ||
+ (grfAccess & PACC_WRITE))
+ {
+ return E_INVALIDARG;
+ }
+ }
+ else
+ {
+ // Validate access for data segments
+ // Data segments are always readable never executable
+
+ if (((grfAccess & PACC_WRITE) &&
+ (vle->HighWord.Bits.Type & LTYPE_DWRITE) == 0) ||
+ (grfAccess & PACC_CODE))
+ {
+ return E_INVALIDARG;
+ }
+ }
+
+ // Bring in segment if it's not present
+ if (!vle->HighWord.Bits.Pres)
+ {
+ // We've validated access permissions and segments must
+ // always be at least one byte long so it's safe to
+ // touch the first byte to bring it in
+
+ // On Win95, this will call GlobalFix on the pointer
+ // to ensure that it stays in memory
+ WOWCallback16(gdata16Data.fnTouchPointer16, vp);
+
+#if defined(_CHICAGO_)
+ // Since we only copy the descriptor, recopy it now.
+ WOWGetDescriptor(vp, vle);
+#endif
+
+ thkAssert(vle->HighWord.Bits.Pres);
+ }
+#ifdef _CHICAGO_
+ else
+ {
+ // Lock the LDT entry (as best as we can) by fixing it
+ // This prevents global blocks from being relocated during
+ // heap compaction
+ WOWGetVDMPointerFix(vp, dwSize, TRUE);
+ }
+#endif
+
+
+ dwLength = ((DWORD)vle->LimitLow |
+ ((DWORD)vle->HighWord.Bits.LimitHi << 16))+1;
+ if (vle->HighWord.Bits.Granularity)
+ {
+ // 4K granularity
+ dwLength <<= 12;
+ }
+
+ if ((vle->HighWord.Bits.Type & LTYPE_CODE) ||
+ (vle->HighWord.Bits.Type & LTYPE_DDOWN) == 0)
+ {
+ // Validate length for code and normal data segments
+
+ if (wOff+dwSize > dwLength)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+
+ pvpd->dwLengthLeft = dwLength-wOff;
+ }
+ else
+ {
+ // Expand-down segment
+
+ if (wOff < dwLength)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+
+ // Check for wraparound
+
+ if (vle->HighWord.Bits.Granularity)
+ {
+ // BUGBUG - Compiler - This should be +1, but
+ // the compiler generates a warning about an overflow
+ // in constant arithmetic
+ pvpd->dwLengthLeft = 0xffffffff-wOff;
+ }
+
+ if (dwSize > pvpd->dwLengthLeft)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+ }
+
+ // VDM memory is always zero-based on Win95
+#ifndef _CHICAGO_
+ if ( dwBaseVDMMemory == 0xFFFFFFFF )
+ {
+ dwBaseVDMMemory = (DWORD)WOWGetVDMPointer(0, 0, FALSE);
+ }
+#endif
+
+ // Translate the pointer even on Win95 because forcing the segment
+ // present may have changed its address
+ pvpd->pbFlat = (BYTE *)(dwBaseVDMMemory +
+ wOff +
+ ( (DWORD)vle->BaseLow |
+ ( (DWORD)vle->HighWord.Bytes.BaseMid << 16) |
+ ( (DWORD)vle->HighWord.Bytes.BaseHi << 24) ) );
+
+#if DBG == 1
+ if (pvpd->pbFlat != WOWGetVDMPointer(vp, dwSize, TRUE))
+ {
+ thkDebugOut((DEB_ERROR, "GetPtr16Description: "
+ "%p computed, %p system\n",
+ pvpd->pbFlat, WOWGetVDMPointer(vp, dwSize, TRUE)));
+ }
+#endif
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetReadPtr16
+//
+// Synopsis: Validates a 16-bit pointer for reading and converts it into
+// a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetReadPtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_READ, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetWritePtr16
+//
+// Synopsis: Validates a 16-bit pointer for writing and converts it into
+// a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetWritePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_WRITE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCodePtr16
+//
+// Synopsis: Validates a 16-bit pointer for execution and converts it
+// into a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetCodePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_CODE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetReadWritePtr16
+//
+// Synopsis: Validates a 16-bit pointer for reading and writing and
+// converts it into a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetReadWritePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_READ | PACC_WRITE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetStringPtr16
+//
+// Synopsis: Validates a 16-bit pointer to a string for reading and
+// converts it (the pointer) into a flat 32 pointer. It also
+// returns the length, since it has to compute it anyway.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [cchMax] - Maximum legal length
+// [lpSize] - Place to return length
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+CHAR *
+GetStringPtr16(
+ THUNKINFO *pti,
+ VPSTR vp,
+ UINT cchMax,
+ PUINT lpSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ // Check the first byte to ensure read access to the segment
+ sc = GetPtr16Description(vp, PACC_READ, 1, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ UINT cchLen;
+ BYTE *pb;
+ BOOL fMbLead;
+
+ pb = vpd.pbFlat;
+
+ if (pb == NULL)
+ {
+ goto Exit;
+ }
+
+
+ // Restrict zero-termination search to cchMax characters
+ // or valid remaining memory
+ // Since we specified one in GetPtr16Description, dwLengthLeft
+ // is one off here
+ cchMax = min(cchMax, vpd.dwLengthLeft+1);
+
+ cchLen = 0;
+ fMbLead = FALSE;
+ while (cchMax > 0)
+ {
+ cchLen++;
+
+ if (*pb == 0 && !fMbLead)
+ {
+ break;
+ }
+ else
+ {
+ fMbLead = (BOOL)g_abLeadTable[*pb++];
+ cchMax--;
+ }
+ }
+
+ if (cchMax > 0)
+ {
+ *lpSize = cchLen;
+ return (LPSTR)vpd.pbFlat;
+ }
+
+Exit:
+ {
+ pti->scResult = E_INVALIDARG;
+ WOWRELVDMPTR(vp);
+ return NULL;
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ValidatePtr16, public
+//
+// Synopsis: Calls an appropriate validation routine for 16-bit
+// memory based on in/out status
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [vp16] - 16-bit pointer
+// [dwSize] - Size
+// [thopInOut] - In/out type
+//
+// Returns: Pointer or NULL
+//
+// Modifies: [pti]->scResult for errors
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: 0 - No validation
+// THOP_IN - Read validation
+// THOP_OUT - Write validation
+// THOP_INOUT - Read/write validation
+//
+//----------------------------------------------------------------------------
+
+VOID *
+ValidatePtr16(THUNKINFO *pti,
+ VPVOID vp16,
+ DWORD dwSize,
+ THOP thopInOut)
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ thopInOut &= THOP_INOUT;
+ if (thopInOut != 0)
+ {
+ sc = GetPtr16Description(vp16, thopInOut, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+ }
+ else
+ {
+ return WOWFIXVDMPTR(vp16, dwSize);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsValidInterface16, public
+//
+// Synopsis: Validates that a provided 16-bit interface is really valid
+// (uses the same validation technique as 16-bit OLE 2.01)
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [vp16] - 16-bit pointer
+//
+// Returns: BOOL - true for valid, false for invalid
+//
+// Modifies: [pti]->scResult for errors
+//
+// History: 22-Jul-92 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp )
+{
+ VPVOID UNALIGNED *pvpv;
+ VPVOID vpvtbl;
+ VPVOID vpfn;
+ LPVOID lpfn;
+
+ //
+ // Make sure we can read the vtbl pointer from the object.
+ //
+ pvpv = (VPVOID FAR *)GetReadPtr16(pti, vp, sizeof(VPVOID));
+ if ( pvpv == NULL )
+ {
+ thkDebugOut((DEB_WARN, "IsValidInterface16: "
+ "Interface ptr invalid %p\n", vp));
+ return FALSE;
+ }
+
+ vpvtbl = *pvpv; // Read the vtbl ptr
+
+ WOWRELVDMPTR(vp);
+
+ // Make sure we can read the first entry from the vtbl (QI)
+
+ pvpv = (VPVOID FAR *)GetReadPtr16(pti, vpvtbl, sizeof(VPVOID));
+ if ( pvpv == NULL )
+ {
+ thkDebugOut((DEB_WARN, "Vtbl ptr invalid %p:%p\n", vp, vpvtbl));
+ return FALSE;
+ }
+
+ vpfn = *pvpv; // Get the QI Function
+
+ WOWRELVDMPTR(vpvtbl);
+
+ if ( vpfn == 0 )
+ {
+ thkDebugOut((DEB_WARN, "QI function NULL %p:%p\n", vp, vpvtbl));
+ pti->scResult = E_INVALIDARG;
+ return FALSE;
+ }
+
+ // Why it has to be 9 bytes long, I have no idea.
+ // This check was taken from valid.cpp in
+ // \src\ole2\dll\src\debug the 16-bit ole2.01
+ // sources...
+ lpfn = (LPVOID)GetCodePtr16(pti, vpfn, 9);
+
+ WOWRELVDMPTR(vpfn);
+
+ if ( lpfn == NULL )
+ {
+ thkDebugOut((DEB_WARN, "QI function ptr invalid %p:%p:%p\n",
+ vp,vpvtbl,vpfn));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GuidString, debug public
+//
+// Synopsis: Converts a guid to a string
+//
+// Arguments: [pguid] - GUID
+//
+// Returns: Pointer to string
+//
+// History: 08-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidString(GUID const *pguid)
+{
+ static char ach[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ wsprintfA(ach, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return ach;
+}
+
+#endif
+
+#if DBG == 1
+ char *apszThopNames[] =
+{
+ "THOP_END",
+ "THOP_SHORTLONG",
+ "THOP_WORDDWORD",
+ "THOP_COPY",
+ "THOP_LPSTR",
+ "THOP_LPLPSTR",
+ "THOP_BUFFER",
+ "THOP_HUSER",
+ "THOP_HGDI",
+ "THOP_SIZE",
+ "THOP_RECT",
+ "THOP_MSG",
+ "THOP_HRESULT",
+ "THOP_STATSTG",
+ "THOP_DVTARGETDEVICE",
+ "THOP_STGMEDIUM",
+ "THOP_FORMATETC",
+ "THOP_HACCEL",
+ "THOP_OIFI",
+ "THOP_BINDOPTS",
+ "THOP_LOGPALETTE",
+ "THOP_SNB",
+ "THOP_CRGIID",
+ "THOP_OLESTREAM",
+ "THOP_HTASK",
+ "THOP_INTERFACEINFO",
+ "THOP_IFACE",
+ "THOP_IFACEOWNER",
+ "THOP_IFACENOADDREF",
+ "THOP_IFACECLEAN",
+ "THOP_IFACEGEN",
+ "THOP_IFACEGENOWNER",
+ "THOP_ROUTINEINDEX",
+ "THOP_RETURNTYPE",
+ "THOP_NULL",
+ "THOP_ERROR",
+ "THOP_ENUM",
+ "THOP_CALLBACK",
+ "THOP_RPCOLEMESSAGE",
+ "THOP_ALIAS32",
+ "THOP_CLSCONTEXT",
+ "THOP_FILENAME",
+ "THOP_SIZEDSTRING"
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThopName, debug public
+//
+// Synopsis: Returns the string name of a thop
+//
+// Arguments: [thop] - Thop
+//
+// Returns: Pointer to string
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *ThopName(THOP thop)
+{
+ static char achString[80];
+ char *psz;
+
+ thkAssert((thop & THOP_OPMASK) < THOP_LASTOP);
+ thkAssert(THOP_LASTOP ==
+ (sizeof(apszThopNames)/sizeof(apszThopNames[0])));
+
+ strcpy(achString, apszThopNames[thop & THOP_OPMASK]);
+
+ psz = achString+strlen(achString);
+ if (thop & THOP_IN)
+ {
+ strcpy(psz, " | THOP_IN");
+ psz += strlen(psz);
+ }
+ if (thop & THOP_OUT)
+ {
+ strcpy(psz, " | THOP_OUT");
+ }
+
+ return achString;
+}
+#endif
+
+#if DBG == 1
+ char *apszEnumThopNames[] =
+{
+ "STRING",
+ "UNKNOWN",
+ "STATSTG",
+ "FORMATETC",
+ "STATDATA",
+ "MONIKER",
+ "OLEVERB"
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: EnumThopName, debug public
+//
+// Synopsis: Returns the string name of an enum thop
+//
+// Arguments: [thopEnum] - Thop
+//
+// Returns: Pointer to string
+//
+// History: 11-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *EnumThopName(THOP thopEnum)
+{
+ thkAssert(thopEnum <
+ (sizeof(apszEnumThopNames)/sizeof(apszEnumThopNames[0])));
+ return apszEnumThopNames[thopEnum];
+}
+#endif
+
+#if DBG == 1
+// Maintain current thunking invocation nesting level
+int _iThunkNestingLevel = 1;
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: NestingSpaces, debug public
+//
+// Synopsis: Spaces for each nesting level
+//
+// History: 22-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#define NESTING_SPACES 32
+#define SPACES_PER_LEVEL 2
+
+static char achSpaces[NESTING_SPACES+1] = " ";
+
+void NestingSpaces(char *psz)
+{
+ int iSpaces, i;
+
+ iSpaces = _iThunkNestingLevel*SPACES_PER_LEVEL;
+
+ while (iSpaces > 0)
+ {
+ i = min(iSpaces, NESTING_SPACES);
+ memcpy(psz, achSpaces, i);
+ psz += i;
+ *psz = 0;
+ iSpaces -= i;
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: NestingLevelString, debug public
+//
+// Synopsis: Provides a string describing the nesting level
+//
+// History: 22-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *NestingLevelString(void)
+{
+ static char ach[256];
+ char *psz;
+
+ if ((thkInfoLevel & DEB_NESTING) == 0)
+ {
+ return "";
+ }
+
+ wsprintfA(ach, "%2d:", _iThunkNestingLevel);
+ psz = ach+strlen(ach);
+
+ if (sizeof(ach)/SPACES_PER_LEVEL <= _iThunkNestingLevel)
+ {
+ strcpy(psz, "...");
+ }
+ else
+ {
+ NestingSpaces(psz);
+ }
+ return ach;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidOrInterfaceString, debug public
+//
+// Synopsis: Returns the interface name for known interfaces or
+// the IID string itself
+//
+// Arguments: [piid] - IID
+//
+// Returns: char *
+//
+// History: 18-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *IidOrInterfaceString(IID const *piid)
+{
+ return IidIdxString(IidToIidIdx(*piid));
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidIdxString, debug public
+//
+// Synopsis: Returns the interface name for known interfaces or
+// the IID string itself
+//
+// Arguments: [iidx] - IID or index
+//
+// Returns: char *
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *IidIdxString(IIDIDX iidx)
+{
+ if (IIDIDX_IS_IID(iidx))
+ {
+ return GuidString(IIDIDX_IID(iidx));
+ }
+ else if (IIDIDX_INDEX(iidx) == THI_COUNT)
+ {
+ // Special case here because of IMalloc's unusual unthunked-
+ // but-indexed existence
+ return "IMalloc";
+ }
+ else
+ {
+ return inInterfaceNames[IIDIDX_INDEX(iidx)].pszInterface;
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Handler routines, public
+//
+// Synopsis: Generic conversion routines for the generic thop handler
+//
+// Arguments: [pbFrom] - Data to convert from
+// [pbTo] - Buffer to convert into
+// [cbFrom] - Size of source data
+// [cbTo] - Size of destination data
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhCopyMemory, public
+//
+// Synopsis: Handler routine for memory copies
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == cbTo);
+
+ memcpy(pbTo, pbFrom, cbFrom);
+
+#if DBG == 1
+ if (cbFrom == sizeof(DWORD))
+ {
+ thkDebugOut((DEB_ARGS, "Arg DWORD: 0x%08lX\n",
+ *(DWORD UNALIGNED *)pbFrom));
+ }
+ else if (cbFrom == sizeof(LARGE_INTEGER))
+ {
+ thkDebugOut((DEB_ARGS, "Arg 8 byte: 0x%08lX:%08lX\n",
+ *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
+ }
+ else if (cbFrom == sizeof(GUID))
+ {
+ thkDebugOut((DEB_ARGS, "Arg 16 byte: 0x%08lX:%08lX:%08lX:%08lX\n",
+ *(DWORD UNALIGNED *)(pbFrom+3*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+2*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Arg %d byte copy\n", cbFrom));
+ }
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhShortToLong, FhLongToShort, public
+//
+// Synopsis: Signed int conversion
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(SHORT));
+ thkAssert(cbTo == sizeof(LONG));
+
+ *(LONG UNALIGNED *)pbTo = (LONG)*(SHORT UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "ShToLo %d -> %d\n",
+ *(SHORT UNALIGNED *)pbFrom, *(LONG UNALIGNED *)pbTo));
+}
+
+void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(LONG));
+ thkAssert(cbTo == sizeof(SHORT));
+
+ // Not used in situations where clamping is meaningful
+ *(SHORT UNALIGNED *)pbTo = (SHORT)*(LONG UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "LoToSh %d -> %d\n",
+ *(LONG UNALIGNED *)pbFrom, *(SHORT UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhWordToDword, FhDwordToWord, public
+//
+// Synopsis: Handler routine for memory copies
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(WORD));
+ thkAssert(cbTo == sizeof(DWORD));
+
+ *(DWORD UNALIGNED *)pbTo = (DWORD)*(WORD UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "WoToDw 0x%04lX -> 0x%08lX\n",
+ *(WORD UNALIGNED *)pbFrom, *(DWORD UNALIGNED *)pbTo));
+}
+
+void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(DWORD));
+ thkAssert(cbTo == sizeof(WORD));
+
+ // Not used in situations where clamping is meaningful
+ *(WORD UNALIGNED *)pbTo = (WORD)*(DWORD UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "DwToWo 0x%08lX -> 0x%04lX\n",
+ *(DWORD UNALIGNED *)pbFrom, *(WORD UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Handle routines, public
+//
+// Synopsis: Handler routine for Windows handles
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ *(HBITMAP *)pbTo = HBITMAP_32(*(HBITMAP16 UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HGdi: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HBITMAP_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HGdi: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ // Even though the constant is WOW_TYPE_FULLHWND, it
+ // works for any user handle
+
+ *(HANDLE *)pbTo = WOWHandle32(*(HAND16 UNALIGNED *)pbFrom,
+ WOW_TYPE_FULLHWND);
+
+ thkDebugOut((DEB_ARGS, "1632 HUser: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HWND_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HUser: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ *(HANDLE *)pbTo = HACCEL_32(*(HAND16 UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HACCEL: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HACCEL_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HACCEL: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ HAND16 h16;
+ DWORD h32;
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ h16 = *(HAND16 UNALIGNED *)pbFrom;
+ if ( h16 == 0 )
+ {
+ h32 = 0;
+ }
+ else
+ {
+ h32 = HTASK_32(h16);
+ }
+ *(DWORD *)pbTo = h32;
+
+ thkDebugOut((DEB_ARGS, "1632 HTASK: 0x%04lX -> 0x%p\n", h16, h32));
+}
+
+void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ HAND16 h16;
+ HANDLE h32;
+
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ h32 = *(HANDLE *)pbFrom;
+ if ( h32 == NULL )
+ {
+ h16 = 0;
+ }
+ else
+ {
+ h16 = HTASK_16(h32);
+ }
+ *(HAND16 UNALIGNED *)pbTo = h16;
+
+ thkDebugOut((DEB_ARGS, "3216 HTASK: 0x%p -> 0x%04lX\n",h32, h16));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: HRESULT routines, public
+//
+// Synopsis: Handler routine for HRESULTs
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HRESULT));
+ thkAssert(cbTo == sizeof(HRESULT));
+
+ *(HRESULT *)pbTo = TransformHRESULT_1632(*(HRESULT UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HRESULT: 0x%08lX -> 0x%08lX\n",
+ *(HRESULT UNALIGNED *)pbFrom, *(HRESULT *)pbTo));
+}
+
+void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HRESULT));
+ thkAssert(cbTo == sizeof(HRESULT));
+
+ *(HRESULT UNALIGNED *)pbTo = TransformHRESULT_3216(*(HRESULT *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HRESULT: 0x%08lX -> 0x%08lX\n",
+ *(HRESULT *)pbFrom, *(HRESULT UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NULL routines, public
+//
+// Synopsis: Handler routine for NULL
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(void *));
+ thkAssert(cbTo == sizeof(void *));
+
+ thkDebugOut((DEB_WARN, "FhNull: %p NULL value not NULL\n", pbFrom));
+ *(void UNALIGNED **)pbTo = NULL;
+
+ thkDebugOut((DEB_ARGS, "Arg NULL\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Rect routines, public
+//
+// Synopsis: Handler routines for RECT
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ RECT *pr32;
+ RECT16 UNALIGNED * pr16;
+
+ thkAssert(cbFrom == sizeof(RECT16));
+ thkAssert(cbTo == sizeof(RECT));
+
+ pr16 = (RECT16 UNALIGNED *)pbFrom;
+ pr32 = (RECT *)pbTo;
+
+ pr32->left = (LONG)pr16->left; // Sign extend
+ pr32->top = (LONG)pr16->top; // Sign extend
+ pr32->right = (LONG)pr16->right; // Sign extend
+ pr32->bottom = (LONG)pr16->bottom; // Sign extend
+
+ thkDebugOut((DEB_ARGS, "1632 RECT: {%d, %d, %d, %d}\n",
+ pr32->left, pr32->top, pr32->right, pr32->bottom));
+}
+
+void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ RECT *pr32;
+ RECT16 UNALIGNED *pr16;
+
+ thkAssert(cbFrom == sizeof(RECT));
+ thkAssert(cbTo == sizeof(RECT16));
+
+ pr32 = (RECT *)pbFrom;
+ pr16 = (RECT16 UNALIGNED *)pbTo;
+
+ pr16->left = ClampLongToShort(pr32->left);
+ pr16->top = ClampLongToShort(pr32->top);
+ pr16->right = ClampLongToShort(pr32->right);
+ pr16->bottom = ClampLongToShort(pr32->bottom);
+
+ thkDebugOut((DEB_ARGS, "3216 RECT: {%d, %d, %d, %d}\n",
+ pr32->left, pr32->top, pr32->right, pr32->bottom));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Size routines, public
+//
+// Synopsis: Handler routines for SIZE
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ SIZE16 UNALIGNED *psize16;
+ SIZE *psize32;
+
+ thkAssert(cbFrom == sizeof(SIZE16));
+ thkAssert(cbTo == sizeof(SIZE));
+
+ psize16 = (SIZE16 UNALIGNED *)pbFrom;
+ psize32 = (SIZE *)pbTo;
+
+ psize32->cx = (LONG)psize16->cx;
+ psize32->cy = (LONG)psize16->cy;
+
+ thkDebugOut((DEB_ARGS, "1632 SIZE: {%d, %d}\n",
+ psize32->cx, psize32->cy));
+}
+
+void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ SIZE16 UNALIGNED *psize16;
+ SIZE *psize32;
+
+ thkAssert(cbFrom == sizeof(SIZE));
+ thkAssert(cbTo == sizeof(SIZE16));
+
+ psize32 = (SIZE *)pbFrom;
+ psize16 = (SIZE16 UNALIGNED *)pbTo;
+
+ psize16->cx = ClampLongToShort(psize32->cx);
+ psize16->cy = ClampLongToShort(psize32->cy);
+
+ thkDebugOut((DEB_ARGS, "3216 SIZE: {%d, %d}\n",
+ psize32->cx, psize32->cy));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Message routines, public
+//
+// Synopsis: Handler routines for MSG
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ MSG16 UNALIGNED *pmsg16;
+ MSG *pmsg32;
+
+ thkAssert(cbFrom == sizeof(MSG16));
+ thkAssert(cbTo == sizeof(MSG));
+
+ pmsg16 = (MSG16 UNALIGNED *)pbFrom;
+ pmsg32 = (MSG *)pbTo;
+
+ pmsg32->hwnd = HWND_32(pmsg16->hwnd);
+ pmsg32->message = (UINT)pmsg16->message;
+ pmsg32->wParam = (WPARAM)pmsg16->wParam; // Should we sign extend?
+ pmsg32->lParam = (LPARAM)pmsg16->lParam;
+ pmsg32->time = pmsg16->time;
+ pmsg32->pt.x = (LONG)(SHORT)LOWORD(pmsg16->pt); // Sign extend
+ pmsg32->pt.y = (LONG)(SHORT)HIWORD(pmsg16->pt); // Sign extend
+
+ thkDebugOut((DEB_ARGS, "1632 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
+ "0x%08lX, {%d, %d}}\n",
+ pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
+ pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
+ pmsg32->pt.y));
+}
+
+void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ MSG16 UNALIGNED *pmsg16;
+ MSG *pmsg32;
+
+ thkAssert(cbFrom == sizeof(MSG));
+ thkAssert(cbTo == sizeof(MSG16));
+
+ pmsg32 = (MSG *)pbFrom;
+ pmsg16 = (MSG16 UNALIGNED *)pbTo;
+
+ pmsg16->hwnd = HWND_16(pmsg32->hwnd);
+ pmsg16->message = (WORD)pmsg32->message;
+ pmsg16->wParam = (WORD)pmsg32->wParam; // Sign truncate
+ pmsg16->lParam = (LONG)pmsg32->lParam;
+ pmsg16->time = pmsg32->time;
+ pmsg16->pt = MAKELONG(ClampLongToShort(pmsg32->pt.x),
+ ClampLongToShort(pmsg32->pt.y));
+
+ thkDebugOut((DEB_ARGS, "3216 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
+ "0x%08lX, {%d, %d}}\n",
+ pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
+ pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
+ pmsg32->pt.y));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ALLOCROUTINE, public
+//
+// Synopsis: A routine which allocates memory
+//
+// Arguments: [cb] - Amount to allocate
+//
+// Returns: Pointer to memory
+//
+// History: 19-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: FREEROUTINE, public
+//
+// Synopsis: A routine which frees memory
+//
+// Arguments: [pv] - Memory to free
+// [cb] - Size of memory to free
+//
+// History: 19-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void *ArTask16(UINT cb)
+{
+ return (void *)TaskMalloc16(cb);
+}
+
+void FrTask16(void *pv, UINT cb)
+{
+ TaskFree16((VPVOID)pv);
+}
+
+void *ArTask32(UINT cb)
+{
+ return TaskMalloc32(cb);
+}
+
+void FrTask32(void *pv, UINT cb)
+{
+ TaskFree32(pv);
+}
+
+void *ArStack16(UINT cb)
+{
+ return (void *)STACKALLOC16(cb);
+}
+
+void FrStack16(void *pv, UINT cb)
+{
+ STACKFREE16((VPVOID)pv, cb);
+}
+
+void *ArStack32(UINT cb)
+{
+ // Can't use STACKALLOC32 on NT since it may be _alloca which wouldn't
+ // live beyond this routine
+#ifdef _CHICAGO_
+ return STACKALLOC32(cb);
+#else
+ return (void *)LocalAlloc(LMEM_FIXED, cb);
+#endif
+}
+
+void FrStack32(void *pv, UINT cb)
+{
+#ifdef _CHICAGO_
+ STACKFREE32(pv, cb);
+#else
+ LocalFree(pv);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertDvtd1632, private
+//
+// Synopsis: Converts a DVTARGETDEVICE from 16 to 32-bits
+//
+// Arguments: [pti] - Thunking state information
+// [vpdvtd16] - Source
+// [pfnAlloc] - ALLOCROUTINE
+// [pfnFree] - FREEROUTINE
+// [ppdvtd32] - Destination
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdvtd32]
+// [pcbSize]
+//
+// History: 18-Apr-94 DrewB Created
+//
+// Notes: [pfnAlloc/Free] must deal with 32-bit memory
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertDvtd1632(THUNKINFO *pti,
+ VPVOID vpdvtd16,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ DVTARGETDEVICE **ppdvtd32,
+ UINT *pcbSize)
+{
+ DVTARGETDEVICE UNALIGNED *pdvtd16;
+ DVTARGETDEVICE *pdvtd32;
+ DVTDINFO dvtdi;
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
+ sizeof(DVTARGETDEVICE));
+ if (pdvtd16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
+ pdvtd16->tdSize);
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if (pdvtd16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ pti->scResult = UtGetDvtd16Info( pdvtd16, &dvtdi );
+
+ if ( FAILED(pti->scResult) )
+ {
+ WOWRELVDMPTR(vpdvtd16);
+ return pti->scResult;
+ }
+
+ pdvtd32 = (DVTARGETDEVICE *)pfnAlloc(dvtdi.cbConvertSize);
+ if (pdvtd32 == NULL)
+ {
+ WOWRELVDMPTR(vpdvtd16);
+ return E_OUTOFMEMORY;
+ }
+
+ pti->scResult = UtConvertDvtd16toDvtd32( pdvtd16, &dvtdi, pdvtd32 );
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if ( FAILED(pti->scResult) )
+ {
+ pfnFree(pdvtd32, dvtdi.cbConvertSize);
+ return pti->scResult;
+ }
+
+ *ppdvtd32 = pdvtd32;
+ *pcbSize = dvtdi.cbConvertSize;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertDvtd3216, private
+//
+// Synopsis: Converts a DVTARGETDEVICE from 32 to 16-bits
+//
+// Arguments: [pti] - Thunking state information
+// [pdvtd32] - Source
+// [pfnAlloc] - Allocator
+// [pfnFree] - Freer
+// [ppvdvtd16] - Destination
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvdvtd16]
+// [pcbSize]
+//
+// History: 18-Apr-94 DrewB Created
+//
+// Notes: [pfnAlloc/Free] must deal with 16-bit memory
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertDvtd3216(THUNKINFO *pti,
+ DVTARGETDEVICE *pdvtd32,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ VPVOID *ppvdvtd16,
+ UINT *pcbSize)
+{
+ DVTARGETDEVICE UNALIGNED *pdvtd16;
+ VPVOID vpdvtd16;
+ DVTDINFO dvtdi;
+
+ if (IsBadReadPtr(pdvtd32, sizeof(DVTARGETDEVICE)) ||
+ IsBadReadPtr(pdvtd32, pdvtd32->tdSize))
+ {
+ return E_INVALIDARG;
+ }
+
+ pti->scResult = UtGetDvtd32Info( pdvtd32, &dvtdi );
+
+ if ( FAILED(pti->scResult) )
+ {
+ return pti->scResult;
+ }
+
+ vpdvtd16 = (VPVOID)pfnAlloc(dvtdi.cbConvertSize);
+ if (vpdvtd16 == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)WOWFIXVDMPTR(vpdvtd16,
+ dvtdi.cbConvertSize);
+
+ pti->scResult = UtConvertDvtd32toDvtd16( pdvtd32, &dvtdi, pdvtd16 );
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if ( FAILED(pti->scResult) )
+ {
+ pfnFree((void *)vpdvtd16, dvtdi.cbConvertSize);
+ return pti->scResult;
+ }
+
+ *ppvdvtd16 = vpdvtd16;
+ *pcbSize = dvtdi.cbConvertSize;
+
+ return S_OK;
+}
+
+#if !defined(_CHICAGO_)
+
+SCODE ConvertHDrop1632(HMEM16 hg16, HGLOBAL* phg32)
+{
+ SCODE sc = S_OK;
+
+ *phg32 = CopyDropFilesFrom16(hg16);
+ if (!*phg32)
+ sc = E_INVALIDARG;
+
+ return sc;
+}
+
+
+SCODE ConvertHDrop3216(HGLOBAL hg32, HMEM16* phg16)
+{
+ SCODE sc = S_OK;
+
+ *phg16 = CopyDropFilesFrom32(hg32);
+ if (!*phg16)
+ sc = E_INVALIDARG;
+
+ return sc;
+}
+
+#endif
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHGlobal1632, public
+//
+// Synopsis: Creates a 32-bit HGLOBAL for a 16-bit HGLOBAL
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [hg16] - 16-bit HGLOBAL
+// [thopInOut] - Validation type
+// [phg32] - 32-bit HGLOBAL in/out
+// [pdwSize] - Size in/out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+// [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: If [phg32] is non-NULL on entry, [pdwSize] must be set
+// appropriately also
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertHGlobal1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ THOP thopInOut,
+ HGLOBAL *phg32,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ VPVOID vpdata16;
+ LPVOID lpdata16;
+ LPVOID lpdata32;
+ HGLOBAL hg32;
+ DWORD dwSize;
+ BOOL fOwn;
+
+ sc = S_OK;
+
+ vpdata16 = WOWGlobalLockSize16( hg16, &dwSize );
+ if ( vpdata16 == 0 )
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ if (*phg32 != 0 && *pdwSize == dwSize)
+ {
+ hg32 = *phg32;
+ fOwn = FALSE;
+ }
+ else
+ {
+ hg32 = GlobalAlloc( GMEM_MOVEABLE, dwSize );
+ fOwn = TRUE;
+ }
+
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpdata32 = GlobalLock( hg32 );
+
+ lpdata16 = (LPVOID)ValidatePtr16(pti, vpdata16, dwSize, thopInOut);
+ if ( lpdata16 != NULL )
+ {
+ memcpy( lpdata32, lpdata16, dwSize );
+ WOWRELVDMPTR(vpdata16);
+ }
+ else
+ {
+ sc = pti->scResult;
+ }
+
+ GlobalUnlock(hg32);
+
+ if (FAILED(sc) && fOwn)
+ {
+ GlobalFree(hg32);
+ }
+ }
+
+ WOWGlobalUnlock16( hg16 );
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (*phg32 != 0 && hg32 != *phg32)
+ {
+ GlobalFree(*phg32);
+ }
+
+ *phg32 = hg32;
+ *pdwSize = dwSize;
+
+ thkDebugOut((DEB_ARGS, "1632 HGLOBAL: 0x%04X -> 0x%p, %u\n",
+ hg16, hg32, dwSize));
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHGlobal3216, public
+//
+// Synopsis: Creates a 16-bit HGLOBAL for a 32-bit HGLOBAL
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [hg32] - 32-bit HGLOBAL
+// [thopInOut] - Validation type
+// [phg16] - 16-bit HGLOBAL in/out
+// [pdwSize] - Size in/out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+// [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: If [phg16] is non-NULL on entry, [pdwSize] must be set
+// appropriately also
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertHGlobal3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ THOP thopInOut,
+ HMEM16 *phg16,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ VPVOID vpdata16;
+ LPVOID lpdata16;
+ LPVOID lpdata32;
+ HMEM16 hg16;
+ DWORD dwSize;
+ BOOL fOwn;
+
+ sc = S_OK;
+
+ dwSize = GlobalSize(hg32);
+ if (dwSize == 0)
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ lpdata32 = GlobalLock(hg32);
+
+ if (*phg16 != 0 && *pdwSize == dwSize)
+ {
+ hg16 = *phg16;
+ vpdata16 = WOWGlobalLock16(hg16);
+ fOwn = FALSE;
+ }
+ else
+ {
+ vpdata16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
+ dwSize, &hg16);
+ fOwn = TRUE;
+ }
+
+ if (vpdata16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpdata16 = (LPVOID)WOWFIXVDMPTR( vpdata16, dwSize );
+ if ( lpdata16 == NULL )
+ {
+ sc = E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( lpdata16, lpdata32, dwSize );
+
+ WOWRELVDMPTR(vpdata16);
+ }
+
+ WOWGlobalUnlock16( hg16 );
+
+ if (FAILED(sc) && fOwn)
+ {
+ WOWGlobalFree16(hg16);
+ }
+ }
+
+ GlobalUnlock(hg32);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (*phg16 != 0 && hg16 != *phg16)
+ {
+ WOWGlobalFree16(*phg16);
+ }
+
+ *phg16 = hg16;
+ *pdwSize = dwSize;
+
+ thkDebugOut((DEB_ARGS, "3216 HGLOBAL: 0x%p -> 0x%04X, %u\n",
+ hg32, hg16, dwSize));
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertMfPict1632, public
+//
+// Synopsis: Converts a 16-bit METAFILEPICT to 32-bit
+//
+// Arguments: [pti] - Thunk info
+// [hg16] - 16-bit HGLOBAL containing METAFILEPICT
+// [phg32] - 32-bit HGLOBAL return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ SCODE ConvertMfPict1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ HGLOBAL *phg32)
+{
+ SCODE sc;
+ VPVOID vpmfp16;
+ METAFILEPICT16 UNALIGNED *pmfp16;
+ METAFILEPICT *pmfp32;
+ HGLOBAL hg32;
+ DWORD dwSize;
+#if DBG == 1
+ BOOL fSaveToFile = FALSE;
+#endif
+
+ thkDebugOut((DEB_ITRACE, "In ConvertMfPict1632(%p, 0x%04X, %p)\n",
+ pti, hg16, phg32));
+
+ *phg32 = 0;
+ sc = S_OK;
+
+ vpmfp16 = WOWGlobalLockSize16( hg16, &dwSize );
+ if ( vpmfp16 == 0 || dwSize < sizeof(METAFILEPICT16))
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ hg32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pmfp32 = (METAFILEPICT *)GlobalLock( hg32 );
+
+ pmfp16 = (METAFILEPICT16 UNALIGNED *)GetReadPtr16(pti, vpmfp16,
+ dwSize);
+ if ( pmfp16 != NULL )
+ {
+ pmfp32->mm = (LONG)pmfp16->mm;
+ pmfp32->xExt = (LONG)pmfp16->xExt;
+ pmfp32->yExt = (LONG)pmfp16->yExt;
+
+ pmfp32->hMF = HMETAFILE_32(pmfp16->hMF);
+
+ thkDebugOut((DEB_ARGS, "1632 METAFILEPICT: "
+ "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
+ pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF,
+ pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF));
+
+ WOWRELVDMPTR(vpmfp16);
+
+#if DBG == 1
+ if (fSaveToFile)
+ {
+ HMETAFILE hmf;
+
+ hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
+ if (hmf != NULL)
+ {
+ DeleteMetaFile(hmf);
+ }
+ }
+#endif
+ }
+ else
+ {
+ sc = pti->scResult;
+ }
+
+ GlobalUnlock(hg32);
+
+ if (FAILED(sc))
+ {
+ GlobalFree(hg32);
+ }
+ }
+
+ WOWGlobalUnlock16( hg16 );
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ *phg32 = hg32;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out ConvertMfPict1632 => 0x%08lX, 0x%p\n",
+ sc, *phg32));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertMfPict3216, public
+//
+// Synopsis: Converts a 32-bit METAFILEPICT to 16-bit
+//
+// Arguments: [pti] - Thunk info
+// [hg32] - 32-bit HGLOBAL containing METAFILEPICT
+// [phg16] - 16-bit HGLOBAL return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ SCODE ConvertMfPict3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ HMEM16 *phg16)
+{
+ SCODE sc;
+ VPVOID vpmfp16;
+ METAFILEPICT16 UNALIGNED *pmfp16;
+ METAFILEPICT *pmfp32;
+ DWORD dwSize;
+ HMEM16 hg16;
+#if DBG == 1
+ BOOL fSaveToFile = FALSE;
+#endif
+
+ thkDebugOut((DEB_ITRACE, "In ConvertMfPict3216(%p, 0x%p, %p)\n",
+ pti, hg32, phg16));
+
+ *phg16 = 0;
+ sc = S_OK;
+
+ dwSize = GlobalSize(hg32);
+ pmfp32 = (METAFILEPICT *)GlobalLock(hg32);
+ if (dwSize == 0 || dwSize < sizeof(METAFILEPICT) || pmfp32 == NULL)
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ vpmfp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
+ sizeof(METAFILEPICT16), &hg16);
+ if (vpmfp16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pmfp16 = FIXVDMPTR(vpmfp16, METAFILEPICT16);
+ if ( pmfp16 != NULL )
+ {
+ pmfp16->mm = (SHORT)pmfp32->mm;
+ pmfp16->xExt = ClampLongToShort(pmfp32->xExt);
+ pmfp16->yExt = ClampLongToShort(pmfp32->yExt);
+ pmfp16->hMF = HMETAFILE_16(pmfp32->hMF);
+
+ thkDebugOut((DEB_ARGS, "3216 METAFILEPICT: "
+ "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
+ pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF,
+ pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF));
+
+ RELVDMPTR(vpmfp16);
+
+#if DBG == 1
+ if (fSaveToFile)
+ {
+ HMETAFILE hmf;
+
+ hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
+ if (hmf != NULL)
+ {
+ DeleteMetaFile(hmf);
+ }
+ }
+#endif
+ }
+ else
+ {
+ sc = E_UNEXPECTED;
+ }
+
+ WOWGlobalUnlock16(hg16);
+
+ if (FAILED(sc))
+ {
+ WOWGlobalFree16(hg16);
+ }
+ }
+
+ GlobalUnlock(hg32);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ *phg16 = hg16;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out ConvertMfPict3216 => 0x%08lX, 0x%04X\n",
+ sc, *phg16));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDesc1632, public
+//
+// Synopsis: Converts an OBJECTDESCRIPTOR structure
+//
+// Arguments: [pti] - THUNKINFO
+// [hg16] - HGLOBAL containing structure
+// [phg32] - Output HGLOBAL
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+//
+// History: 04-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertObjDesc1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ HGLOBAL *phg32)
+{
+ SCODE sc;
+ VPVOID vp16;
+ HGLOBAL hg32;
+ DWORD dwSize;
+ OBJECTDESCRIPTOR UNALIGNED *pod16;
+ OBJECTDESCRIPTOR *pod32;
+ char *pszFutn, *pszSoc;
+ UINT cchFutn, cchSoc;
+ UINT cbOffset;
+
+ sc = S_OK;
+
+ vp16 = WOWGlobalLock16(hg16);
+ if ( vp16 == 0 )
+ {
+ return E_INVALIDARG;
+ }
+
+ pszFutn = NULL;
+ pszSoc = NULL;
+
+ pod16 = (OBJECTDESCRIPTOR UNALIGNED *)
+ GetReadPtr16(pti, vp16, sizeof(OBJECTDESCRIPTOR));
+ if (pod16 == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ pszFutn = (char *)GetStringPtr16(pti, vp16+pod16->dwFullUserTypeName,
+ CCHMAXSTRING, &cchFutn);
+ if (pszFutn == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize += cchFutn*sizeof(WCHAR);
+ }
+
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ pszSoc = (char *)GetStringPtr16(pti, vp16+pod16->dwSrcOfCopy,
+ CCHMAXSTRING, &cchSoc);
+ if (pszSoc == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize += cchSoc*sizeof(WCHAR);
+ }
+
+ hg32 = GlobalAlloc(GMEM_MOVEABLE, dwSize);
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ goto EH_Unlock;
+ }
+
+ pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
+ memcpy(pod32, pod16, sizeof(OBJECTDESCRIPTOR));
+ pod32->cbSize = dwSize;
+
+ cbOffset = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pszFutn, cchFutn,
+ (WCHAR *)((BYTE *)pod32+cbOffset),
+ cchFutn) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod32->dwFullUserTypeName = cbOffset;
+ cbOffset += cchFutn*sizeof(WCHAR);
+ }
+
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pszSoc, cchSoc,
+ (WCHAR *)((BYTE *)pod32+cbOffset),
+ cchSoc) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod32->dwSrcOfCopy = cbOffset;
+ cbOffset += cchFutn*sizeof(WCHAR);
+ }
+
+#if DBG == 1
+ WCHAR *pwcsFutn, *pwcsSoc;
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
+ }
+ else
+ {
+ pwcsFutn = NULL;
+ }
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
+ }
+ else
+ {
+ pwcsSoc = NULL;
+ }
+ thkDebugOut((DEB_ARGS, "1632 OBJECTDESCRIPTOR: "
+ "{%d, ..., \"%ws\" (%s), \"%ws\" (%s)} %p -> %p\n",
+ pod32->cbSize, pwcsFutn, pszFutn, pwcsSoc, pszSoc,
+ vp16, pod32));
+#endif
+
+ GlobalUnlock(hg32);
+
+ *phg32 = hg32;
+
+ EH_Unlock:
+ if (pszFutn != NULL)
+ {
+ WOWRELVDMPTR(vp16+pod16->dwFullUserTypeName);
+ }
+ if (pszSoc != NULL)
+ {
+ WOWRELVDMPTR(vp16+pod16->dwSrcOfCopy);
+ }
+ if (pod16 != NULL)
+ {
+ WOWRELVDMPTR(vp16);
+ }
+
+ WOWGlobalUnlock16(hg16);
+
+ return sc;
+
+ EH_Free:
+ GlobalUnlock(hg32);
+ GlobalFree(hg32);
+ goto EH_Unlock;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDesc3216, public
+//
+// Synopsis: Converts an OBJECTDESCRIPTOR structure
+//
+// Arguments: [pti] - THUNKINFO
+// [hg32] - HGLOBAL containing structure
+// [phg16] - Output HGLOBAL
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+//
+// History: 04-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertObjDesc3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ HMEM16 *phg16)
+{
+ SCODE sc;
+ VPVOID vp16;
+ HMEM16 hg16;
+ DWORD dwSize;
+ OBJECTDESCRIPTOR UNALIGNED *pod16;
+ OBJECTDESCRIPTOR *pod32;
+ WCHAR *pwcsFutn, *pwcsSoc;
+ UINT cchFutn, cchSoc;
+ UINT cbOffset;
+
+ sc = S_OK;
+
+ pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
+ if ( pod32 == 0 )
+ {
+ return E_INVALIDARG;
+ }
+
+ if (IsBadReadPtr(pod32, sizeof(OBJECTDESCRIPTOR)))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ dwSize = sizeof(OBJECTDESCRIPTOR);
+
+ pwcsFutn = NULL;
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
+ if (IsBadStringPtrW(pwcsFutn, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ cchFutn = lstrlenW(pwcsFutn)+1;
+ dwSize += cchFutn*2;
+ }
+
+ pwcsSoc = NULL;
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
+ if (IsBadStringPtrW(pwcsSoc, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ cchSoc = lstrlenW(pwcsSoc)+1;
+ dwSize += cchSoc*2;
+ }
+
+ vp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE, dwSize, &hg16);
+ if ( vp16 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ goto EH_Unlock;
+ }
+
+ pod16 = FIXVDMPTR(vp16, OBJECTDESCRIPTOR);
+ memcpy(pod16, pod32, sizeof(OBJECTDESCRIPTOR));
+ pod16->cbSize = dwSize;
+
+ cbOffset = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pwcsFutn, cchFutn,
+ (char *)pod16+cbOffset, 2 * cchFutn,
+ NULL, NULL) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod16->dwFullUserTypeName = cbOffset;
+ cbOffset += cchFutn*2;
+ }
+
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pwcsSoc, cchSoc,
+ (char *)pod16+cbOffset, 2 * cchSoc,
+ NULL, NULL) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod16->dwSrcOfCopy = cbOffset;
+ cbOffset += cchFutn*2;
+ }
+
+#if DBG == 1
+ char *pszFutn, *pszSoc;
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ pszFutn = (char *)((BYTE *)pod16+pod16->dwFullUserTypeName);
+ }
+ else
+ {
+ pszFutn = NULL;
+ }
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ pszSoc = (char *)((BYTE *)pod16+pod16->dwSrcOfCopy);
+ }
+ else
+ {
+ pszSoc = NULL;
+ }
+ thkDebugOut((DEB_ARGS, "3216 OBJECTDESCRIPTOR: "
+ "{%d, ..., \"%s\" (%ws), \"%s\" (%ws)} %p -> %p\n",
+ pod16->cbSize, pszFutn, pwcsFutn, pszSoc, pwcsSoc,
+ pod32, vp16));
+#endif
+
+ RELVDMPTR(vp16);
+
+ WOWGlobalUnlock16(hg16);
+
+ *phg16 = hg16;
+
+ EH_Unlock:
+ GlobalUnlock(hg32);
+
+ return sc;
+
+ EH_Free:
+ WOWGlobalUnlockFree16(vp16);
+ goto EH_Unlock;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSm32ReleaseHandler (srh)
+//
+// Purpose: Provides punkForRelease for 16->32 STGMEDIUM conversion
+//
+// Interface: IUnknown
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CSm32ReleaseHandler : public IUnknown
+{
+public:
+ CSm32ReleaseHandler(void)
+ {
+ _punkForRelease = NULL;
+ }
+ ~CSm32ReleaseHandler(void)
+ {
+ // Clean up proxy if it hasn't already been released
+ if (_punkForRelease)
+ {
+ _pThkMgr->FreeProxy3216((VPVOID)_sm16.pUnkForRelease);
+ }
+ }
+
+ void Init(CThkMgr *pThkMgr,
+ STGMEDIUM UNALIGNED *psm16,
+ STGMEDIUM *psm32,
+ IUnknown *punkForRelease,
+ CLIPFORMAT cfFormat)
+ {
+ // Unfortunately, the MIPS compiler is not smart enough
+ // to do the right thing if we just declare psm16 as UNALIGNED -- it
+ // doesn't recognize that each member of the structure is also
+ // unaligned when it does the structure copy. So...to make
+ // sure we don't generate an alignment fault, we just copy each
+ // member of the structure directly.
+
+ _sm16.tymed = psm16->tymed;
+ _sm16.hGlobal = psm16->hGlobal;
+ _sm16.pUnkForRelease = psm16->pUnkForRelease;
+ _sm32 = *psm32;
+ _punkForRelease = punkForRelease;
+ _cReferences = 1;
+ _cfFormat = cfFormat;
+ _pThkMgr = pThkMgr;
+ }
+
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppv)
+ {
+ if ( IsEqualIID(riid,IID_IUnknown) )
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ STDMETHOD_(ULONG, AddRef)(void)
+ {
+ return InterlockedIncrement(&_cReferences);
+ }
+ STDMETHOD_(ULONG, Release)(void);
+
+private:
+ STGMEDIUM _sm16;
+ STGMEDIUM _sm32;
+ IUnknown *_punkForRelease;
+ CLIPFORMAT _cfFormat;
+ CThkMgr *_pThkMgr;
+
+public:
+ LONG _cReferences;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm32ReleaseHandler::Release, public
+//
+// Synopsis: Frees resources for the 32-bit copy and then
+// passes the ReleaseStgMedium on to 16-bits
+//
+// Returns: Ref count
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSm32ReleaseHandler::Release(void)
+{
+ STGMEDIUM UNALIGNED *psm16;
+ STGMEDIUM *psm32;
+ LONG lRet;
+ SCODE sc;
+ DWORD dwSize;
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet != 0)
+ {
+ return lRet;
+ }
+
+ psm16 = &_sm16;
+ psm32 = &_sm32;
+
+ switch(psm32->tymed)
+ {
+ case TYMED_HGLOBAL:
+ // BUGBUG - Assumption that OBJECTDESCRIPTOR does not need copyback
+ if (!OBJDESC_CF(_cfFormat))
+ {
+ // BUGBUG - Do we ever need to do this?
+ // Is it valid to rely on the contents of the HGLOBAL
+ // at release time?
+
+ // BUGBUG - Is this the right time to copy back?
+
+ Assert(NULL != psm32->hGlobal);
+
+ WOWGlobalLockSize16((HMEM16)psm16->hGlobal, &dwSize);
+ WOWGlobalUnlock16((HMEM16)psm16->hGlobal);
+
+ sc = ConvertHGlobal3216(NULL, psm32->hGlobal, 0,
+ (HMEM16 *)&psm16->hGlobal, &dwSize);
+ // BUGBUG - What happens on errors?
+ thkAssert(SUCCEEDED(sc));
+ }
+
+ GlobalFree(psm32->hGlobal);
+ psm32->hGlobal = NULL;
+ break;
+
+ case TYMED_MFPICT:
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ METAFILEPICT *pmfp32;
+
+ pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
+ DeleteMetaFile(pmfp32->hMF);
+ GlobalUnlock(psm32->hGlobal);
+#endif
+ GlobalFree(psm32->hGlobal);
+ break;
+
+ case TYMED_FILE:
+ // 32-bit handled by ReleaseStgMedium
+ // Clean up 16-bit ourselves
+#ifdef SM_FREE_16BIT_FILENAME
+ // BUGBUG - 16-bit OLE did not free the filename, so we can't
+ // either. This may lead to memory leaks, but there's not
+ // really anything we can do about it
+ TaskFree16((VPVOID)psm16->lpszFileName);
+#endif
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Handled by ReleaseStgMedium and thunked to 16-bits if necessary
+ break;
+
+ case TYMED_GDI:
+ case TYMED_NULL:
+ // Nothing to release
+ break;
+
+ default:
+ thkAssert(!"Unknown tymed in CSm32ReleaseHandler::Release");
+ break;
+ }
+
+ // Call 16-bit Release through proxy
+ ((IUnknown *)_punkForRelease)->Release();
+ _punkForRelease = NULL;
+
+ // Clean up this
+ delete this;
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm16ReleaseHandler::Init, public
+//
+// Synopsis: Initialize class
+//
+// Arguments: [psm32] - 32-bit STGMEDIUM
+// [psm16] - 16-bit STGMEDIUM
+// [vpvUnkForRelease] - Object for punkForRelease
+// [cfFormat] - Clipboard format associated with STGMEDIUM
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CSm16ReleaseHandler::Init(IUnknown *pThkMgr,
+ STGMEDIUM *psm32,
+ STGMEDIUM UNALIGNED *psm16,
+ VPVOID vpvUnkForRelease,
+ CLIPFORMAT cfFormat)
+{
+ _avpfnVtbl = gdata16Data.avpfnSm16ReleaseHandlerVtbl;
+ _sm32 = *psm32;
+
+ // Unfortunately, the MIPS compiler is not smart enough
+ // to do the right thing if we just (ony) declare psm16 as UNALIGNED,
+ // it doesn't recognize that each member of the structure is also
+ // unaligned when it does the structure copy. So...to make
+ // sure we don't generate an alignment fault, we just copy each
+ // member of the structure directly.
+
+ _sm16.tymed = psm16->tymed;
+ _sm16.hGlobal = psm16->hGlobal;
+ _sm16.pUnkForRelease = psm16->pUnkForRelease;
+
+ _vpvUnkForRelease = vpvUnkForRelease;
+ _cReferences = 1;
+ _cfFormat = cfFormat;
+ _pUnkThkMgr = pThkMgr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm16ReleaseHandler::Uninit, public
+//
+// Synopsis: Uninitialize class
+//
+// History: 25-Apr-94 DrewB Created
+//
+// Notes: For cleanup without use only; do not call after
+// the release handler has actually executed Release
+//
+//----------------------------------------------------------------------------
+
+void CSm16ReleaseHandler::Uninit(void)
+{
+ ((CThkMgr *)_pUnkThkMgr)->FreeProxy1632(_sm32.pUnkForRelease);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSm16ReleaseHandler_Release32, public
+//
+// Synopsis: Handles 32-bit portion of cleaning up STGMEDIUMs for
+// punkForRelease
+//
+// Arguments: [psrh] - this
+// [dw1]
+// [dw2]
+//
+// Returns: punkForRelease->Release()
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) CSm16ReleaseHandler_Release32(CSm16ReleaseHandler *psrh,
+ DWORD dw1,
+ DWORD dw2)
+{
+ STGMEDIUM UNALIGNED *psm16;
+ STGMEDIUM *psm32;
+ DWORD dwSize;
+ SCODE sc;
+
+ psm16 = &psrh->_sm16;
+ psm32 = &psrh->_sm32;
+ switch(psm32->tymed)
+ {
+ case TYMED_FILE:
+ // 16-bit code cleaned up the 16-bit name,
+ // now clean up the 32-bit name
+ TaskFree32(psm32->lpszFileName);
+ break;
+
+ case TYMED_HGLOBAL:
+ // BUGBUG - Assumption that OBJECTDESCRIPTOR does not need copyback
+ if (!OBJDESC_CF(psrh->_cfFormat))
+ {
+ // BUGBUG - Do we ever need to do this?
+ // Copy data back and free global memory
+
+ dwSize = GlobalSize(psm32->hGlobal);
+
+ sc = ConvertHGlobal1632(NULL, (HMEM16)psm16->hGlobal, 0,
+ &psm32->hGlobal, &dwSize);
+ // BUGBUG - What happens on errors?
+ thkAssert(SUCCEEDED(sc));
+ }
+
+ WOWGlobalFree16((HMEM16)psm16->hGlobal);
+ break;
+
+ case TYMED_MFPICT:
+ // Untouched in this case
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Handled by ReleaseStgMedium and thunked to 32-bits if necessary
+ break;
+
+ case TYMED_GDI:
+ case TYMED_NULL:
+ // Nothing to release
+ break;
+
+ default:
+ thkAssert(!"Unknown tymed in ReleaseStgMedium32");
+ break;
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStgMed1632, public
+//
+// Synopsis: Converts a 16-bit STGMEDIUM to 32-bits
+//
+// Arguments: [pti] - Thunk info
+// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
+// [psm32] - 32-bit STGMEDIUM to fill in
+// [pfe] - FORMATETC paired with STGMEDIUM or NULL
+// [pdwSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: [pdwSize] is only set for TYMED_HGLOBAL
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStgMed1632(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ CSm32ReleaseHandler *psrh;
+ IUnknown *punkForRelease;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+ HGDIOBJ hGDI = NULL;
+ THKSTATE thkstateSaved;
+
+ psm16 = (STGMEDIUM UNALIGNED *)
+ GetReadPtr16(pti, vpsm16, sizeof(STGMEDIUM));
+ if (psm16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ sc = S_OK;
+
+ psm32->tymed = psm16->tymed;
+
+ vpvUnk = (VPVOID)psm16->pUnkForRelease;
+ WOWRELVDMPTR(vpsm16);
+
+ if (vpvUnk != 0)
+ {
+ // If the storageMedium includes a pUnk and we are passing
+ // ownership via an [in] parameter. Then we need to build
+ // a proxy with a "real" (rather than "local") reference.
+ // Here we trick "FindProxy3216" into believing it
+ // is building an [out] parameter
+ thkstateSaved = pti->pThkMgr->GetThkState();
+ if(fPassingOwnershipIn)
+ {
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
+ }
+
+ punkForRelease = pti->pThkMgr->FindProxy3216(NULL,
+ vpvUnk,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (punkForRelease == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ psrh = new CSm32ReleaseHandler;
+ if (psrh == NULL)
+ {
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ psrh = NULL;
+ }
+ psm32->pUnkForRelease = psrh;
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+
+ // Word 6 insists on treating BITMAPs as HGLOBALS, which is bogus.
+ // If this is the case, just patch the tymed to the correct value
+
+ if (pfe != NULL)
+ {
+ if( (pfe->cfFormat == CF_BITMAP || pfe->cfFormat == CF_PALETTE ) &&
+ psm16->tymed == TYMED_HGLOBAL )
+ {
+ DWORD dw = TlsThkGetAppCompatFlags();
+
+ // if we are in Word 6, then hack the tymed so we thunk the
+ // bitmaps as GDI objects
+
+ if( (dw & OACF_USEGDI ) )
+ {
+ DWORD dwType;
+
+ hGDI = HBITMAP_32((HBITMAP16)psm16->hBitmap);
+
+ // make sure HGDI is either a bitmap or palette
+
+ dwType = GetObjectType(hGDI);
+ if( (pfe->cfFormat == CF_BITMAP && dwType == OBJ_BITMAP) ||
+ (pfe->cfFormat == CF_PALETTE && dwType == OBJ_PAL) )
+ {
+ psm16->tymed = TYMED_GDI;
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "WARNING! invalid bitmap or palette!\n"));
+ hGDI = NULL;
+ }
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING! App trying to transfer a "
+ "bitmap or palette on an HGLOBAL\n"));
+ }
+ }
+ }
+
+ switch( psm16->tymed )
+ {
+ case TYMED_HGLOBAL:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ if (pfe && OBJDESC_CF(pfe->cfFormat))
+ {
+ sc = ConvertObjDesc1632(pti, hmem16, &psm32->hGlobal);
+ }
+#if !defined(_CHICAGO_)
+
+ else if (pfe && pfe->cfFormat == CF_HDROP)
+ {
+ // fix for mapi forms
+ // thunk CF_HDROP passed as HGLOBAL format
+ sc = ConvertHDrop1632(hmem16, &psm32->hGlobal);
+ }
+
+#endif
+ else
+ {
+ psm32->hGlobal = 0;
+ sc = ConvertHGlobal1632(pti, hmem16, THOP_INOUT,
+ &psm32->hGlobal, pdwSize);
+ }
+ break;
+
+ case TYMED_MFPICT:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ sc = ConvertMfPict1632(pti, hmem16, &psm32->hGlobal);
+ break;
+
+ case TYMED_FILE:
+ psm32->lpszFileName =
+ Convert_VPSTR_to_LPOLESTR( pti,
+ (VPVOID)psm16->lpszFileName,
+ NULL, 0 );
+ if (psm32->lpszFileName == NULL)
+ {
+ sc = pti->scResult;
+ }
+ else
+ {
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "1632 TYMED_FILE: '%ws' (%s)\n",
+ psm32->lpszFileName,
+ WOWFIXVDMPTR((VPVOID)psm16->lpszFileName, 0)));
+ WOWRELVDMPTR((VPVOID)psm16->lpszFileName);
+#endif
+ }
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_ISTREAM:
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ psm32->pstm =
+ (LPSTREAM)pti->pThkMgr->FindProxy3216(NULL, vpvUnk,
+ INDEX_IIDIDX(THI_IStream),
+ NULL);
+ if (psm32->pstm == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "1632 TYMED_ISTREAM: %p -> %p\n",
+ vpvUnk, psm32->pstm));
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ psm32->pstg =
+ (LPSTORAGE)pti->pThkMgr->FindProxy3216(NULL, vpvUnk,
+ INDEX_IIDIDX(THI_IStorage),
+ NULL);
+ if (psm32->pstg == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "1632 TYMED_ISTORAGE: %p -> %p\n",
+ vpvUnk, psm32->pstg));
+ }
+ break;
+
+ case TYMED_GDI:
+ // if we're in Word6, then we may have already converted the bitmap
+ // or palette handle
+ if( hGDI == NULL )
+ {
+ psm32->hBitmap = HBITMAP_32((HBITMAP16)psm16->hBitmap);
+ }
+ else
+ {
+ psm32->hBitmap = (HBITMAP)hGDI;
+ }
+
+ thkDebugOut((DEB_ARGS, "1632 TYMED_GDI: 0x%04X -> 0x%p\n",
+ psm16->hBitmap, psm32->hBitmap));
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_NULL:
+ RELVDMPTR(vpsm16);
+ break;
+
+ default:
+ RELVDMPTR(vpsm16);
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ if (FAILED(sc))
+ {
+ delete psrh;
+ }
+ else
+ {
+ if (psrh)
+ {
+ CLIPFORMAT cf;
+
+ if (pfe)
+ {
+ cf = pfe->cfFormat;
+ }
+ else
+ {
+ cf = CF_INVALID;
+ }
+ psrh->Init(pti->pThkMgr, FIXVDMPTR(vpsm16, STGMEDIUM), psm32,
+ punkForRelease, cf);
+ RELVDMPTR(vpsm16);
+ }
+
+#if DBG == 1
+ if (pfe)
+ {
+ thkDebugOut((DEB_ARGS, "1632 STGMEDIUM FORMATETC %p {%d}\n",
+ pfe, pfe->cfFormat));
+ }
+ thkDebugOut((DEB_ARGS, "1632 STGMEDIUM: %p {%d, %p, ...} -> "
+ "%p {%d, %p, ...}\n", vpsm16, psm16->tymed,
+ psm16->pUnkForRelease, psm32, psm32->tymed,
+ psm32->pUnkForRelease));
+#endif
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanStgMed32, public
+//
+// Synopsis: Cleans up a 32-bit STGMEDIUM
+//
+// Arguments: [pti] - Thunk info
+// [psm32] - STGMEDIUM to clean
+// [vpsm16] - Source STGMEDIUM if thunk
+// [dwSize] - Source size if thunk
+// [fIsThunk] - STGMEDIUM was generated by thunking
+// [pfe] - FORMATETC or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CleanStgMed32(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ HMEM16 hmem16;
+ VPVOID vpvUnk;
+ BOOL bNoRefs=TRUE;
+
+ thkDebugOut((DEB_ITRACE, "In CleanStgMed32(%p, %p, %p, %u, %d, %p)\n",
+ pti, psm32, vpsm16, dwSize, fIsThunk, pfe));
+
+ sc = S_OK;
+
+ if (fIsThunk && (NULL!=psm32->pUnkForRelease) )
+ {
+ CSm32ReleaseHandler* psm32rh = (CSm32ReleaseHandler*)psm32->pUnkForRelease;
+
+ // When the StgMed is a Thunk and we have a pUnkForRelease:
+ //
+ // Only the remote end is expected to call the last Release() of
+ // the ReleaseHandler. We normally have the last reference here
+ // so just "delete" the ReleaseHandler and release everything.
+ //
+ // But... in the Async OnDataChange() if the remote call hasn't
+ // completed yet the system will be holding a reference so we need to
+ // release our reference but not free any non-reference counted objects
+ // below. Sm32ReleaseHandler->Release() will be called when the
+ // remote side call completes and Release() is called on the
+ // pUnkForRelease. And that will clean up.
+
+ if(1 == psm32rh->_cReferences)
+ {
+ delete psm32rh;
+ bNoRefs = TRUE;
+ }
+ else
+ {
+ psm32rh->Release();
+ bNoRefs = FALSE;
+ }
+ psm32->pUnkForRelease = NULL;
+ }
+
+ switch( psm32->tymed )
+ {
+ case TYMED_HGLOBAL:
+ if (bNoRefs)
+ {
+ if (fIsThunk &&
+ (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ Assert(NULL != psm32->hGlobal);
+
+ sc = ConvertHGlobal3216(pti, psm32->hGlobal, 0,
+ &hmem16, &dwSize);
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ }
+
+ GlobalFree( psm32->hGlobal );
+ psm32->hGlobal = NULL;
+ }
+ break;
+
+ case TYMED_MFPICT:
+ if (bNoRefs)
+ {
+
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ // Can't modify an MFPICT
+
+ METAFILEPICT *pmfp32;
+
+ pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
+ DeleteMetaFile(pmfp32->hMF);
+ GlobalUnlock(psm32->hGlobal);
+#endif
+ GlobalFree(psm32->hGlobal);
+ }
+ break;
+
+ case TYMED_FILE:
+ if (bNoRefs)
+ {
+ Convert_VPSTR_to_LPOLESTR_free( NULL, psm32->lpszFileName );
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ if (fIsThunk)
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ if (fIsThunk)
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pstg;
+ RELVDMPTR(vpsm16);
+
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ }
+ break;
+
+ case TYMED_GDI:
+ //
+ // No unthunking needed
+ //
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ // Ignore, this case is handled on input
+ thkAssert(!"STGMEDIUM with invalid tymed");
+ break;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out CleanStgMed32 => 0x%08lX\n", sc));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStgMed3216, public
+//
+// Synopsis: Converts a 32-bit STGMEDIUM to 16-bits
+//
+// Arguments: [pti] - Thunk info
+// [psm32] - 32-bit STGMEDIUM
+// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
+// [pfe] - FORMATETC paired with STGMEDIUM or NULL
+// [pdwSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: [pdwSize] is only set for TYMED_HGLOBAL
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStgMed3216(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ VPVOID vpsrh;
+ VPSTR vpstr;
+ UINT uiSize;
+ VPVOID vpvUnkForRelease;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+ THKSTATE thkstateSaved;
+
+ sc = S_OK;
+
+ if (psm32->pUnkForRelease != NULL)
+ {
+ // If the storageMedium includes a pUnk and we are passing
+ // ownership via an [in] parameter. Then we need to build
+ // a proxy with a "real" (rather than "local") reference.
+ // Here we trick "FindProxy1632" into believing it
+ // is building an [out] parameter
+ thkstateSaved = pti->pThkMgr->GetThkState();
+ if(fPassingOwnershipIn)
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ vpvUnkForRelease = pti->pThkMgr->FindProxy1632(NULL,
+ psm32->pUnkForRelease,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (vpvUnkForRelease == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ vpsrh = WOWGlobalAllocLock16(GMEM_MOVEABLE,
+ sizeof(CSm16ReleaseHandler),
+ NULL);
+ if (vpsrh == 0)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pUnkForRelease);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpsrh = 0;
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->tymed = psm32->tymed;
+ psm16->pUnkForRelease = (IUnknown *)vpsrh;
+ RELVDMPTR(vpsm16);
+
+ switch( psm32->tymed )
+ {
+ case TYMED_HGLOBAL:
+ if (pfe && OBJDESC_CF(pfe->cfFormat))
+ {
+ sc = ConvertObjDesc3216(pti, psm32->hGlobal, &hmem16);
+ }
+#if !defined(_CHICAGO_)
+
+ else if (pfe && pfe->cfFormat == CF_HDROP)
+ {
+ // fix for mapi forms
+ sc = ConvertHDrop3216(psm32->hGlobal, &hmem16);
+ }
+
+#endif
+ else
+ {
+ hmem16 = 0;
+ sc = ConvertHGlobal3216(pti, psm32->hGlobal, THOP_INOUT,
+ &hmem16, pdwSize);
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_MFPICT:
+ sc = ConvertMfPict3216(pti, psm32->hGlobal, &hmem16);
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_FILE:
+ uiSize = lstrlenW(psm32->lpszFileName) + 1;
+ vpstr = TaskMalloc16( uiSize*2 );
+ if ( vpstr == NULL )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ sc = Convert_LPOLESTR_to_VPSTR( psm32->lpszFileName,
+ vpstr, uiSize, uiSize*2 );
+ if (FAILED(sc))
+ {
+ TaskFree16(vpstr);
+ }
+ else
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->lpszFileName = (LPOLESTR)vpstr;
+ RELVDMPTR(vpsm16);
+
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "3216 TYMED_FILE: '%s' (%ws)\n",
+ WOWFIXVDMPTR(vpstr, 0),
+ psm32->lpszFileName));
+ WOWRELVDMPTR(vpstr);
+#endif
+ }
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstm,
+ INDEX_IIDIDX(THI_IStream),
+ NULL);
+ if (vpvUnk == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "3216 TYMED_ISTREAM: %p -> %p\n",
+ psm32->pstm, vpvUnk));
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->pstm = (IStream *)vpvUnk;
+ RELVDMPTR(vpsm16);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstg,
+ INDEX_IIDIDX(THI_IStorage),
+ NULL);
+ if (vpvUnk == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "3216 TYMED_ISTORAGE: %p -> %p\n",
+ psm32->pstg, vpvUnk));
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->pstg = (IStorage *)vpvUnk;
+ RELVDMPTR(vpsm16);
+ }
+ break;
+
+ case TYMED_GDI:
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hBitmap = (HBITMAP)HBITMAP_16(psm32->hBitmap);
+ thkDebugOut((DEB_ARGS, "3216 TYMED_GDI: 0x%p -> 0x%04X\n",
+ psm32->hBitmap, psm16->hBitmap));
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ if (FAILED(sc))
+ {
+ if (vpsrh != 0)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pUnkForRelease);
+ WOWGlobalUnlockFree16(vpsrh);
+ }
+ }
+ else
+ {
+ if (vpsrh != 0)
+ {
+ CSm16ReleaseHandler UNALIGNED *psrh;
+ CLIPFORMAT cf;
+
+ if (pfe)
+ {
+ cf = pfe->cfFormat;
+ }
+ else
+ {
+ cf = CF_INVALID;
+ }
+ psrh = FIXVDMPTR(vpsrh, CSm16ReleaseHandler);
+ psrh->Init(pti->pThkMgr, psm32, FIXVDMPTR(vpsm16, STGMEDIUM),
+ vpvUnkForRelease, cf);
+ RELVDMPTR(vpsrh);
+ RELVDMPTR(vpsm16);
+ }
+
+#if DBG == 1
+ if (pfe)
+ {
+ thkDebugOut((DEB_ARGS, "3216 STGMEDIUM FORMATETC %p {%d}\n",
+ pfe, pfe->cfFormat));
+ }
+ thkDebugOut((DEB_ARGS, "3216 STGMEDIUM: %p {%d, %p, ...} -> "
+ "%p {%d, %p, ...}\n", psm32, psm32->tymed,
+ psm32->pUnkForRelease, vpsm16, psm16->tymed,
+ psm16->pUnkForRelease));
+#endif
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanStgMed16, public
+//
+// Synopsis: Frees up resources in a 16-bit STGMEDIUM
+//
+// Arguments: [pti] - Thunk info
+// [vpsm16] - STGMEDIUM to clean
+// [psm32] - Source STGMEDIUM if thunk
+// [dwSize] - Source size for thunked HGLOBAL
+// [fIsThunk] - If the STGMEDIUM is a result of thunking
+// [pfe] - FORMATETC or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CleanStgMed16(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+
+ thkDebugOut((DEB_ITRACE, "In CleanStgMed16(%p, %p, %p, %u, %d, %p)\n",
+ pti, vpsm16, psm32, dwSize, fIsThunk, pfe));
+
+ sc = S_OK;
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pUnkForRelease;
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk && vpvUnk != 0)
+ {
+ CSm16ReleaseHandler UNALIGNED *psrh;
+
+ psrh = FIXVDMPTR(vpvUnk, CSm16ReleaseHandler);
+ psrh->Uninit();
+ RELVDMPTR(vpvUnk);
+ WOWGlobalUnlockFree16(vpvUnk);
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ switch( psm16->tymed )
+ {
+ case TYMED_HGLOBAL:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk &&
+ (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
+ {
+ sc = ConvertHGlobal1632(pti, hmem16, 0,
+ &psm32->hGlobal, &dwSize);
+ }
+
+ WOWGlobalFree16( hmem16 );
+ break;
+
+ case TYMED_MFPICT:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ // Can't modify an MFPICT
+
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ VPVOID vpvmfp16;
+ METAFILEPICT16 *pmfp16;
+ HMEM16 hmf16;
+
+ vpvmfp16 = WOWGlobalLock16(hmem16);
+ pmfp16 = FIXVDMPTR(vpvmfp16, METAFILEPICT16);
+ hmf16 = pmfp16->hMF;
+ RELVDMPTR(vpvmfp16);
+
+ // Relies on the fact that a 16-bit metafile is an HGLOBAL
+ WOWGlobalFree16(hmf16);
+
+ WOWGlobalUnlockFree16(vpvmfp16);
+#else
+ WOWGlobalFree16(hmem16);
+#endif
+ break;
+
+ case TYMED_FILE:
+ vpvUnk = (VPVOID)psm16->lpszFileName;
+ RELVDMPTR(vpsm16);
+
+ TaskFree16(vpvUnk);
+ break;
+
+ case TYMED_ISTREAM:
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pstm);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pstg);
+ }
+ break;
+
+ case TYMED_GDI:
+ RELVDMPTR(vpsm16);
+
+ //
+ // No unthunking needed
+ //
+ break;
+
+ case TYMED_NULL:
+ RELVDMPTR(vpsm16);
+
+ break;
+
+ default:
+ // Ignore, this case is handled on input
+ thkAssert(!"CleanStgMed16 with invalid tymed");
+ break;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out CleanStgMed16 => 0x%08lX\n", sc));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertFetc1632, public
+//
+// Synopsis: Converts a FORMATETC
+//
+// Arguments: [pti] - Thunk info
+// [vpfe16] - FORMATETC
+// [pfe32] - FORMATETC
+// [fFree] - Free resources as converting
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pfe32]
+//
+// History: 14-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertFetc1632(THUNKINFO *pti,
+ VPVOID vpfe16,
+ FORMATETC *pfe32,
+ BOOL fFree)
+{
+ FORMATETC16 UNALIGNED *pfe16;
+ VPVOID vpdv16;
+ DVTARGETDEVICE *pdv32;
+ UINT cbSize;
+ SCODE sc;
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ vpdv16 = (VPVOID)pfe16->ptd;
+ RELVDMPTR(vpfe16);
+
+ if ( vpdv16 == 0 )
+ {
+ pdv32 = NULL;
+ }
+ else
+ {
+ sc = ConvertDvtd1632(pti, vpdv16, ArTask32, FrTask32,
+ &pdv32, &cbSize);
+
+ if (fFree)
+ {
+ TaskFree16(vpdv16);
+ }
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+ }
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ pfe32->cfFormat = pfe16->cfFormat;
+ pfe32->ptd = pdv32;
+ pfe32->dwAspect = pfe16->dwAspect;
+ pfe32->lindex = pfe16->lindex;
+ pfe32->tymed = pfe16->tymed;
+
+ thkDebugOut((DEB_ARGS, "1632 FORMATETC: "
+ "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
+ vpfe16, pfe32,
+ pfe32->cfFormat,
+ pfe32->ptd, vpdv16,
+ pfe32->dwAspect,
+ pfe32->lindex,
+ pfe32->tymed));
+
+ RELVDMPTR(vpfe16);
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertFetc3216, public
+//
+// Synopsis: Converts a FORMATETC
+//
+// Arguments: [pti] - Thunk info
+// [pfe32] - FORMATETC
+// [vpfe16] - FORMATETC
+// [fFree] - Free resources as converting
+//
+// Returns: Appropriate status code
+//
+// Modifies: [vpfe16]
+//
+// History: 14-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertFetc3216(THUNKINFO *pti,
+ FORMATETC *pfe32,
+ VPVOID vpfe16,
+ BOOL fFree)
+{
+ FORMATETC16 UNALIGNED *pfe16;
+ DVTARGETDEVICE *pdv32;
+ SCODE sc;
+ VPVOID vpdv16;
+ UINT cbSize;
+
+ pdv32 = pfe32->ptd;
+ if (pdv32 != NULL)
+ {
+ sc = ConvertDvtd3216(pti, pdv32, ArTask16, FrTask16,
+ &vpdv16, &cbSize);
+
+ if (fFree)
+ {
+ TaskFree32(pdv32);
+ }
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+ }
+ else
+ {
+ vpdv16 = 0;
+ }
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ pfe16->cfFormat = pfe32->cfFormat;
+ pfe16->ptd = vpdv16;
+ pfe16->dwAspect = pfe32->dwAspect;
+ pfe16->lindex = pfe32->lindex;
+ pfe16->tymed = pfe32->tymed;
+
+ thkDebugOut((DEB_ARGS, "3216 FORMATETC: "
+ "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
+ pfe32, vpfe16,
+ pfe16->cfFormat,
+ vpdv16, pdv32,
+ pfe16->dwAspect,
+ pfe16->lindex,
+ pfe16->tymed));
+
+ RELVDMPTR(vpfe16);
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DebugValidateProxy1632, debug public
+//
+// Synopsis: Validates a 16->32 proxy pointer and its memory
+//
+// Arguments: [vpvProxy] - Proxy
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void DebugValidateProxy1632(VPVOID vpvProxy)
+{
+ THUNK1632OBJ UNALIGNED *pto;
+ THUNKINFO ti;
+
+ thkAssert(vpvProxy != 0 && "Invalid proxy pointer");
+
+ pto = (THUNK1632OBJ UNALIGNED *)
+ GetReadWritePtr16(&ti, vpvProxy, sizeof(THUNK1632OBJ));
+ thkAssert(pto != NULL && "Invalid proxy pointer");
+
+ thkAssert(pto->dwSignature == PSIG1632 && "Dead or invalid proxy!");
+
+ thkAssert(pto->cRefLocal >= 0 && "Invalid proxy refcount");
+ thkAssert(pto->cRefLocal >= pto->cRef && "Invalid proxy refcount");
+
+ if (!IsValidInterface(pto->punkThis32))
+ {
+ thkDebugOut((DEB_ERROR, "1632 %p: Invalid proxied object %p\n",
+ vpvProxy, pto->punkThis32));
+ }
+
+ WOWRELVDMPTR(vpvProxy);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DebugValidateProxy3216, debug public
+//
+// Synopsis: Validates a 32->16 proxy pointer and its memory
+//
+// Arguments: [pto] - Proxy
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void DebugValidateProxy3216(THUNK3216OBJ *pto)
+{
+ THUNKINFO ti;
+
+ thkAssert(pto != 0 && "Invalid proxy pointer");
+
+ thkAssert(!IsBadReadPtr(pto, sizeof(THUNK3216OBJ)) &&
+ !IsBadWritePtr(pto, sizeof(THUNK3216OBJ)) &&
+ "Invalid proxy pointer");
+
+ thkAssert(pto->dwSignature == PSIG3216 && "Dead or invalid proxy!");
+
+ thkAssert(pto->cRefLocal >= 0 && "Invalid proxy refcount");
+ thkAssert(pto->cRefLocal >= pto->cRef && "Invalid proxy refcount");
+
+ if (!IsValidInterface16(&ti, pto->vpvThis16))
+ {
+ thkDebugOut((DEB_ERROR, "3216 %p: Invalid proxied object %p\n",
+ pto, pto->vpvThis16));
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClampLongToShort, public
+//
+// Synopsis: Restricts a long value to a short value by clamping
+//
+// Arguments: [l] - Long
+//
+// Returns: Short
+//
+// History: 16-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SHORT ClampLongToShort(LONG l)
+{
+ SHORT s;
+
+ if (l < SHRT_MIN)
+ {
+ s = SHRT_MIN;
+ thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
+ }
+ else if (l > SHRT_MAX)
+ {
+ s = SHRT_MAX;
+ thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
+ }
+ else
+ {
+ s = (SHORT)l;
+ }
+
+ return s;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClampULongToUShort, public
+//
+// Synopsis: Restricts an unsigned long value to an unsigned short value
+// by clamping
+//
+// Arguments: [ul] - Long
+//
+// Returns: UShort
+//
+// History: 16-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+USHORT ClampULongToUShort(ULONG ul)
+{
+ USHORT us;
+
+ if (ul > USHRT_MAX)
+ {
+ us = USHRT_MAX;
+ thkDebugOut((DEB_WARN, "ClampULongToUShort: %ld -> %d\n", ul, us));
+ }
+ else
+ {
+ us = (USHORT)ul;
+ }
+
+ return us;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDescriptor
+//
+// Synopsis: Exported API called by WOW to convert ObjectDescriptors to
+// the indicated format.
+//
+//
+// Arguments: [hMem] -- Handle to the ObjectDescriptor to convert.
+// [flag] -- Flag indicating which direction the convertion
+// should take place. Valid values are:
+// CFOLE_UNICODE_TO_ANSI.
+// CFOLE_ANSI_TO_UNICODE.
+//
+// Returns: HGLOBAL to the converted ObjectDescriptor,
+// or NULL on failure.
+//
+// History: 8-16-94 terryru Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(HGLOBAL) ConvertObjDescriptor( HANDLE hMem, UINT flag )
+{
+
+ const UINT CFOLE_UNICODE_TO_ANSI = 0;
+ const UINT CFOLE_ANSI_TO_UNICODE = 1;
+
+ THUNKINFO ti;
+ HGLOBAL hMem32;
+ HMEM16 hMem16;
+
+ switch ( flag )
+ {
+ case CFOLE_UNICODE_TO_ANSI:
+ if( FAILED( ConvertObjDesc3216( &ti, (HGLOBAL) hMem, &hMem16 )))
+ {
+ return (HGLOBAL) NULL;
+ }
+ else
+ {
+ return (HGLOBAL) hMem16;
+ }
+ break;
+
+ case CFOLE_ANSI_TO_UNICODE:
+ if( FAILED( ConvertObjDesc1632( &ti, (HMEM16) hMem, &hMem32 )))
+ {
+ return (HGLOBAL) NULL;
+ }
+ else
+ {
+ return (HGLOBAL) hMem32;
+ }
+ break;
+
+ default:
+ thkAssert(!"ConvertObjDescriptor, Invalid flag");
+ break;
+ }
+ return (HGLOBAL) NULL;
+}
+
+#if defined(_CHICAGO_)
+
+//
+// BUGBUGCHICAGO
+//
+// A hack so everyone can build Chicago OLE until I write the thunking
+// library later this week.
+//
+
+#define ERR ((char*) -1)
+
+#if DBG==1
+int UnicodeToAnsi(LPSTR sz, LPCWSTR pwsz, LONG cb)
+{
+ int ret;
+
+ ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL);
+
+ thkAssert(ret != 0 && "Lost characters in thk Unicode->Ansi conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+
+ return ret;
+}
+#else
+#define UnicodeToAnsi(sz,pwsz,cb) WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL)
+#endif
+
+
+#if DBG==1
+int AnsiToUnicode(LPWSTR pwsz, LPCSTR sz, LONG cb)
+{
+ int ret;
+
+ ret = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb);
+
+ thkAssert(ret != 0 && "Lost characters in thk Ansi->Unicode conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+
+ return ret;
+}
+#else
+#define AnsiToUnicode(pwsz,sz,cb) MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb)
+#endif
+
+
+
+extern "C"
+DWORD
+WINAPI
+GetShortPathNameX(
+ LPCWSTR lpszFullPath,
+ LPWSTR lpszShortPath,
+ DWORD cchBuffer
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetShortPathName\n");
+ #endif
+
+ CHAR szFullPath[MAX_PATH];
+ CHAR szShortBuffer[MAX_PATH];
+ DWORD ret;
+
+
+ UnicodeToAnsi(szFullPath, lpszFullPath, sizeof(szFullPath));
+
+ if (lpszShortPath == NULL)
+ {
+ ret = GetShortPathNameA(szFullPath, NULL, cchBuffer);
+ }
+ else
+ {
+ ret = GetShortPathNameA(szFullPath, szShortBuffer,
+ sizeof(szShortBuffer));
+
+ thkAssert(ret != cchBuffer &&
+ "GetShortPathName - Output buffer too short");
+ //
+ // Don't convert the buffer if the
+ // call to GetShortPathNameA() failed.
+ //
+ if(0 != ret)
+ {
+ //
+ // Only convert the actual data, not the whole buffer.
+ //
+ if (cchBuffer > ret + 1)
+ cchBuffer = ret + 1;
+
+ AnsiToUnicode(lpszShortPath, szShortBuffer, cchBuffer);
+ }
+ }
+
+ return ret;
+}
+
+#endif // _CHICAGO_
+
diff --git a/private/ole32/olethunk/olethk32/thoputil.hxx b/private/ole32/olethunk/olethk32/thoputil.hxx
new file mode 100644
index 000000000..f13fe7f09
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thoputil.hxx
@@ -0,0 +1,216 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thoputil.hxx
+//
+// Contents: Thunk routine utilities
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPUTIL_HXX__
+#define __THOPUTIL_HXX__
+
+// Alias manager for THOP_ALIAS32
+extern CAliases gAliases32;
+
+IIDIDX IidToIidIdx(REFIID riid);
+
+#ifdef COTASK_DEFINED
+#define TaskMalloc32 CoTaskMemAlloc
+#define TaskFree32 CoTaskMemFree
+#else
+LPVOID TaskMalloc32(DWORD cb);
+void TaskFree32(LPVOID pv);
+#endif
+
+DWORD TaskMalloc16( UINT uiSize );
+void TaskFree16( DWORD vpvoid );
+
+LPOLESTR Convert_VPSTR_to_LPOLESTR(THUNKINFO *pti,
+ VPSTR vpstr,
+ LPOLESTR lpOleStr,
+ UINT uiSizeInPlace);
+//
+// Simple macro to free up any string allocated in the conversion process
+//
+#define Convert_VPSTR_to_LPOLESTR_free( lpOleStr, lpOleStrUsed ) \
+ (((lpOleStr) == (lpOleStrUsed)) ? 0 : \
+ (lpOleStrUsed == NULL) ? 0 : TaskFree32(lpOleStrUsed))
+
+SCODE Convert_LPOLESTR_to_VPSTR(LPCOLESTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16);
+
+#ifdef _CHICAGO_
+// This is only really used on Chicago
+SCODE Convert_LPSTR_to_VPSTR(LPCSTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16);
+#endif
+
+STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult );
+STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult );
+
+SHORT ClampLongToShort(LONG l);
+USHORT ClampULongToUShort(ULONG l);
+
+VOID * GetReadPtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetWritePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetCodePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetReadWritePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+CHAR * GetStringPtr16( THUNKINFO *pti, VPVOID vp16, UINT cchMax,
+ PUINT lpuiSize );
+VOID * ValidatePtr16(THUNKINFO *pti, VPVOID vp16, DWORD dwSize,
+ THOP thopInOut);
+BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp );
+
+SCODE ConvertHGlobal1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ THOP thopInOut,
+ HGLOBAL *phg32,
+ DWORD *pdwSize);
+SCODE ConvertHGlobal3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ THOP thopInOut,
+ HMEM16 *phg16,
+ DWORD *pdwSize);
+SCODE ConvertStgMed1632(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize);
+SCODE CleanStgMed32(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe);
+SCODE ConvertStgMed3216(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize);
+SCODE CleanStgMed16(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe);
+SCODE ConvertFetc1632(THUNKINFO *pti,
+ VPVOID vpfe16,
+ FORMATETC *pfe32,
+ BOOL fFree);
+SCODE ConvertFetc3216(THUNKINFO *pti,
+ FORMATETC *pfe32,
+ VPVOID vpfe16,
+ BOOL fFree);
+
+#if DBG == 1
+
+char *ThopName(THOP thop);
+char *EnumThopName(THOP thopEnum);
+char *GuidString(GUID const *pguid);
+char *IidOrInterfaceString(IID const *piid);
+char *IidIdxString(IIDIDX iidx);
+
+void DebugValidateProxy1632(VPVOID vpvProxy);
+void DebugValidateProxy3216(THUNK3216OBJ *ptoProxy);
+
+#else
+
+#define DebugValidateProxy1632(p)
+#define DebugValidateProxy3216(p)
+
+#endif
+
+#define StackAlloc16(cb) \
+ ((VPVOID)TlsThkGetStack16()->Alloc(cb))
+#define StackFree16(vpv, cb) \
+ TlsThkGetStack16()->Free((DWORD)vpv, cb)
+#define StackAlloc32(cb) \
+ ((LPVOID)TlsThkGetStack32()->Alloc(cb))
+#define StackFree32(pv, cb) \
+ TlsThkGetStack32()->Free((DWORD)pv, cb)
+
+#define STACKALLOC16(x) StackAlloc16(x)
+#define STACKFREE16(x,y) StackFree16(x, y)
+
+#ifdef _CHICAGO_
+#define STACKALLOC32(x) StackAlloc32(x)
+#define STACKFREE32(x, y) StackFree32(x, y)
+#else
+#define STACKALLOC32(x) (DWORD)_alloca(x)
+#define STACKFREE32(x, y)
+#endif
+
+#if DBG == 1
+void RecordStackState16(SStackRecord *psr);
+void CheckStackState16(SStackRecord *psr);
+
+void RecordStackState32(SStackRecord *psr);
+void CheckStackState32(SStackRecord *psr);
+#endif
+
+typedef void *(*ALLOCROUTINE)(UINT cb);
+typedef void (*FREEROUTINE)(void *pv, UINT cb);
+
+void *ArTask16(UINT cb);
+void FrTask16(void *pv, UINT cb);
+
+void *ArTask32(UINT cb);
+void FrTask32(void *pv, UINT cb);
+
+void *ArStack16(UINT cb);
+void FrStack16(void *pv, UINT cb);
+
+void *ArStack32(UINT cb);
+void FrStack32(void *pv, UINT cb);
+
+SCODE ConvertDvtd1632(THUNKINFO *pti,
+ VPVOID vpdvtd16,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ DVTARGETDEVICE **ppdvtd32,
+ UINT *pcbSize);
+SCODE ConvertDvtd3216(THUNKINFO *pti,
+ DVTARGETDEVICE *pdvtd32,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ VPVOID *ppvdvtd16,
+ UINT *pcbSize);
+
+typedef void (*FIXEDHANDLERROUTINE)(BYTE *pbFrom, BYTE *pbTo,
+ UINT cbFrom, UINT cbTo);
+
+void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+
+#endif // #ifndef __THOPUTIL_HXX__
diff --git a/private/ole32/olethunk/olethk32/thtblapi.cxx b/private/ole32/olethunk/olethk32/thtblapi.cxx
new file mode 100644
index 000000000..3bc046a0d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thtblapi.cxx
@@ -0,0 +1,125 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thtblapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "thopsapi.cxx"
+
+THOP CONST * CONST apthopsApiThops[] =
+{
+ thopsCoInitialize
+, thopsCoUninitialize
+, thopsCoGetClassObject
+, thopsCoRegisterClassObject
+, thopsCoRevokeClassObject
+, thopsCoMarshalInterface
+, thopsCoUnmarshalInterface
+, thopsCoReleaseMarshalData
+, thopsCoDisconnectObject
+, thopsCoLockObjectExternal
+, thopsCoGetStandardMarshal
+, thopsCoIsHandlerConnected
+, thopsCoFreeAllLibraries
+, thopsCoFreeUnusedLibraries
+, thopsCoCreateInstance
+, thopsCLSIDFromString
+, thopsCoIsOle1Class
+, thopsProgIDFromCLSID
+, thopsCLSIDFromProgID
+, thopsCoCreateGuid
+, thopsCoFileTimeToDosDateTime
+, thopsCoDosDateTimeToFileTime
+, thopsCoFileTimeNow
+, thopsCoRegisterMessageFilter
+, thopsCoGetTreatAsClass
+, thopsCoTreatAsClass
+, thopsDllGetClassObject
+, thopsStgCreateDocfile
+, thopsStgCreateDocfileOnILockBytes
+, thopsStgOpenStorage
+, thopsStgOpenStorageOnILockBytes
+, thopsStgIsStorageFile
+, thopsStgIsStorageILockBytes
+, thopsStgSetTimes
+, thopsCreateDataAdviseHolder
+, thopsCreateDataCache
+, thopsBindMoniker
+, thopsMkParseDisplayName
+, thopsMonikerRelativePathTo
+, thopsMonikerCommonPrefixWith
+, thopsCreateBindCtx
+, thopsCreateGenericComposite
+, thopsGetClassFile
+, thopsCreateFileMoniker
+, thopsCreateItemMoniker
+, thopsCreateAntiMoniker
+, thopsCreatePointerMoniker
+, thopsGetRunningObjectTable
+, thopsReadClassStg
+, thopsWriteClassStg
+, thopsReadClassStm
+, thopsWriteClassStm
+, thopsWriteFmtUserTypeStg
+, thopsReadFmtUserTypeStg
+, thopsOleInitialize
+, thopsOleUninitialize
+, thopsOleQueryLinkFromData
+, thopsOleQueryCreateFromData
+, thopsOleCreate
+, thopsOleCreateFromData
+, thopsOleCreateLinkFromData
+, thopsOleCreateStaticFromData
+, thopsOleCreateLink
+, thopsOleCreateLinkToFile
+, thopsOleCreateFromFile
+, thopsOleLoad
+, thopsOleSave
+, thopsOleLoadFromStream
+, thopsOleSaveToStream
+, thopsOleSetContainedObject
+, thopsOleNoteObjectVisible
+, thopsRegisterDragDrop
+, thopsRevokeDragDrop
+, thopsDoDragDrop
+, thopsOleSetClipboard
+, thopsOleGetClipboard
+, thopsOleFlushClipboard
+, thopsOleIsCurrentClipboard
+, thopsOleCreateMenuDescriptor
+, thopsOleSetMenuDescriptor
+, thopsOleDestroyMenuDescriptor
+, thopsOleDraw
+, thopsOleRun
+, thopsOleIsRunning
+, thopsOleLockRunning
+, thopsCreateOleAdviseHolder
+, thopsOleCreateDefaultHandler
+, thopsOleCreateEmbeddingHelper
+, thopsOleRegGetUserType
+, thopsOleRegGetMiscStatus
+, thopsOleRegEnumFormatEtc
+, thopsOleRegEnumVerbs
+, thopsOleConvertIStorageToOLESTREAM
+, thopsOleConvertOLESTREAMToIStorage
+, thopsOleConvertIStorageToOLESTREAMEx
+, thopsOleConvertOLESTREAMToIStorageEx
+, thopsOleDoAutoConvert
+, thopsOleGetAutoConvert
+, thopsOleSetAutoConvert
+, thopsGetConvertStg
+, thopsSetConvertStg
+, thopsReadOleStg
+, thopsWriteOleStg
+};
diff --git a/private/ole32/olethunk/olethk32/thtblint.cxx b/private/ole32/olethunk/olethk32/thtblint.cxx
new file mode 100644
index 000000000..dcd0e89dc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thtblint.cxx
@@ -0,0 +1,508 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thtblint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST * CONST apthopsIUnknown[] =
+{
+ NULL
+};
+THOP CONST * CONST apthopsIClassFactory[] =
+{
+ thopsIClassFactory_CreateInstance
+, thopsIClassFactory_LockServer
+};
+THOP CONST * CONST apthopsIMarshal[] =
+{
+ thopsIMarshal_GetUnmarshalClass
+, thopsIMarshal_GetMarshalSizeMax
+, thopsIMarshal_MarshalInterface
+, thopsIMarshal_UnmarshalInterface
+, thopsIMarshal_ReleaseMarshalData
+, thopsIMarshal_DisconnectObject
+};
+THOP CONST * CONST apthopsIStdMarshalInfo[] =
+{
+ thopsIStdMarshalInfo_GetClassForHandler
+};
+THOP CONST * CONST apthopsIMessageFilter[] =
+{
+ thopsIMessageFilter_HandleInComingCall
+, thopsIMessageFilter_RetryRejectedCall
+, thopsIMessageFilter_MessagePending
+};
+THOP CONST * CONST apthopsIExternalConnection[] =
+{
+ thopsIExternalConnection_AddConnection
+, thopsIExternalConnection_ReleaseConnection
+};
+THOP CONST * CONST apthopsIEnumString[] =
+{
+ thopsIEnumString_Next
+, thopsIEnumString_Skip
+, thopsIEnumString_Reset
+, thopsIEnumString_Clone
+};
+THOP CONST * CONST apthopsIEnumUnknown[] =
+{
+ thopsIEnumUnknown_Next
+, thopsIEnumUnknown_Skip
+, thopsIEnumUnknown_Reset
+, thopsIEnumUnknown_Clone
+};
+THOP CONST * CONST apthopsIEnumSTATSTG[] =
+{
+ thopsIEnumSTATSTG_Next
+, thopsIEnumSTATSTG_Skip
+, thopsIEnumSTATSTG_Reset
+, thopsIEnumSTATSTG_Clone
+};
+THOP CONST * CONST apthopsILockBytes[] =
+{
+ thopsILockBytes_ReadAt
+, thopsILockBytes_WriteAt
+, thopsILockBytes_Flush
+, thopsILockBytes_SetSize
+, thopsILockBytes_LockRegion
+, thopsILockBytes_UnlockRegion
+, thopsILockBytes_Stat
+};
+THOP CONST * CONST apthopsIStream[] =
+{
+ thopsIStream_Read
+, thopsIStream_Write
+, thopsIStream_Seek
+, thopsIStream_SetSize
+, thopsIStream_CopyTo
+, thopsIStream_Commit
+, thopsIStream_Revert
+, thopsIStream_LockRegion
+, thopsIStream_UnlockRegion
+, thopsIStream_Stat
+, thopsIStream_Clone
+};
+THOP CONST * CONST apthopsIStorage[] =
+{
+ thopsIStorage_CreateStream
+, thopsIStorage_OpenStream
+, thopsIStorage_CreateStorage
+, thopsIStorage_OpenStorage
+, thopsIStorage_CopyTo
+, thopsIStorage_MoveElementTo
+, thopsIStorage_Commit
+, thopsIStorage_Revert
+, thopsIStorage_EnumElements
+, thopsIStorage_DestroyElement
+, thopsIStorage_RenameElement
+, thopsIStorage_SetElementTimes
+, thopsIStorage_SetClass
+, thopsIStorage_SetStateBits
+, thopsIStorage_Stat
+};
+THOP CONST * CONST apthopsIRootStorage[] =
+{
+ thopsIRootStorage_SwitchToFile
+};
+THOP CONST * CONST apthopsIEnumFORMATETC[] =
+{
+ thopsIEnumFORMATETC_Next
+, thopsIEnumFORMATETC_Skip
+, thopsIEnumFORMATETC_Reset
+, thopsIEnumFORMATETC_Clone
+};
+THOP CONST * CONST apthopsIEnumSTATDATA[] =
+{
+ thopsIEnumSTATDATA_Next
+, thopsIEnumSTATDATA_Skip
+, thopsIEnumSTATDATA_Reset
+, thopsIEnumSTATDATA_Clone
+};
+THOP CONST * CONST apthopsIDataObject[] =
+{
+ thopsIDataObject_GetData
+, thopsIDataObject_GetDataHere
+, thopsIDataObject_QueryGetData
+, thopsIDataObject_GetCanonicalFormatEtc
+, thopsIDataObject_SetData
+, thopsIDataObject_EnumFormatEtc
+, thopsIDataObject_DAdvise
+, thopsIDataObject_DUnadvise
+, thopsIDataObject_EnumDAdvise
+};
+THOP CONST * CONST apthopsIViewObject[] =
+{
+ thopsIViewObject_Draw
+, thopsIViewObject_GetColorSet
+, thopsIViewObject_Freeze
+, thopsIViewObject_Unfreeze
+, thopsIViewObject_SetAdvise
+, thopsIViewObject_GetAdvise
+};
+THOP CONST * CONST apthopsIViewObject2[] =
+{
+ thopsIViewObject2_Draw
+, thopsIViewObject2_GetColorSet
+, thopsIViewObject2_Freeze
+, thopsIViewObject2_Unfreeze
+, thopsIViewObject2_SetAdvise
+, thopsIViewObject2_GetAdvise
+, thopsIViewObject2_GetExtent
+};
+THOP CONST * CONST apthopsIAdviseSink[] =
+{
+ thopsIAdviseSink_OnDataChange
+, thopsIAdviseSink_OnViewChange
+, thopsIAdviseSink_OnRename
+, thopsIAdviseSink_OnSave
+, thopsIAdviseSink_OnClose
+};
+THOP CONST * CONST apthopsIAdviseSink2[] =
+{
+ thopsIAdviseSink2_OnDataChange
+, thopsIAdviseSink2_OnViewChange
+, thopsIAdviseSink2_OnRename
+, thopsIAdviseSink2_OnSave
+, thopsIAdviseSink2_OnClose
+, thopsIAdviseSink2_OnLinkSrcChange
+};
+THOP CONST * CONST apthopsIDataAdviseHolder[] =
+{
+ thopsIDataAdviseHolder_Advise
+, thopsIDataAdviseHolder_Unadvise
+, thopsIDataAdviseHolder_EnumAdvise
+, thopsIDataAdviseHolder_SendOnDataChange
+};
+THOP CONST * CONST apthopsIOleCache[] =
+{
+ thopsIOleCache_Cache
+, thopsIOleCache_Uncache
+, thopsIOleCache_EnumCache
+, thopsIOleCache_InitCache
+, thopsIOleCache_SetData
+};
+THOP CONST * CONST apthopsIOleCache2[] =
+{
+ thopsIOleCache2_Cache
+, thopsIOleCache2_Uncache
+, thopsIOleCache2_EnumCache
+, thopsIOleCache2_InitCache
+, thopsIOleCache2_SetData
+, thopsIOleCache2_UpdateCache
+, thopsIOleCache2_DiscardCache
+};
+THOP CONST * CONST apthopsIOleCacheControl[] =
+{
+ thopsIOleCacheControl_OnRun
+, thopsIOleCacheControl_OnStop
+};
+THOP CONST * CONST apthopsIDropTarget[] =
+{
+ thopsIDropTarget_DragEnter
+, thopsIDropTarget_DragOver
+, thopsIDropTarget_DragLeave
+, thopsIDropTarget_Drop
+};
+THOP CONST * CONST apthopsIDropSource[] =
+{
+ thopsIDropSource_QueryContinueDrag
+, thopsIDropSource_GiveFeedback
+};
+THOP CONST * CONST apthopsIPersist[] =
+{
+ thopsIPersist_GetClassID
+};
+THOP CONST * CONST apthopsIPersistStorage[] =
+{
+ thopsIPersistStorage_GetClassID
+, thopsIPersistStorage_IsDirty
+, thopsIPersistStorage_InitNew
+, thopsIPersistStorage_Load
+, thopsIPersistStorage_Save
+, thopsIPersistStorage_SaveCompleted
+, thopsIPersistStorage_HandsOffStorage
+};
+THOP CONST * CONST apthopsIPersistStream[] =
+{
+ thopsIPersistStream_GetClassID
+, thopsIPersistStream_IsDirty
+, thopsIPersistStream_Load
+, thopsIPersistStream_Save
+, thopsIPersistStream_GetSizeMax
+};
+THOP CONST * CONST apthopsIPersistFile[] =
+{
+ thopsIPersistFile_GetClassID
+, thopsIPersistFile_IsDirty
+, thopsIPersistFile_Load
+, thopsIPersistFile_Save
+, thopsIPersistFile_SaveCompleted
+, thopsIPersistFile_GetCurFile
+};
+THOP CONST * CONST apthopsIBindCtx[] =
+{
+ thopsIBindCtx_RegisterObjectBound
+, thopsIBindCtx_RevokeObjectBound
+, thopsIBindCtx_ReleaseBoundObjects
+, thopsIBindCtx_SetBindOptions
+, thopsIBindCtx_GetBindOptions
+, thopsIBindCtx_GetRunningObjectTable
+, thopsIBindCtx_RegisterObjectParam
+, thopsIBindCtx_GetObjectParam
+, thopsIBindCtx_EnumObjectParam
+, thopsIBindCtx_RevokeObjectParam
+};
+THOP CONST * CONST apthopsIMoniker[] =
+{
+ thopsIMoniker_GetClassID
+, thopsIMoniker_IsDirty
+, thopsIMoniker_Load
+, thopsIMoniker_Save
+, thopsIMoniker_GetSizeMax
+, thopsIMoniker_BindToObject
+, thopsIMoniker_BindToStorage
+, thopsIMoniker_Reduce
+, thopsIMoniker_ComposeWith
+, thopsIMoniker_Enum
+, thopsIMoniker_IsEqual
+, thopsIMoniker_Hash
+, thopsIMoniker_IsRunning
+, thopsIMoniker_GetTimeOfLastChange
+, thopsIMoniker_Inverse
+, thopsIMoniker_CommonPrefixWith
+, thopsIMoniker_RelativePathTo
+, thopsIMoniker_GetDisplayName
+, thopsIMoniker_ParseDisplayName
+, thopsIMoniker_IsSystemMoniker
+};
+THOP CONST * CONST apthopsIRunningObjectTable[] =
+{
+ thopsIRunningObjectTable_Register
+, thopsIRunningObjectTable_Revoke
+, thopsIRunningObjectTable_IsRunning
+, thopsIRunningObjectTable_GetObject
+, thopsIRunningObjectTable_NoteChangeTime
+, thopsIRunningObjectTable_GetTimeOfLastChange
+, thopsIRunningObjectTable_EnumRunning
+};
+THOP CONST * CONST apthopsIEnumMoniker[] =
+{
+ thopsIEnumMoniker_Next
+, thopsIEnumMoniker_Skip
+, thopsIEnumMoniker_Reset
+, thopsIEnumMoniker_Clone
+};
+THOP CONST * CONST apthopsIEnumOLEVERB[] =
+{
+ thopsIEnumOLEVERB_Next
+, thopsIEnumOLEVERB_Skip
+, thopsIEnumOLEVERB_Reset
+, thopsIEnumOLEVERB_Clone
+};
+THOP CONST * CONST apthopsIOleObject[] =
+{
+ thopsIOleObject_SetClientSite
+, thopsIOleObject_GetClientSite
+, thopsIOleObject_SetHostNames
+, thopsIOleObject_Close
+, thopsIOleObject_SetMoniker
+, thopsIOleObject_GetMoniker
+, thopsIOleObject_InitFromData
+, thopsIOleObject_GetClipboardData
+, thopsIOleObject_DoVerb
+, thopsIOleObject_EnumVerbs
+, thopsIOleObject_Update
+, thopsIOleObject_IsUpToDate
+, thopsIOleObject_GetUserClassID
+, thopsIOleObject_GetUserType
+, thopsIOleObject_SetExtent
+, thopsIOleObject_GetExtent
+, thopsIOleObject_Advise
+, thopsIOleObject_Unadvise
+, thopsIOleObject_EnumAdvise
+, thopsIOleObject_GetMiscStatus
+, thopsIOleObject_SetColorScheme
+};
+THOP CONST * CONST apthopsIOleClientSite[] =
+{
+ thopsIOleClientSite_SaveObject
+, thopsIOleClientSite_GetMoniker
+, thopsIOleClientSite_GetContainer
+, thopsIOleClientSite_ShowObject
+, thopsIOleClientSite_OnShowWindow
+, thopsIOleClientSite_RequestNewObjectLayout
+};
+THOP CONST * CONST apthopsIRunnableObject[] =
+{
+ thopsIRunnableObject_GetRunningClass
+, thopsIRunnableObject_Run
+, thopsIRunnableObject_IsRunning
+, thopsIRunnableObject_LockRunning
+, thopsIRunnableObject_SetContainedObject
+};
+THOP CONST * CONST apthopsIParseDisplayName[] =
+{
+ thopsIParseDisplayName_ParseDisplayName
+};
+THOP CONST * CONST apthopsIOleContainer[] =
+{
+ thopsIOleContainer_ParseDisplayName
+, thopsIOleContainer_EnumObjects
+, thopsIOleContainer_LockContainer
+};
+THOP CONST * CONST apthopsIOleItemContainer[] =
+{
+ thopsIOleItemContainer_ParseDisplayName
+, thopsIOleItemContainer_EnumObjects
+, thopsIOleItemContainer_LockContainer
+, thopsIOleItemContainer_GetObject
+, thopsIOleItemContainer_GetObjectStorage
+, thopsIOleItemContainer_IsRunning
+};
+THOP CONST * CONST apthopsIOleAdviseHolder[] =
+{
+ thopsIOleAdviseHolder_Advise
+, thopsIOleAdviseHolder_Unadvise
+, thopsIOleAdviseHolder_EnumAdvise
+, thopsIOleAdviseHolder_SendOnRename
+, thopsIOleAdviseHolder_SendOnSave
+, thopsIOleAdviseHolder_SendOnClose
+};
+THOP CONST * CONST apthopsIOleLink[] =
+{
+ thopsIOleLink_SetUpdateOptions
+, thopsIOleLink_GetUpdateOptions
+, thopsIOleLink_SetSourceMoniker
+, thopsIOleLink_GetSourceMoniker
+, thopsIOleLink_SetSourceDisplayName
+, thopsIOleLink_GetSourceDisplayName
+, thopsIOleLink_BindToSource
+, thopsIOleLink_BindIfRunning
+, thopsIOleLink_GetBoundSource
+, thopsIOleLink_UnbindSource
+, thopsIOleLink_Update
+};
+THOP CONST * CONST apthopsIOleWindow[] =
+{
+ thopsIOleWindow_GetWindow
+, thopsIOleWindow_ContextSensitiveHelp
+};
+THOP CONST * CONST apthopsIOleInPlaceObject[] =
+{
+ thopsIOleInPlaceObject_GetWindow
+, thopsIOleInPlaceObject_ContextSensitiveHelp
+, thopsIOleInPlaceObject_InPlaceDeactivate
+, thopsIOleInPlaceObject_UIDeactivate
+, thopsIOleInPlaceObject_SetObjectRects
+, thopsIOleInPlaceObject_ReactivateAndUndo
+};
+THOP CONST * CONST apthopsIOleInPlaceActiveObject[] =
+{
+ thopsIOleInPlaceActiveObject_GetWindow
+, thopsIOleInPlaceActiveObject_ContextSensitiveHelp
+, thopsIOleInPlaceActiveObject_TranslateAccelerator
+, thopsIOleInPlaceActiveObject_OnFrameWindowActivate
+, thopsIOleInPlaceActiveObject_OnDocWindowActivate
+, thopsIOleInPlaceActiveObject_ResizeBorder
+, thopsIOleInPlaceActiveObject_EnableModeless
+};
+THOP CONST * CONST apthopsIOleInPlaceUIWindow[] =
+{
+ thopsIOleInPlaceUIWindow_GetWindow
+, thopsIOleInPlaceUIWindow_ContextSensitiveHelp
+, thopsIOleInPlaceUIWindow_GetBorder
+, thopsIOleInPlaceUIWindow_RequestBorderSpace
+, thopsIOleInPlaceUIWindow_SetBorderSpace
+, thopsIOleInPlaceUIWindow_SetActiveObject
+};
+THOP CONST * CONST apthopsIOleInPlaceFrame[] =
+{
+ thopsIOleInPlaceFrame_GetWindow
+, thopsIOleInPlaceFrame_ContextSensitiveHelp
+, thopsIOleInPlaceFrame_GetBorder
+, thopsIOleInPlaceFrame_RequestBorderSpace
+, thopsIOleInPlaceFrame_SetBorderSpace
+, thopsIOleInPlaceFrame_SetActiveObject
+, thopsIOleInPlaceFrame_InsertMenus
+, thopsIOleInPlaceFrame_SetMenu
+, thopsIOleInPlaceFrame_RemoveMenus
+, thopsIOleInPlaceFrame_SetStatusText
+, thopsIOleInPlaceFrame_EnableModeless
+, thopsIOleInPlaceFrame_TranslateAccelerator
+};
+THOP CONST * CONST apthopsIOleInPlaceSite[] =
+{
+ thopsIOleInPlaceSite_GetWindow
+, thopsIOleInPlaceSite_ContextSensitiveHelp
+, thopsIOleInPlaceSite_CanInPlaceActivate
+, thopsIOleInPlaceSite_OnInPlaceActivate
+, thopsIOleInPlaceSite_OnUIActivate
+, thopsIOleInPlaceSite_GetWindowContext
+, thopsIOleInPlaceSite_Scroll
+, thopsIOleInPlaceSite_OnUIDeactivate
+, thopsIOleInPlaceSite_OnInPlaceDeactivate
+, thopsIOleInPlaceSite_DiscardUndoState
+, thopsIOleInPlaceSite_DeactivateAndUndo
+, thopsIOleInPlaceSite_OnPosRectChange
+};
+THOP CONST * CONST apthopsIRpcChannelBuffer[] =
+{
+ thopsIRpcChannelBuffer_GetBuffer
+, thopsIRpcChannelBuffer_SendReceive
+, thopsIRpcChannelBuffer_FreeBuffer
+, thopsIRpcChannelBuffer_GetDestCtx
+, thopsIRpcChannelBuffer_IsConnected
+};
+THOP CONST * CONST apthopsIRpcProxyBuffer[] =
+{
+ thopsIRpcProxyBuffer_Connect
+, thopsIRpcProxyBuffer_Disconnect
+};
+THOP CONST * CONST apthopsIRpcStubBuffer[] =
+{
+ thopsIRpcStubBuffer_Connect
+, thopsIRpcStubBuffer_Disconnect
+, thopsIRpcStubBuffer_Invoke
+, thopsIRpcStubBuffer_IsIIDSupported
+, thopsIRpcStubBuffer_CountRefs
+, thopsIRpcStubBuffer_DebugServerQueryInterface
+, thopsIRpcStubBuffer_DebugServerRelease
+};
+THOP CONST * CONST apthopsIPSFactoryBuffer[] =
+{
+ thopsIPSFactoryBuffer_CreateProxy
+, thopsIPSFactoryBuffer_CreateStub
+};
+THOP CONST * CONST apthopsIRpcChannel[] =
+{
+ thopsIRpcChannel_GetStream
+, thopsIRpcChannel_Call
+, thopsIRpcChannel_GetDestCtx
+, thopsIRpcChannel_IsConnected
+};
+THOP CONST * CONST apthopsIRpcProxy[] =
+{
+ thopsIRpcProxy_Connect
+, thopsIRpcProxy_Disconnect
+};
+THOP CONST * CONST apthopsIRpcStub[] =
+{
+ thopsIRpcStub_Connect
+, thopsIRpcStub_Disconnect
+, thopsIRpcStub_Invoke
+, thopsIRpcStub_IsIIDSupported
+, thopsIRpcStub_CountRefs
+};
+THOP CONST * CONST apthopsIPSFactory[] =
+{
+ thopsIPSFactory_CreateProxy
+, thopsIPSFactory_CreateStub
+};
diff --git a/private/ole32/olethunk/olethk32/tlsthk.cxx b/private/ole32/olethunk/olethk32/tlsthk.cxx
new file mode 100644
index 000000000..628710327
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tlsthk.cxx
@@ -0,0 +1,171 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tlsthk.cxx
+//
+// Contents: Utility routines for logical thread data
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include "headers.cxx"
+#pragma hdrstop
+
+#define UNINITIALIZED_INDEX (0xffffffff)
+
+DWORD dwTlsThkIndex = UNINITIALIZED_INDEX;
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkGetData
+//
+// Synopsis: returns pointer to thread data
+//
+// Returns: pointer to threaddata
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+PThreadData TlsThkGetData(void)
+{
+ if (dwTlsThkIndex == UNINITIALIZED_INDEX)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: TLS slot used when uninitialized\n"));
+ }
+
+ PThreadData pThreaddata = (PThreadData) TlsGetValue(dwTlsThkIndex);
+
+ return pThreaddata;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkAlloc
+//
+// Synopsis: allocates a slot for thread data
+//
+// Returns: BOOL
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL TlsThkAlloc(void)
+{
+ thkDebugOut((DEB_THUNKMGR, "In TlsThkAlloc\n"));
+
+ // We must be uninitialized to call this routine
+ thkAssert(dwTlsThkIndex == UNINITIALIZED_INDEX);
+
+ dwTlsThkIndex = TlsAlloc();
+ if (dwTlsThkIndex == UNINITIALIZED_INDEX)
+ {
+ return FALSE;
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "Out TlsThkAlloc\n"));
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkInitialize
+//
+// Synopsis: allocates thread data and initialize slot
+//
+// Returns: Appropriate status code
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+HRESULT TlsThkInitialize(void)
+{
+ PThreadData pThreaddata;
+
+ thkDebugOut((DEB_THUNKMGR, "In TlsThkInitialize\n"));
+
+ thkAssert(dwTlsThkIndex != UNINITIALIZED_INDEX &&
+ "Tls slot not allocated.");
+
+ // We must be uninitialized to call this routine
+ thkAssert(TlsGetValue(dwTlsThkIndex) == 0);
+
+ pThreaddata = (PThreadData) LocalAlloc(LPTR, sizeof (ThreadData));
+ if(pThreaddata != NULL)
+ {
+ // Force construction since we allocated with LocalAlloc
+ pThreaddata->sa16.CStackAllocator::
+ CStackAllocator(&mmodel16Owned, 1024, 2);
+ pThreaddata->sa32.CStackAllocator::
+ CStackAllocator(&mmodel32, 8192, 8);
+
+ pThreaddata->pCThkMgr = 0;
+ pThreaddata->dwAppCompatFlags = 0;
+
+ TlsSetValue(dwTlsThkIndex, pThreaddata);
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "Out TlsThkInitialize\n"));
+
+ return (pThreaddata != NULL) ? NOERROR : E_OUTOFMEMORY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkUninitialize
+//
+// Synopsis: frees thread data and set it to NULL
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void TlsThkUninitialize(void)
+{
+ thkDebugOut((DEB_TLSTHK, "In TlsThkUninitialize\n"));
+
+ // Asserts if data is NULL
+ PThreadData pThreaddata = TlsThkGetData();
+
+ // BUGBUG - We should assert that the things in the ThreadData
+ // are freed up
+
+ if (pThreaddata != NULL)
+ {
+ // Stack allocators are cleaned up elsewhere
+ // because they require special treatment
+
+ if (pThreaddata->pDelayedRegs != NULL)
+ {
+ delete pThreaddata->pDelayedRegs;
+ }
+ LocalFree(pThreaddata);
+ }
+
+ TlsSetValue(dwTlsThkIndex, NULL);
+
+ thkDebugOut((DEB_TLSTHK, "Out TlsThkUninitialize\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkFree
+//
+// Synopsis: frees slot
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void TlsThkFree(void)
+{
+ thkAssert(dwTlsThkIndex != UNINITIALIZED_INDEX);
+
+ TlsFree( dwTlsThkIndex );
+
+ // We must set this to an invalid value so any further uses of the
+ // TLS slot will return NULL
+ dwTlsThkIndex = UNINITIALIZED_INDEX;
+}
diff --git a/private/ole32/olethunk/olethk32/tlsthk.hxx b/private/ole32/olethunk/olethk32/tlsthk.hxx
new file mode 100644
index 000000000..c2411133d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tlsthk.hxx
@@ -0,0 +1,85 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: TLSTHK.hxx
+//
+// Contents: Thunk routine utilities for tls
+//
+// History: 05-May-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TLSTHK_HXX__
+#define __TLSTHK_HXX__
+
+//
+// The following structures are used by CoRegisterClassObjectDelayed
+//
+typedef struct tagDelayedRegistration
+{
+ CLSID _clsid;
+ DWORD _dwRealKey;
+ LPUNKNOWN _punk;
+ DWORD _dwClsContext;
+ DWORD _flags;
+} DelayRegistration;
+
+#define MAX_DELAYED_REGISTRATIONS 8
+
+typedef struct tagDelayedRegistrationTable
+{
+ tagDelayedRegistrationTable()
+ {
+ memset(&_Entries,0,sizeof(_Entries));
+ }
+ DelayRegistration _Entries[MAX_DELAYED_REGISTRATIONS];
+} DelayedRegistrationTable;
+
+//
+// This is the per thread thunk manager state
+//
+
+typedef struct tagThreadData
+{
+ tagThreadData(DWORD cbBlock16,
+ DWORD cbAlign16,
+ DWORD cbBlock32,
+ DWORD cbAlign32)
+ : sa16(&mmodel16Owned, cbBlock16, cbAlign16),
+ sa32(&mmodel32, cbBlock32, cbAlign32),pDelayedRegs(NULL)
+ {
+ }
+
+ CStackAllocator sa16;
+ CStackAllocator sa32;
+ CThkMgr *pCThkMgr;
+ DWORD dwAppCompatFlags;
+ DelayedRegistrationTable *pDelayedRegs;
+} ThreadData, *PThreadData;
+
+HRESULT TlsThkInitialize();
+void TlsThkUninitialize();
+
+BOOL TlsThkAlloc();
+void TlsThkFree();
+
+#if DBG == 1
+PThreadData TlsThkGetData(void);
+#else
+extern DWORD dwTlsThkIndex;
+#define TlsThkGetData() ((PThreadData)TlsGetValue(dwTlsThkIndex))
+#endif
+
+#define TlsThkGetStack16() (&TlsThkGetData()->sa16)
+#define TlsThkGetStack32() (&TlsThkGetData()->sa32)
+
+#define TlsThkGetThkMgr() (TlsThkGetData()->pCThkMgr)
+#define TlsThkSetThkMgr(ptm) ((TlsThkGetData()->pCThkMgr) = (ptm))
+
+#define TlsThkGetAppCompatFlags() (TlsThkGetData()->dwAppCompatFlags)
+#define TlsThkSetAppCompatFlags(dw) \
+ ((TlsThkGetData()->dwAppCompatFlags) = (dw))
+
+#endif // #ifndef __TLSTHK_HXX__
diff --git a/private/ole32/olethunk/olethk32/vtblapi.cxx b/private/ole32/olethunk/olethk32/vtblapi.cxx
new file mode 100644
index 000000000..12f7ea492
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblapi.cxx
@@ -0,0 +1,123 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+VTBLFN CONST apfnApiFunctions[] =
+{
+ (VTBLFN)CoInitializeNot
+, (VTBLFN)CoUninitialize
+, (VTBLFN)CoGetClassObject
+, (VTBLFN)CoRegisterClassObjectNot
+, (VTBLFN)CoRevokeClassObjectNot
+, (VTBLFN)CoMarshalInterface
+, (VTBLFN)CoUnmarshalInterface
+, (VTBLFN)CoReleaseMarshalData
+, (VTBLFN)CoDisconnectObject
+, (VTBLFN)CoLockObjectExternal
+, (VTBLFN)CoGetStandardMarshal
+, (VTBLFN)CoIsHandlerConnected
+, (VTBLFN)CoFreeAllLibraries
+, (VTBLFN)CoFreeUnusedLibraries
+, (VTBLFN)CoCreateInstance
+, (VTBLFN)CLSIDFromString
+, (VTBLFN)CoIsOle1Class
+, (VTBLFN)ProgIDFromCLSID
+, (VTBLFN)CLSIDFromProgID
+, (VTBLFN)CoCreateGuid
+, (VTBLFN)CoFileTimeToDosDateTime
+, (VTBLFN)CoDosDateTimeToFileTime
+, (VTBLFN)CoFileTimeNow
+, (VTBLFN)CoRegisterMessageFilter
+, (VTBLFN)CoGetTreatAsClass
+, (VTBLFN)CoTreatAsClass
+, (VTBLFN)DllGetClassObjectWOW
+, (VTBLFN)StgCreateDocfile
+, (VTBLFN)StgCreateDocfileOnILockBytes
+, (VTBLFN)StgOpenStorage
+, (VTBLFN)StgOpenStorageOnILockBytes
+, (VTBLFN)StgIsStorageFile
+, (VTBLFN)StgIsStorageILockBytes
+, (VTBLFN)StgSetTimes
+, (VTBLFN)CreateDataAdviseHolder
+, (VTBLFN)CreateDataCache
+, (VTBLFN)BindMoniker
+, (VTBLFN)MkParseDisplayName
+, (VTBLFN)MonikerRelativePathTo
+, (VTBLFN)MonikerCommonPrefixWith
+, (VTBLFN)CreateBindCtx
+, (VTBLFN)CreateGenericComposite
+, (VTBLFN)GetClassFile
+, (VTBLFN)CreateFileMoniker
+, (VTBLFN)CreateItemMoniker
+, (VTBLFN)CreateAntiMoniker
+, (VTBLFN)CreatePointerMoniker
+, (VTBLFN)GetRunningObjectTable
+, (VTBLFN)ReadClassStg
+, (VTBLFN)WriteClassStg
+, (VTBLFN)ReadClassStm
+, (VTBLFN)WriteClassStm
+, (VTBLFN)WriteFmtUserTypeStg
+, (VTBLFN)ReadFmtUserTypeStg
+, (VTBLFN)OleInitializeNot
+, (VTBLFN)OleUninitialize
+, (VTBLFN)OleQueryLinkFromData
+, (VTBLFN)OleQueryCreateFromData
+, (VTBLFN)OleCreate
+, (VTBLFN)OleCreateFromData
+, (VTBLFN)OleCreateLinkFromData
+, (VTBLFN)OleCreateStaticFromData
+, (VTBLFN)OleCreateLink
+, (VTBLFN)OleCreateLinkToFile
+, (VTBLFN)OleCreateFromFile
+, (VTBLFN)OleLoad
+, (VTBLFN)OleSave
+, (VTBLFN)OleLoadFromStream
+, (VTBLFN)OleSaveToStream
+, (VTBLFN)OleSetContainedObject
+, (VTBLFN)OleNoteObjectVisible
+, (VTBLFN)RegisterDragDrop
+, (VTBLFN)RevokeDragDrop
+, (VTBLFN)DoDragDrop
+, (VTBLFN)OleSetClipboard
+, (VTBLFN)OleGetClipboard
+, (VTBLFN)OleFlushClipboard
+, (VTBLFN)OleIsCurrentClipboard
+, (VTBLFN)OleCreateMenuDescriptor
+, (VTBLFN)OleSetMenuDescriptor
+, (VTBLFN)OleDestroyMenuDescriptor
+, (VTBLFN)OleDraw
+, (VTBLFN)OleRun
+, (VTBLFN)OleIsRunning
+, (VTBLFN)OleLockRunning
+, (VTBLFN)CreateOleAdviseHolder
+, (VTBLFN)OleCreateDefaultHandler
+, (VTBLFN)OleCreateEmbeddingHelper
+, (VTBLFN)OleRegGetUserTypeNot
+, (VTBLFN)OleRegGetMiscStatus
+, (VTBLFN)OleRegEnumFormatEtc
+, (VTBLFN)OleRegEnumVerbs
+, (VTBLFN)OleConvertIStorageToOLESTREAM
+, (VTBLFN)OleConvertOLESTREAMToIStorage
+, (VTBLFN)OleConvertIStorageToOLESTREAMEx
+, (VTBLFN)OleConvertOLESTREAMToIStorageEx
+, (VTBLFN)OleDoAutoConvert
+, (VTBLFN)OleGetAutoConvert
+, (VTBLFN)OleSetAutoConvert
+, (VTBLFN)GetConvertStg
+, (VTBLFN)SetConvertStg
+, (VTBLFN)ReadOleStg
+, (VTBLFN)WriteOleStg
+};
diff --git a/private/ole32/olethunk/olethk32/vtblifn.cxx b/private/ole32/olethunk/olethk32/vtblifn.cxx
new file mode 100644
index 000000000..b6fb85ea4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblifn.cxx
@@ -0,0 +1,766 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblifn.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkMethod3216_48(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[48];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_47(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[47];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_46(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[46];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_45(
+ THUNK3216OBJ *ptoThis32,
+ SIZEL Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(SIZEL *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[45];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_44(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ WORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(WORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[44];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_43(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[43];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_42(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[42];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_41(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[41];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_40(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[40];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_39(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[39];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_38(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[38];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_37(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[37];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_36(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[36];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_35(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[35];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_34(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[34];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_33(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ SIZEL Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(SIZEL *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[33];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_32(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ SIZEL Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(SIZEL *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[32];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_31(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ SIZEL Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(SIZEL *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[31];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_30(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[30];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_29(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[29];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_28(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6,
+ DWORD Arg7,
+ DWORD Arg8,
+ DWORD Arg9,
+ DWORD Arg10
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[44];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ *(DWORD *)(bArgs+28) = Arg7;
+ *(DWORD *)(bArgs+32) = Arg8;
+ *(DWORD *)(bArgs+36) = Arg9;
+ *(DWORD *)(bArgs+40) = Arg10;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[28];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_27(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[27];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_26(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[26];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_25(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[25];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_24(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[24];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_23(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[23];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_22(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[22];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_21(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[21];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_20(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[20];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_19(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[19];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_18(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[18];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_17(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[17];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_16(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+20) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[16];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_15(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+20) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[15];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_14(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[14];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_13(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[13];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_12(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[12];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_11(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[11];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_10(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[10];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_9(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[9];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_8(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[8];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_7(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[7];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_6(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[6];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_5(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[5];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_4(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[4];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_3(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[3];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_2(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[2];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_1(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[1];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_0(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[0];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
diff --git a/private/ole32/olethunk/olethk32/vtblint.cxx b/private/ole32/olethunk/olethk32/vtblint.cxx
new file mode 100644
index 000000000..cd1e9b62b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblint.cxx
@@ -0,0 +1,678 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THUNK3216FN CONST tfnIUnknown[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+};
+THUNK3216FN CONST tfnIClassFactory[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIMarshal[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_7
+, (THUNK3216FN)ThunkMethod3216_8
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIStdMarshalInfo[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIMessageFilter[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_10
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIExternalConnection[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIEnumString[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumUnknown[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumSTATSTG[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnILockBytes[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_12
+, (THUNK3216FN)ThunkMethod3216_13
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_14
+, (THUNK3216FN)ThunkMethod3216_15
+, (THUNK3216FN)ThunkMethod3216_16
+, (THUNK3216FN)ThunkMethod3216_2
+};
+THUNK3216FN CONST tfnIStream[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_17
+, (THUNK3216FN)ThunkMethod3216_14
+, (THUNK3216FN)ThunkMethod3216_18
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_16
+, (THUNK3216FN)ThunkMethod3216_15
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_19
+, (THUNK3216FN)ThunkMethod3216_20
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_10
+, (THUNK3216FN)ThunkMethod3216_22
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_26
+};
+THUNK3216FN CONST tfnIRootStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIEnumFORMATETC[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumSTATDATA[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIDataObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIViewObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_28
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIViewObject2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_28
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_23
+};
+THUNK3216FN CONST tfnIAdviseSink[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIAdviseSink2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIDataAdviseHolder[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIOleCache[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIOleCache2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIOleCacheControl[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIDropTarget[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_31
+, (THUNK3216FN)ThunkMethod3216_32
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_33
+};
+THUNK3216FN CONST tfnIDropSource[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIPersist[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIPersistStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_6
+};
+THUNK3216FN CONST tfnIPersistStream[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIPersistFile[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIBindCtx[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIMoniker[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_22
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIRunningObjectTable[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIEnumMoniker[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIEnumOLEVERB[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIOleObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_38
+, (THUNK3216FN)ThunkMethod3216_39
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+};
+THUNK3216FN CONST tfnIOleClientSite[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+};
+THUNK3216FN CONST tfnIRunnableObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIParseDisplayName[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+};
+THUNK3216FN CONST tfnIOleContainer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+};
+THUNK3216FN CONST tfnIOleItemContainer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIOleAdviseHolder[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIOleLink[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIOleWindow[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIOleInPlaceObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_6
+};
+THUNK3216FN CONST tfnIOleInPlaceActiveObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIOleInPlaceUIWindow[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_41
+};
+THUNK3216FN CONST tfnIOleInPlaceFrame[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_44
+};
+THUNK3216FN CONST tfnIOleInPlaceSite[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_45
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_46
+, (THUNK3216FN)ThunkMethod3216_47
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIRpcChannelBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_39
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcProxyBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcStubBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_47
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIPSFactoryBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_37
+};
+THUNK3216FN CONST tfnIRpcChannel[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcProxy[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcStub[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_47
+};
+THUNK3216FN CONST tfnIPSFactory[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_37
+};