Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4065 lines
116 KiB

//+---------------------------------------------------------------------------
//
// 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, "%sIn ExThop3216: %s (0x%02X), s16 %p, s32 %p\n",
NestingLevelString(),
ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
pti->s32.pbCurrent));
DebugIncrementNestingLevel();
// Local variable
DWORD dwRet;
// Sanity check
thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
dwRet = (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti);
DebugDecrementNestingLevel();
thkDebugOut((DEB_THOPS, "%sOut ExThop3216\n", NestingLevelString()));
return(dwRet);
}
#endif
#if DBG == 1
DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti)
{
thkDebugOut((DEB_THOPS, "%sIn ExEnumThop3216: %s (0x%02X), s16 %p, s32 %p\n",
NestingLevelString(),
EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
pti->s32.pbCurrent));
DebugIncrementNestingLevel();
// Local variable
DWORD dwRet;
dwRet = (*aThopEnumFunctions3216[*(pti)->pThop])(pti);
DebugDecrementNestingLevel();
thkDebugOut((DEB_THOPS, "%sOut ExEnumThop3216\n", NestingLevelString()));
return(dwRet);
}
#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, "%sIn3216 LPSTR %p -> %p '%s'\n",
NestingLevelString(), 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 passed to the 16-bit world
//
// Returns: Status code
//
// History: Mar 14,97 Gopalk Rewritten to support aggregation and
// proper thunking of IN/OUT interfaces
//
// Notes: Assumes pti->pThop is adjusted by caller
//----------------------------------------------------------------------------
DWORD ThunkInterface3216(THUNKINFO *pti, IIDIDX iidx, THOP thop, VPVOID vpvOuter)
{
// Local variables
DWORD dwResult, dwStatus;
void *pv;
VPVOID vpvOutParam;
VPVOID vpvThis16In, vpvThis16Out;
IUnknown *punkOut;
IUnknown *punkIn;
THUNK3216OBJ *ptoPreAlloc = NULL;
PROXYHOLDER *pph = NULL;
PROXYHOLDER *pAggHolder = NULL;
SAggHolder aggHolderNode;
BOOL bUnlinkAggHolder = FALSE;
// Validate the IID of the interface
thkAssert(IIDIDX_IS_IID(iidx) ||
(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) < THI_COUNT));
// Initialize
dwResult = (DWORD) S_OK;
vpvOutParam = NULL;
vpvThis16In = NULL;
// Retrieve interface pointer
GET_STACK32(pti, pv, void *);
// Check for valid OUT parameter. It also verifies IN-OUT case as well
if((thop & THOP_OUT) && pv) {
if(IsBadReadPtr(pv, sizeof(void *)) || IsBadWritePtr(pv, sizeof(void *))) {
thkDebugOut((DEB_WARN, "WARNING: failing - bad pointer %p\n", pv));
return (DWORD) E_INVALIDARG;
}
// Check if the interface needs to be thunked IN as well.
// In other words, IN-OUT paramenter case
if(thop & THOP_IN)
punkIn = *(IUnknown **)pv;
else
punkIn = NULL;
}
else {
// It must be IN parameter or a NULL OUT parameter
punkIn = (IUnknown *)pv;
}
// Check if interface needs to be thunked IN
if(thop & THOP_IN) {
if(punkIn) {
// Validate the interface
if(IsValidInterface(punkIn)) {
if((thop & THOP_OPMASK) == THOP_UNKOUTER) {
// Aggregation being carried out
// Assert that it is only being thunked IN
thkAssert(!(thop & THOP_OUT));
thkAssert(iidx == THI_IUnknown);
// Either find the actual 16-bit identity or generate a
// new 16-bit proxy identity for the 32-bit identity
vpvThis16In = pti->pThkMgr->CreateOuter16(punkIn, &pAggHolder, &dwStatus);
aggHolderNode.pph = pAggHolder;
TlsThkLinkAggHolder(&aggHolderNode);
bUnlinkAggHolder = TRUE;
// We use this pAggHolder for proxies of inner unk(s). Since
// we cannot put it in the proxy table (as it is private
// and we do not want other thunk calls to use it), we put
// it in a linked list in the TLS. The holder gets used by
// calls to FindAggregate() when the pUnkInner is being
// thunked out. The holder is revoked from the list when
// the ThunkInterface call for the pUnkOuter unwinds.
}
else {
// Find/Generate the proxy for the 32-bit interface
// to be thunked IN
vpvThis16In = pti->pThkMgr->FindProxy1632(NULL, punkIn, NULL,
iidx, &dwStatus);
}
if(vpvThis16In) {
thkAssert(!((thop & THOP_OPMASK) == THOP_UNKOUTER) ||
(dwStatus == FST_CREATED_NEW) ||
(dwStatus == FST_SHORTCUT));
}
else {
thkDebugOut((DEB_WARN, "WARNING: failing - Can't create proxy for %p\n",
punkIn));
return (DWORD) E_OUTOFMEMORY;
}
}
else {
thkDebugOut((DEB_WARN, "WARNING: failing - invalid interface %p\n",
punkIn));
return (DWORD) E_INVALIDARG;
}
}
else {
// No interface to be thunked IN
vpvThis16In = NULL;
}
thkDebugOut((DEB_ARGS, "%sIn3216 %s %p -> %p\n",
NestingLevelString(), IidIdxString(iidx),
punkIn, vpvThis16In));
}
// Check if interface needs to be thunked OUT
if((thop & THOP_OUT) && pv) {
// Preallocate a proxy for the out parameter
ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx);
if(ptoPreAlloc) {
// Allocate space for OUT parameter from the 16-bit heap
vpvOutParam = STACKALLOC16(sizeof(VPVOID));
if(vpvOutParam) {
// Assert that no interface is being thunked IN for
// pure OUT parameter case
thkAssert((thop & THOP_IN) || !vpvThis16In);
// Assign the interface being thunked IN
*FIXVDMPTR(vpvOutParam, VPVOID) = vpvThis16In;
RELVDMPTR(vpvOutParam);
// Push the OUT/IN-OUT parameter onto the stack
TO_STACK16(pti, vpvOutParam, VPVOID);
}
else {
thkDebugOut((DEB_WARN, "WARNING: failing - Allocation on 16-bit heap failed\n"));
dwResult = (DWORD)E_OUTOFMEMORY;
}
}
else {
thkDebugOut((DEB_WARN, "WARNING: failing - Cannot allocate proxy\n"));
dwResult = (DWORD) E_OUTOFMEMORY;
}
}
else {
// Assert invariant
thkAssert((pv && vpvThis16In) || (!pv && !vpvThis16In));
// Push the IN parameter onto the stack
TO_STACK16(pti, vpvThis16In, VPVOID);
}
if(SUCCEEDED((SCODE)dwResult)) {
// Execute the next THOP operation
dwResult = EXECUTE_THOP3216(pti);
}
if((thop & THOP_OUT) && pv) {
punkOut = NULL;
if(SUCCEEDED((SCODE)dwResult)) {
// Obtain the 16-bit interface to be thunked OUT
vpvThis16Out = *FIXVDMPTR(vpvOutParam, VPVOID);
RELVDMPTR(vpvOutParam);
// Check if a 16-bit interface was returned
if(vpvThis16Out) {
// Obtain 32-bit proxy for the 16-bit interface
if(vpvOuter) {
//Get the holder that was linked into TLS when the pUnkOuter
//was being thunked in.
pAggHolder = (TlsThkGetAggHolder())->pph;
punkOut = pti->pThkMgr->FindAggregate3216(ptoPreAlloc, vpvOuter,
vpvThis16Out, iidx, pAggHolder,
&dwStatus);
}
else {
punkOut = pti->pThkMgr->FindProxy3216(ptoPreAlloc, vpvThis16Out,
NULL, iidx, FALSE, &dwStatus);
}
if(punkOut) {
if((thop & THOP_OPMASK) == THOP_UNKINNER) {
if (dwStatus != FST_SHORTCUT) {
// Obtain the holder
pph = ((THUNK3216OBJ *)punkOut)->pphHolder ;
// Assert invariants in debug builds
thkAssert(pph->dwFlags & PH_AGGREGATEE);
thkAssert(dwStatus == FST_CREATED_NEW);
// Mark the proxy as representing inner unknown
((THUNK3216OBJ *)punkOut)->grfFlags = PROXYFLAG_PUNKINNER;
}
}
// Either the preallocated proxy was used and freed
ptoPreAlloc = NULL;
}
else {
dwResult = (DWORD)E_OUTOFMEMORY;
}
// Release the actual 16-bit interface. If a proxy to the
// 16-bit interface could not be created above, this could
// be the last release on the 16-bit interface
ReleaseOnObj16(vpvThis16Out);
}
}
// Set the OUT parameter
*(void **)pv = (void *)punkOut;
thkDebugOut((DEB_ARGS, "%sOut3216 %s %p -> %p\n",
NestingLevelString(), IidIdxString(iidx),
vpvThis16Out, punkOut));
}
if(vpvThis16In) {
if((thop & THOP_INOUT) == THOP_INOUT) {
// IN-OUT parameter.
thkAssert(punkIn);
// Release the 32-bit side interface
punkIn->Release();
}
else {
// Just an IN parameter
thkAssert(thop & THOP_IN);
#if DBG==1
// Ensure that the following is not the last release
// on the IN parameter
THKSTATE thkstate;
// Remember the current thunk state
thkstate = pti->pThkMgr->GetThkState();
// Set the thunk state to THKSTATE_VERIFYINPARAM
pti->pThkMgr->SetThkState(THKSTATE_VERIFY32INPARAM);
#endif
// Release the 16-bit side interface
ReleaseOnObj16(vpvThis16In);
#if DBG==1
// Restore previous thunk state
pti->pThkMgr->SetThkState(thkstate);
#endif
}
// We should never receive a call IRpcStubBuffer::DebugServerRelease
Win4Assert((thop & THOP_OPMASK) != THOP_IFACECLEAN);
}
// Cleanup
if(ptoPreAlloc) {
// Free preallocated proxy as it was not used
pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
}
if(vpvOutParam) {
// Free the space created on the 16-bit for the OUT parameter
STACKFREE16(vpvOutParam, sizeof(VPVOID));
}
if (bUnlinkAggHolder) {
TlsThkUnlinkAggHolder();
}
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)
{
// Obtain the outer unknown that is being passed to the 16 bit world
thopWeakOffset = *pti->pThop++;
INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
if(vpvOuter) {
// Aggregation across 32-16 boundary
// Assert that the IID requested is IID_IUnknown
thkAssert(iidx == THI_IUnknown ||
(pti->iidx==THI_IPSFactoryBuffer && pti->dwMethod==3));
// Change thop to indicate that inner unknown is being thunked
if(iidx == THI_IUnknown)
thop = (thop & THOP_IOMASK) | THOP_UNKINNER;
}
}
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, NULL,
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)
{
// Release the 16-bit interface as it is an IN parameter
ReleaseOnObj16(vpunk16);
}
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:
// Thunking an interface as a return value is completly broken
// First, such an interface needs to be thunked as an OUT parameter
// which I am fixing below. Second, the IID of the interface being
// thunked needs to be in the THOP string for proper thunking of
// interface. The only known case where an interface is returned
// is IRpcStubBuffer::IsIIDSupported() and the interface returned
// is of type IRpcStubBuffer, not IUnknown. As this method is not
// used in the curremt COM code, I am not changing THOP strings
// to reflect the IID of the interface being thunked
// Gopalk Mar 27, 97
if (dwResult != 0)
{
// BUGBUG - What if another thop failed and returned an HRESULT?
// This will break
VPVOID vpvUnk = (VPVOID) dwResult;
dwResult =
(DWORD)pti->pThkMgr->FindProxy3216(ptoPreAlloc, dwResult, NULL,
iidx, FALSE, NULL);
// Release actual interface as it is an OUT parameter
// This could be the last release on the interface if the
// above call failed;
ReleaseOnObj16(vpvUnk);
thkAssert(dwResult);
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
|| thopOp == THOP_UNKOUTER);
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);
thkAssert(thopOp != THOP_UNKOUTER || iidx == THI_IUnknown);
vpvOuter = 0;
if (thopOp == THOP_IFACEOWNER)
{
// Obtain the outer unknown that is being passed to the 16 bit world
thopWeakOffset = *pti->pThop++;
INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
if(vpvOuter) {
// Aggregation across 32-16 boundary
// Assert invariants
thkAssert(iidx == THI_IRpcProxyBuffer || iidx == THI_IRpcProxy);
// Change thop to indicate that inner unknown is being thunked
thop = (thop & THOP_IOMASK) | THOP_UNKINNER;
}
}
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");
alias = 0;
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_FN(IFACE), // x UNKOUTER
Thop_ERROR_3216, // x UNKINNER
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 = 0;
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, NULL,
INDEX_IIDIDX(THI_IUnknown),
FALSE, NULL);
// Release the actual 16-bit IUnknown as it is an OUT parameter
// This could be the last release on the interface if the
// above call failed;
ReleaseOnObj16(vpunknown16);
if(!punkThis32) {
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;
if(lpunknown32) {
// Release the proxy to 16-bit interface
ReleaseProxy3216((THUNK3216OBJ *) lpunknown32);
}
}
//+---------------------------------------------------------------------------
//
// 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, NULL,
INDEX_IIDIDX(THI_IAdviseSink2),
FALSE, NULL);
// Release the actual 16-bit IAdviseSink as it is an OUT parameter
// This could be the last release on the interface if the
// above call failed;
ReleaseOnObj16(vpadv16);
if(!punkThis32) {
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) {
// Release the proxy to 16-bit interface
ReleaseProxy3216((THUNK3216OBJ *) (lpstatdata32->pAdvSink));
}
}
//+---------------------------------------------------------------------------
//
// 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, NULL,
INDEX_IIDIDX(THI_IMoniker),
FALSE, NULL);
// Release the actual 16-bit IMoniker as it is an OUT parameter
// This could be the last release on the interface if the
// above call failed;
ReleaseOnObj16(vpmoniker16);
if(!punkThis32) {
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;
if(lpmoniker32) {
// Release the proxy to 16-bit interface
ReleaseProxy3216((THUNK3216OBJ *) lpmoniker32);
}
}
//+---------------------------------------------------------------------------
//
// 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
};