4066 lines
120 KiB
C++
4066 lines
120 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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
|
|
};
|
|
|