mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4317 lines
125 KiB
4317 lines
125 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
|
//
|
|
// File: thop16.cxx
|
|
//
|
|
// Contents: Thop implementations for 16->32
|
|
//
|
|
// History: 22-Feb-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <ole2.h>
|
|
#include <valid.h>
|
|
#include <string.h>
|
|
|
|
#include "struct16.hxx"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EXECUTE_THOP1632, public
|
|
//
|
|
// Synopsis: Debugging version of thop dispatch routine
|
|
//
|
|
// Arguments: [pti] - Thunking info
|
|
//
|
|
// Returns: Appropriate status
|
|
//
|
|
// History: 24-Feb-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
DWORD EXECUTE_THOP1632(THUNKINFO *pti)
|
|
{
|
|
thkDebugOut((DEB_THOPS, "%sIn ExThop1632: %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 = (*aThopFunctions1632[*((pti)->pThop) & THOP_OPMASK])(pti);
|
|
|
|
DebugDecrementNestingLevel();
|
|
thkDebugOut((DEB_THOPS, "%sOut ExThop1632\n", NestingLevelString()));
|
|
return(dwRet);
|
|
}
|
|
#endif
|
|
|
|
#if DBG == 1
|
|
DWORD EXECUTE_ENUMTHOP1632(THUNKINFO *pti)
|
|
{
|
|
thkDebugOut((DEB_THOPS, "%sIn ExEnumThop1632: %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 = (*aThopEnumFunctions1632[*(pti)->pThop])(pti);
|
|
|
|
DebugDecrementNestingLevel();
|
|
thkDebugOut((DEB_THOPS, "%sOut ExEnumThop1632\n", NestingLevelString()));
|
|
return(dwRet);
|
|
}
|
|
#endif
|
|
|
|
// Generated by the tool, in tc1632.cxx
|
|
DWORD ThunkCall1632( THUNKINFO * );
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FixedThopHandler, public
|
|
//
|
|
// Synopsis: Generic function which handles the high-level details
|
|
// of thop execution for thops that operate on known-size
|
|
// data
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [thop] - Thop being executed
|
|
// [cb16] - 16-bit size
|
|
// [pfn1632] - 16->32 conversion routine
|
|
// [cb32] - 32-bit size
|
|
// [pfn3216] - 32->16 conversion routine
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
// Notes: Automatically increments pThop
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD FixedThopHandler1632(THUNKINFO *pti,
|
|
THOP thop,
|
|
UINT cb16,
|
|
FIXEDHANDLERROUTINE pfn1632,
|
|
UINT cb32,
|
|
FIXEDHANDLERROUTINE pfn3216)
|
|
{
|
|
DWORD dwResult;
|
|
VPVOID vp16;
|
|
BYTE *pb16;
|
|
BYTE *pb32;
|
|
|
|
if ((thop & (THOP_IN | THOP_OUT)) != 0)
|
|
{
|
|
pb32 = NULL;
|
|
|
|
GET_STACK16(pti, vp16, VPVOID);
|
|
if ( vp16 != 0 )
|
|
{
|
|
pb16 = (BYTE *)ValidatePtr16(pti, vp16, cb16, thop);
|
|
if (pb16 != NULL)
|
|
{
|
|
pb32 = (BYTE *)STACKALLOC32(cb32);
|
|
if (pb32 == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else if ((thop & THOP_IN) != 0)
|
|
{
|
|
(pfn1632)(pb16, pb32, cb16, cb32);
|
|
}
|
|
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, pb32, BYTE *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ((thop & THOP_OUT) != 0 && vp16 != 0)
|
|
{
|
|
pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
|
|
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
(pfn3216)(pb32, pb16, cb32, cb16);
|
|
}
|
|
else if ((thop & THOP_IN) == 0)
|
|
{
|
|
// Zero out-only parameters on failure
|
|
memset(pb16, 0, cb16);
|
|
}
|
|
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
|
|
if (pb32 != NULL)
|
|
{
|
|
STACKFREE32(pb32, cb32);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(pfn1632)(PTR_STACK16(&pti->s16, cb16), PTR_STACK32(&pti->s32),
|
|
cb16, cb32);
|
|
SKIP_STACK16(&pti->s16, cb16);
|
|
SKIP_STACK32(&pti->s32, cb32);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Handler-based thunks
|
|
//
|
|
// These thunks use the fixed-size generic thop handler to do their work
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Handle straight copy
|
|
DWORD Thop_Copy_1632(THUNKINFO *pti)
|
|
{
|
|
THOP thopSize;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
|
|
|
|
thopSize = *++pti->pThop;
|
|
return FixedThopHandler1632(pti,
|
|
*(pti->pThop-1),
|
|
thopSize, FhCopyMemory,
|
|
thopSize, FhCopyMemory);
|
|
}
|
|
|
|
DWORD Thop_ShortToLong_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(SHORT), FhShortToLong,
|
|
sizeof(LONG), FhLongToShort);
|
|
}
|
|
|
|
DWORD Thop_WordToDword_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(WORD), FhWordToDword,
|
|
sizeof(DWORD), FhDwordToWord);
|
|
}
|
|
|
|
DWORD Thop_GdiHandle_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(HAND16), FhGdiHandle1632,
|
|
sizeof(HANDLE), FhGdiHandle3216);
|
|
}
|
|
|
|
DWORD Thop_UserHandle_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(HAND16), FhUserHandle1632,
|
|
sizeof(HANDLE), FhUserHandle3216);
|
|
}
|
|
|
|
DWORD Thop_HACCEL_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(HAND16), FhHaccel1632,
|
|
sizeof(HANDLE), FhHaccel3216);
|
|
}
|
|
|
|
DWORD Thop_HTASK_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(HAND16), FhHtask1632,
|
|
sizeof(HANDLE), FhHtask3216);
|
|
}
|
|
|
|
DWORD Thop_HRESULT_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(HRESULT), FhHresult1632,
|
|
sizeof(HRESULT), FhHresult3216);
|
|
}
|
|
|
|
DWORD Thop_NULL_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(void *), FhNull,
|
|
sizeof(void *), FhNull);
|
|
}
|
|
|
|
DWORD Thop_RECT_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(RECT16), FhRect1632,
|
|
sizeof(RECT), FhRect3216);
|
|
}
|
|
|
|
DWORD Thop_BINDOPTS_1632( THUNKINFO *pti )
|
|
{
|
|
VPVOID vpbo16;
|
|
BIND_OPTS UNALIGNED *pbo;
|
|
UINT cb;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
|
|
|
|
PEEK_STACK16(pti, vpbo16, VPVOID);
|
|
pbo = (BIND_OPTS UNALIGNED *)GetReadPtr16(pti, vpbo16, sizeof(BIND_OPTS));
|
|
if (pbo != NULL)
|
|
{
|
|
cb = pbo->cbStruct;
|
|
WOWRELVDMPTR(vpbo16);
|
|
}
|
|
else
|
|
{
|
|
// Doesn't really matter, since pti->scResult was set to error
|
|
// by GetReadPtr16
|
|
cb = sizeof(BIND_OPTS);
|
|
}
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
cb, FhCopyMemory,
|
|
cb, FhCopyMemory);
|
|
}
|
|
|
|
DWORD Thop_SIZE_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(SIZE16), FhSize1632,
|
|
sizeof(SIZE), FhSize3216);
|
|
}
|
|
|
|
DWORD Thop_MSG_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
|
|
|
|
return FixedThopHandler1632(pti,
|
|
*pti->pThop,
|
|
sizeof(MSG16), FhMsg1632,
|
|
sizeof(MSG), FhMsg3216);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_ERROR_1632, public
|
|
//
|
|
// Synopsis: Any Thop type which should just fail with an error
|
|
// should go be directed here.
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_ERROR_1632 ( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
|
|
|
|
thkAssert( FALSE && "Hey we hit an ERROR Thop in 16->32" );
|
|
|
|
return (DWORD)E_UNEXPECTED;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ThunkInString1632, public
|
|
//
|
|
// Synopsis: Converts an in-parameter string
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Aug-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD ThunkInString1632(THUNKINFO *pti)
|
|
{
|
|
DWORD dwResult;
|
|
VPSTR vpstr;
|
|
LPOLESTR lpstrDest;
|
|
OLECHAR *ptcStackText;
|
|
|
|
dwResult = (DWORD)S_OK;
|
|
ptcStackText = NULL;
|
|
|
|
GET_STACK16(pti, vpstr, VPSTR);
|
|
|
|
if (vpstr == 0)
|
|
{
|
|
lpstrDest = NULL;
|
|
}
|
|
else
|
|
{
|
|
ptcStackText = (OLECHAR *)STACKALLOC32(CWCSTRINGPREALLOC*
|
|
sizeof(OLECHAR));
|
|
if (ptcStackText == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
lpstrDest = Convert_VPSTR_to_LPOLESTR( pti, vpstr, ptcStackText,
|
|
CWCSTRINGPREALLOC );
|
|
}
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "In1632 LPSTR: %p -> %p '%ws'\n",
|
|
vpstr, lpstrDest, lpstrDest));
|
|
|
|
TO_STACK32(pti, lpstrDest, LPOLESTR );
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if (lpstrDest != NULL)
|
|
{
|
|
Convert_VPSTR_to_LPOLESTR_free( ptcStackText, lpstrDest );
|
|
}
|
|
|
|
if (ptcStackText != NULL)
|
|
{
|
|
STACKFREE32(ptcStackText, CWCSTRINGPREALLOC*sizeof(OLECHAR));
|
|
}
|
|
|
|
return( dwResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_LPSTR_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_LPSTR_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
|
|
//
|
|
// We have only input LPSTRs
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
|
|
"LPSTR must be input only!" );
|
|
|
|
return ThunkInString1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertTaskString3216, public
|
|
//
|
|
// Synopsis: Converts a task-memory string
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [pos32] - String
|
|
// [vpstrPreAlloc] - Preallocated string or NULL
|
|
// [cchPreAlloc] - Preallocated size or zero
|
|
// [pvpstr16] - String
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pti]
|
|
// [pvpstr16]
|
|
//
|
|
// History: 14-May-94 DrewB Created
|
|
//
|
|
// Notes: Frees preallocation if successful and:
|
|
// Name is too large or
|
|
// Name is NULL
|
|
//
|
|
// Always frees source string if non-zero and valid
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertTaskString3216(THUNKINFO *pti,
|
|
LPOLESTR pos32,
|
|
VPSTR vpstrPreAlloc,
|
|
UINT cchPreAlloc,
|
|
VPSTR UNALIGNED *pvpstr16)
|
|
{
|
|
VPVOID vpstr16;
|
|
UINT cch;
|
|
SCODE sc;
|
|
|
|
sc = S_OK;
|
|
|
|
if (pos32 == NULL)
|
|
{
|
|
vpstr16 = 0;
|
|
}
|
|
else
|
|
{
|
|
if (IsBadStringPtrW(pos32, CCHMAXSTRING))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
cch = lstrlenW(pos32)+1;
|
|
|
|
if (cch > cchPreAlloc)
|
|
{
|
|
// Our prealloc buffer is too small, so try and get a
|
|
// new one
|
|
|
|
// Allow for each Unicode character to take two
|
|
// bytes in case of multibyte expansion
|
|
vpstr16 = (VPSTR)TaskMalloc16( cch*2 );
|
|
if (vpstr16 == 0)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vpstr16 = vpstrPreAlloc;
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
sc = Convert_LPOLESTR_to_VPSTR(pos32, vpstr16, cch, cch*2);
|
|
if (FAILED(sc) && vpstr16 != vpstrPreAlloc)
|
|
{
|
|
TaskFree16(vpstr16);
|
|
}
|
|
}
|
|
|
|
TaskFree32(pos32);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
// If there was a preallocated string we didn't use,
|
|
// free it
|
|
if (vpstrPreAlloc != 0 && vpstrPreAlloc != vpstr16)
|
|
{
|
|
TaskFree16(vpstrPreAlloc);
|
|
}
|
|
|
|
*pvpstr16 = vpstr16;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ThunkOutString1632, public
|
|
//
|
|
// Synopsis: Converts an out param string or filename
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
// [fFile] - Filename or plain string
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Aug-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD ThunkOutString1632(THUNKINFO *pti,
|
|
BOOL fFile)
|
|
{
|
|
DWORD dwResult;
|
|
VPVOID vpvpstr16;
|
|
VPSTR vpstr16;
|
|
VPSTR UNALIGNED *lpvpstr16;
|
|
LPOLESTR *lplpstr32;
|
|
LPOLESTR lpstr = NULL;
|
|
|
|
GET_STACK16(pti, vpvpstr16, VPSTR);
|
|
|
|
lplpstr32 = NULL;
|
|
if ( vpvpstr16 != 0 )
|
|
{
|
|
lpvpstr16 = (VPSTR UNALIGNED *)GetWritePtr16(pti, vpvpstr16,
|
|
sizeof(VPSTR));
|
|
if ( lpvpstr16 != NULL )
|
|
{
|
|
WOWRELVDMPTR(vpvpstr16);
|
|
|
|
lplpstr32 = &lpstr;
|
|
|
|
vpstr16 = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
|
|
if (vpstr16 == 0)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, lplpstr32, LPOLESTR FAR *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( lplpstr32 != NULL )
|
|
{
|
|
if ( SUCCEEDED(dwResult) )
|
|
{
|
|
SCODE sc;
|
|
|
|
if (fFile)
|
|
{
|
|
UINT cch;
|
|
|
|
// The string pointed to by lpstr is ours so we
|
|
// can do the long->short conversion in place
|
|
// without worrying about trashing the memory
|
|
// The short path name should always be able
|
|
// to fit in the long path name's buffer since
|
|
// the file names that we are thunking are always
|
|
// absolute paths
|
|
|
|
cch = lstrlenW(lpstr)+1;
|
|
|
|
// Ignore failures; if we can't convert the name
|
|
// then we simply pass on what we were given
|
|
GetShortPathName(lpstr, lpstr, cch);
|
|
}
|
|
|
|
sc = ConvertTaskString3216(pti, lpstr, vpstr16,
|
|
CWCSTRINGPREALLOC, &vpstr16);
|
|
if (FAILED(sc))
|
|
{
|
|
dwResult = sc;
|
|
}
|
|
}
|
|
|
|
if (FAILED(dwResult))
|
|
{
|
|
TaskFree16(vpstr16);
|
|
vpstr16 = 0;
|
|
}
|
|
|
|
lpvpstr16 = FIXVDMPTR( vpvpstr16, VPSTR );
|
|
*lpvpstr16 = vpstr16;
|
|
|
|
#if DBG==1
|
|
thkDebugOut((DEB_ARGS, "%sOut1632 LPLPSTR: %p -> %p '%s'\n",
|
|
NestingLevelString(), lpstr, vpstr16,
|
|
vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
|
|
if (vpstr16 != 0)
|
|
{
|
|
WOWRELVDMPTR(vpstr16);
|
|
}
|
|
#endif
|
|
|
|
RELVDMPTR( vpvpstr16 );
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Out1632 LPLPSTR NULL\n"));
|
|
}
|
|
|
|
return( dwResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_LPLPSTR_1632, public
|
|
//
|
|
// Synopsis: Converts 32-bit LPSTR to 16-bit LPSTR pointer
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 25-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_LPLPSTR_1632( THUNKINFO *pti )
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
|
|
//
|
|
// We don't have anything but unmodified LPLPSTRs
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
|
|
"LPLPSTR must be unmodified only!" );
|
|
|
|
return ThunkOutString1632(pti, FALSE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_BUFFER_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit block of memory to 32-bit block of memory
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 25-Feb-94 BobDay Created
|
|
// 14-Mar-95 KentCe Buffer copy not required for Win95.
|
|
//
|
|
// Notes: WARNING! WARNING! WARNING! For an out parameter this expects
|
|
// three parameters on the stack in the following format and order:
|
|
// VOID * pointer to buffer
|
|
// DWORD count of bytes in buffer
|
|
// DWORD * count of bytes returned in the buffer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#define WATCH_VALUE 0xfef1f0
|
|
|
|
DWORD Thop_BUFFER_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
BOOL fThopInput;
|
|
BOOL fThopOutput;
|
|
VPVOID vp16;
|
|
LPVOID lp16;
|
|
LPVOID lp32;
|
|
DWORD dwCount;
|
|
VPVOID vp16CountOut;
|
|
DWORD dwCountOut32 = 0;
|
|
DWORD * pdwCountOut32 = &dwCountOut32;
|
|
#if DBG == 1
|
|
DWORD dwWatch;
|
|
#endif
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
|
|
|
|
fThopInput = IS_THOP_IN(pti);
|
|
fThopOutput = IS_THOP_OUT(pti);
|
|
|
|
//
|
|
// We only have in and out BUFFER thops
|
|
//
|
|
thkAssert((fThopInput || fThopOutput)
|
|
&& (fThopInput != fThopOutput)
|
|
&& "BUFFER must be in or out only!" );
|
|
|
|
GET_STACK16(pti, vp16, VPVOID);
|
|
GET_STACK16(pti, dwCount, DWORD);
|
|
|
|
if (fThopOutput)
|
|
{
|
|
// Get the pointer to the returned value off the stack
|
|
GET_STACK16(pti, vp16CountOut, VPVOID);
|
|
}
|
|
|
|
lp32 = NULL;
|
|
|
|
if (vp16 == 0)
|
|
{
|
|
// lp32 is already NULL
|
|
}
|
|
else if (dwCount == 0)
|
|
{
|
|
// If the count is zero then we can pass any valid 32-bit
|
|
// pointer
|
|
|
|
#if DBG == 1
|
|
// In debug, make sure that no data is written back to the
|
|
// memory we pass on
|
|
dwWatch = WATCH_VALUE;
|
|
lp32 = &dwWatch;
|
|
#else
|
|
lp32 = &dwResult;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Under Win95 we can lock down 16-bit memory so a duplicate
|
|
// buffer is not required.
|
|
//
|
|
#if defined(_CHICAGO_)
|
|
lp32 = WOWFIXVDMPTR(vp16, dwCount);
|
|
#else
|
|
lp16 = ValidatePtr16(pti, vp16, dwCount, *pti->pThop);
|
|
|
|
if ( lp16 != NULL )
|
|
{
|
|
lp32 = (LPVOID)CoTaskMemAlloc( dwCount );
|
|
if ( lp32 == NULL )
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
if ( fThopInput )
|
|
{
|
|
memcpy( lp32, lp16, dwCount );
|
|
}
|
|
}
|
|
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 BUFFER: %p -> %p, %u\n",
|
|
vp16, lp32, dwCount));
|
|
|
|
TO_STACK32(pti, lp32, LPVOID );
|
|
TO_STACK32(pti, dwCount, DWORD );
|
|
|
|
if (fThopOutput)
|
|
{
|
|
TO_STACK32(pti, pdwCountOut32, LPVOID );
|
|
}
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if (fThopOutput)
|
|
{
|
|
// If the pointer in sixteen bit land is non-null then return the
|
|
// count of bytes written to the buffer.
|
|
DWORD UNALIGNED *lpdw16 = (DWORD UNALIGNED *)
|
|
ValidatePtr16(pti, vp16CountOut, sizeof(DWORD), *pti->pThop);
|
|
|
|
if (lpdw16 != NULL)
|
|
{
|
|
*lpdw16 = dwCountOut32;
|
|
WOWRELVDMPTR(vp16CountOut);
|
|
}
|
|
|
|
#if !defined(_CHICAGO_)
|
|
//
|
|
// Under Win95 we can lock down 16-bit memory so a duplicate
|
|
// buffer is not required.
|
|
//
|
|
if ( SUCCEEDED(dwResult) )
|
|
{
|
|
if (dwCountOut32 > 0 && vp16 != 0)
|
|
{
|
|
lp16 = (LPVOID)WOWFIXVDMPTR( vp16, dwCountOut32 );
|
|
|
|
memcpy( lp16, lp32, dwCountOut32 );
|
|
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
}
|
|
#endif // _CHICAGO_
|
|
}
|
|
|
|
#if DBG == 1
|
|
if (lp32 != NULL && dwCount == 0)
|
|
{
|
|
thkAssert(dwWatch == WATCH_VALUE);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Under Win95 we can lock down 16-bit memory so a duplicate
|
|
// buffer is not required.
|
|
//
|
|
// Now free the buffer
|
|
//
|
|
if ( lp32 != NULL && dwCount > 0 )
|
|
{
|
|
#if defined(_CHICAGO_)
|
|
WOWRELVDMPTR(vp16);
|
|
#else
|
|
CoTaskMemFree( lp32 );
|
|
#endif // _CHICAGO_
|
|
}
|
|
|
|
|
|
return( dwResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_SNB_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit SNB to 32-bit SNB pointer
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_SNB_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
BOOL fThopInput;
|
|
BOOL fThopOutput;
|
|
VPVOID snb16;
|
|
VPSTR *lpvpstr;
|
|
VPSTR UNALIGNED *lpvpstrTemp;
|
|
VPSTR vpstr;
|
|
SNB snb32;
|
|
UINT cStr;
|
|
UINT cStrTemp;
|
|
LPOLESTR *lplpstr;
|
|
UINT cbStrings;
|
|
OLECHAR *pocStr;
|
|
LPSTR lpstr16;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
|
|
|
|
fThopInput = IS_THOP_IN(pti);
|
|
fThopOutput = IS_THOP_OUT(pti);
|
|
|
|
//
|
|
// We don't have anything but unmodified SNBs
|
|
//
|
|
thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
|
|
|
|
GET_STACK16(pti, snb16, VPVOID);
|
|
|
|
snb32 = NULL;
|
|
if ( snb16 != 0 )
|
|
{
|
|
//
|
|
// Count the strings in the 16-bit snb
|
|
//
|
|
lpvpstr = (VPSTR FAR *)GetReadPtr16( pti, snb16, sizeof(VPSTR) );
|
|
if ( lpvpstr != 0 )
|
|
{
|
|
lpvpstrTemp = lpvpstr;
|
|
cStr = 0;
|
|
cbStrings = 0;
|
|
do
|
|
{
|
|
cStr++;
|
|
vpstr = *lpvpstrTemp++;
|
|
|
|
if ( vpstr == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
lpstr16 = GetStringPtr16(pti, vpstr, CCHMAXSTRING,
|
|
&cStrTemp);
|
|
if ( lpstr16 == 0 )
|
|
{
|
|
WOWRELVDMPTR(snb16);
|
|
lpvpstr = NULL;
|
|
break; // Leave with snb32 still NULL
|
|
}
|
|
|
|
WOWRELVDMPTR(vpstr);
|
|
|
|
cbStrings += cStrTemp;
|
|
}
|
|
while ( TRUE );
|
|
}
|
|
|
|
if ( lpvpstr != NULL )
|
|
{
|
|
thkDebugOut((DEB_ARGS, "In1632 SNB: %d strings\n", cStr));
|
|
|
|
//
|
|
// Allocate space for the 32-bit snb
|
|
//
|
|
snb32 = (LPOLESTR FAR *)CoTaskMemAlloc( cStr*sizeof(LPOLESTR) +
|
|
cbStrings*sizeof(WCHAR));
|
|
if (snb32 == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pocStr = (OLECHAR *)((BYTE *)snb32+cStr*sizeof(LPOLESTR));
|
|
|
|
//
|
|
// Now convert the strings
|
|
//
|
|
lpvpstrTemp = lpvpstr;
|
|
lplpstr = snb32;
|
|
cStrTemp = cStr - 1;
|
|
|
|
while ( cStrTemp > 0 )
|
|
{
|
|
--cStrTemp;
|
|
|
|
vpstr = *lpvpstrTemp++;
|
|
|
|
thkAssert( vpstr != 0 &&
|
|
"Loop is processing end of snb\n" );
|
|
|
|
// Guaranteed to use pocStr as storage since cbStrings is
|
|
// large enough to contain all the strings
|
|
*lplpstr = Convert_VPSTR_to_LPOLESTR( pti, vpstr,
|
|
pocStr, cbStrings );
|
|
|
|
if (*lplpstr == NULL)
|
|
{
|
|
CoTaskMemFree(snb32);
|
|
snb32 = NULL;
|
|
break;
|
|
}
|
|
|
|
#if DBG == 1
|
|
thkDebugOut((DEB_ARGS, "In1632 SNB: %p '%s' -> "
|
|
"%p '%ws'\n",
|
|
vpstr, WOWFIXVDMPTR(vpstr, 0),
|
|
*lplpstr, *lplpstr));
|
|
WOWRELVDMPTR(vpstr);
|
|
#endif
|
|
|
|
pocStr += lstrlenW(pocStr)+1;
|
|
lplpstr++;
|
|
}
|
|
|
|
// Terminate SNB
|
|
*lplpstr = NULL;
|
|
|
|
thkAssert(*lpvpstrTemp == 0);
|
|
|
|
WOWRELVDMPTR(snb16);
|
|
}
|
|
}
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "In1632 SNB: %p -> %p\n", snb16, snb32));
|
|
|
|
TO_STACK32(pti, snb32, SNB );
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
//
|
|
// Free SNB memory if necessary
|
|
//
|
|
if ( snb32 != 0 )
|
|
{
|
|
CoTaskMemFree(snb32);
|
|
}
|
|
|
|
return( dwResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ThunkInterface1632, private
|
|
//
|
|
// Synopsis: Handles interface thunking for THOP_IFACE and
|
|
// THOP_IFACEGEN
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [iidx] - Interface index or IID
|
|
// [thop] - Thop being executed
|
|
// [punkOuter] - Controlling IUnknown or NULL
|
|
//
|
|
// Returns: status code
|
|
//
|
|
// History: Mar 14,97 Gopalk Rewritten to support aggregation and
|
|
// proper thunking of IN/OUT interfaces
|
|
//
|
|
// Notes: Assumes caller has already adjusted pti->pThop
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD ThunkInterface1632(THUNKINFO *pti, IIDIDX iidx, THOP thop, IUnknown *punkOuter)
|
|
{
|
|
// Local variables
|
|
VPVOID vpv;
|
|
DWORD dwResult, dwStatus;
|
|
IUnknown *punkThis32In;
|
|
IUnknown *punkThis32Out;
|
|
VPVOID vpvOut;
|
|
VPVOID vpvIn;
|
|
VPVOID UNALIGNED *pvpvOut;
|
|
VPVOID vpvPreAlloc = NULL;
|
|
THUNK1632OBJ UNALIGNED *pto;
|
|
PROXYHOLDER *pph;
|
|
PROXYHOLDER *pAggHolder = NULL;
|
|
SAggHolder aggHolderNode;
|
|
BOOL bUnlinkAggHolder = FALSE;
|
|
BOOL bExtraAddRef;
|
|
|
|
// 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;
|
|
punkThis32In = NULL;
|
|
pph = NULL;
|
|
|
|
// Retrieve interface pointer
|
|
GET_STACK16(pti, vpv, VPVOID);
|
|
|
|
// Assert invariant
|
|
thkAssert(iidx!=THI_COUNT || vpv==NULL);
|
|
|
|
// Check for valid OUT parameter. It also verifies IN-OUT case as well
|
|
if((thop & THOP_OUT) && vpv) {
|
|
pvpvOut = (VPVOID UNALIGNED *)GetWritePtr16(pti, vpv, sizeof(VPVOID));
|
|
if(!pvpvOut) {
|
|
thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - bad pointer %p\n",
|
|
vpv));
|
|
pti->scResult = E_INVALIDARG;
|
|
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)
|
|
vpvIn = *pvpvOut;
|
|
else
|
|
vpvIn = NULL;
|
|
|
|
// Release the VMD pointer
|
|
WOWRELVDMPTR(vpv);
|
|
}
|
|
else {
|
|
// It must be IN parameter or a NULL OUT parameter
|
|
vpvIn = vpv;
|
|
}
|
|
|
|
// Check if interface needs to be thunked IN
|
|
if(thop & THOP_IN) {
|
|
if (vpvIn) {
|
|
// Validate the interface
|
|
if(IsValidInterface16(pti, vpvIn)) {
|
|
if((thop & THOP_OPMASK) == THOP_IFACENOADDREF) {
|
|
// vpvIn represents an interface that is used by the
|
|
// 32-bit side without addrefing it.
|
|
// Classic example: IOleCacheControl::OnRun
|
|
// Aggregate it with the identity of the interface on which
|
|
// the current call is being made to ensure that lifetime of proxy
|
|
// is controlled by it.
|
|
VPVOID vpvThis16;
|
|
|
|
// Obtain the 16-bit interface on which the current call is
|
|
// being made
|
|
thkAssert(punkOuter);
|
|
vpvThis16 = pti->pThkMgr->LookupProxy1632(punkOuter);
|
|
thkAssert(vpvThis16);
|
|
|
|
// Obtain its holder
|
|
pto = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
|
|
pph = pto->pphHolder;
|
|
thkAssert(pto->punkThis32 == punkOuter);
|
|
RELVDMPTR(vpvThis16);
|
|
|
|
// Assert that holder exists
|
|
thkAssert(pph);
|
|
}
|
|
else {
|
|
thkAssert(pph == NULL);
|
|
}
|
|
|
|
if((thop & THOP_OPMASK) == THOP_UNKOUTER) {
|
|
// Aggregation is being carried out
|
|
// Assert that interface is only being thunked IN
|
|
thkAssert(!(thop & THOP_OUT));
|
|
thkAssert(iidx == THI_IUnknown);
|
|
|
|
// Either find the actual 32-bit identity or generate a
|
|
// new 32-bit proxy identity for the 16-bit identity
|
|
punkThis32In = pti->pThkMgr->CreateOuter32(vpvIn, &pAggHolder, &dwStatus);
|
|
aggHolderNode.pph = pAggHolder;
|
|
bUnlinkAggHolder = TRUE;
|
|
TlsThkLinkAggHolder(&aggHolderNode);
|
|
// 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 16-bit interface to be thunked IN
|
|
bExtraAddRef = FALSE;
|
|
if (
|
|
(
|
|
(pti->pvfn == (VTBLFN) OleIsCurrentClipboard) &&
|
|
(TlsThkGetAppCompatFlags() & OACF_WORKSCLIPOBJ)
|
|
)
|
|
||
|
|
(
|
|
(TlsThkGetAppCompatFlags() & OACF_TEXTARTDOBJ) &&
|
|
(pti->iidx == THI_IDataAdviseHolder) &&
|
|
(iidx == THI_IDataObject) && (pti->dwMethod == 3)
|
|
)
|
|
){
|
|
bExtraAddRef = TRUE;
|
|
}
|
|
|
|
punkThis32In = pti->pThkMgr->FindProxy3216(NULL, vpvIn, pph,
|
|
iidx, bExtraAddRef, &dwStatus);
|
|
}
|
|
|
|
if(punkThis32In) {
|
|
thkAssert(!((thop & THOP_OPMASK) == THOP_UNKOUTER) ||
|
|
(dwStatus == FST_CREATED_NEW) ||
|
|
(dwStatus == FST_SHORTCUT));
|
|
}
|
|
else {
|
|
thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - Can't create proxy for %p\n",
|
|
vpvIn));
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
return (DWORD) E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else {
|
|
thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - invalid interface %p\n",
|
|
vpvIn));
|
|
pti->scResult = E_INVALIDARG;
|
|
return (DWORD) E_INVALIDARG;
|
|
}
|
|
}
|
|
else {
|
|
// No interface to be thunked IN
|
|
punkThis32In = NULL;
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "%sIn1632 %s %p -> %p\n",
|
|
NestingLevelString(), IidIdxString(iidx),
|
|
vpvIn, punkThis32In));
|
|
}
|
|
|
|
// Check if interface needs to be thunked OUT
|
|
if((thop & THOP_OUT) && vpv) {
|
|
// Preallocate a proxy for the out parameter
|
|
vpvPreAlloc = pti->pThkMgr->CanGetNewProxy1632(iidx);
|
|
if(vpvPreAlloc) {
|
|
// Assert that no interface is being thunked IN for
|
|
// pure OUT parameter case
|
|
thkAssert((thop & THOP_IN) || !punkThis32In);
|
|
|
|
// Use a local variable for OUT parameter
|
|
punkThis32Out = punkThis32In;
|
|
|
|
// Push the OUT/IN-OUT parameter onto the stack
|
|
TO_STACK32(pti, &punkThis32Out, IUnknown **);
|
|
|
|
// Corel Draw 5.0 HACK
|
|
// Some apps seem to call through the OUT parameter in the
|
|
// nested calls before the following call returns
|
|
|
|
// Set the temporary proxy's this pointer to point to
|
|
// 32-bit out pointer pushed onto the satck
|
|
pto = FIXVDMPTR(vpvPreAlloc, THUNK1632OBJ);
|
|
pto->punkThis32 = (IUnknown *)&punkThis32Out;
|
|
RELVDMPTR(vpvPreAlloc);
|
|
|
|
// Set the 16-bit OUT parameter to the preallocated proxy
|
|
*FIXVDMPTR(vpv, VPVOID) = vpvPreAlloc;
|
|
RELVDMPTR(vpv);
|
|
}
|
|
else {
|
|
thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - Cannot preallocate proxy\n"));
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
dwResult = (DWORD) E_OUTOFMEMORY;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Assert invariant
|
|
thkAssert((vpv && punkThis32In) || (!vpv && !punkThis32In));
|
|
|
|
TO_STACK32(pti, punkThis32In, IUnknown *);
|
|
}
|
|
|
|
if(SUCCEEDED((SCODE)dwResult)) {
|
|
// Execute the next THOP operation
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
if((thop & THOP_OUT) && vpv) {
|
|
vpvOut = 0;
|
|
|
|
if(SUCCEEDED((SCODE)dwResult) && punkThis32Out) {
|
|
// Obtain 16-bit proxy for the 32-bit interface
|
|
if(punkOuter) {
|
|
//Get the holder that was linked into TLS when the pUnkOuter
|
|
//was being thunked in.
|
|
pAggHolder = (TlsThkGetAggHolder())->pph;
|
|
vpvOut = pti->pThkMgr->FindAggregate1632(vpvPreAlloc, punkOuter,
|
|
punkThis32Out, iidx, pAggHolder,
|
|
&dwStatus);
|
|
}
|
|
else {
|
|
vpvOut = pti->pThkMgr->FindProxy1632(vpvPreAlloc, punkThis32Out,
|
|
NULL, iidx, &dwStatus);
|
|
}
|
|
|
|
if(vpvOut) {
|
|
|
|
if((thop & THOP_OPMASK) == THOP_UNKINNER) {
|
|
if (dwStatus != FST_SHORTCUT) {
|
|
THUNK1632OBJ UNALIGNED *pProxy1632;
|
|
// Obtain the holder
|
|
pProxy1632 = FIXVDMPTR(vpvOut, THUNK1632OBJ);
|
|
pph = pProxy1632->pphHolder;
|
|
|
|
// Assert invariants in debug builds
|
|
thkAssert(pph->dwFlags & PH_AGGREGATEE);
|
|
thkAssert(dwStatus == FST_CREATED_NEW);
|
|
|
|
// Mark the proxy as representing inner unknown
|
|
pProxy1632->grfFlags = PROXYFLAG_PUNKINNER;
|
|
}
|
|
}
|
|
|
|
// Either the preallocated proxy was used and freed
|
|
vpvPreAlloc = NULL;
|
|
}
|
|
else {
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
dwResult = (DWORD)E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Release the actual 32-bit interface. If a proxy to the
|
|
// 32-bit interface could not be created above, this could
|
|
// be the last release on the 32-bit interface
|
|
punkThis32Out->Release();
|
|
}
|
|
|
|
// Set the OUT parameter
|
|
pvpvOut = FIXVDMPTR(vpv, VPVOID);
|
|
*pvpvOut = vpvOut;
|
|
RELVDMPTR(vpv);
|
|
|
|
thkDebugOut((DEB_ARGS, "%sOut1632 %s %p -> %p\n",
|
|
NestingLevelString(), IidIdxString(iidx),
|
|
punkThis32Out, vpvOut));
|
|
}
|
|
|
|
if(punkThis32In) {
|
|
if((thop & THOP_INOUT) == THOP_INOUT) {
|
|
// IN-OUT parameter.
|
|
thkAssert(vpvIn);
|
|
|
|
// Release the 16-bit side interface
|
|
ReleaseOnObj16(vpvIn);
|
|
}
|
|
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_VERIFY16INPARAM);
|
|
#endif
|
|
// Release the 32-bit side interface
|
|
punkThis32In->Release();
|
|
#if DBG==1
|
|
// Restore previous thunk state
|
|
pti->pThkMgr->SetThkState(thkstate);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Cleanup
|
|
if(vpvPreAlloc) {
|
|
// Free preallocated proxy as it was not used
|
|
pti->pThkMgr->FreeNewProxy1632(vpvPreAlloc, iidx);
|
|
}
|
|
|
|
if (bUnlinkAggHolder)
|
|
TlsThkUnlinkAggHolder();
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_IFACEGEN_1632, public
|
|
//
|
|
// Synopsis: Thunks interfaces out through ppvs from 16->32
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_IFACEGEN_1632(THUNKINFO *pti)
|
|
{
|
|
IIDIDX iidx;
|
|
THOP thop, thopOp, thopWeakOffset;
|
|
VPVOID vpvIid;
|
|
IUnknown *punkOuter;
|
|
IID UNALIGNED const *piid;
|
|
|
|
thop = *pti->pThop++;
|
|
thopOp = thop & THOP_OPMASK;
|
|
|
|
thkAssert(thopOp == THOP_IFACEGEN ||
|
|
thopOp == THOP_IFACEGENOWNER);
|
|
|
|
// The current thop byte indicates how many bytes to look
|
|
// back in the stack to find the IID which identifies the
|
|
// interface being returned
|
|
INDEX_STACK16(pti, vpvIid, VPVOID, *pti->pThop, sizeof(VPVOID));
|
|
pti->pThop++;
|
|
|
|
piid = (IID const *)GetReadPtr16(pti, vpvIid, sizeof(IID const));
|
|
if (piid == NULL)
|
|
{
|
|
pti->scResult = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
#if DBG == 1
|
|
if (!IsValidIid(*piid))
|
|
{
|
|
pti->scResult = E_INVALIDARG;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
iidx = IidToIidIdx(*piid);
|
|
}
|
|
|
|
WOWRELVDMPTR(vpvIid);
|
|
}
|
|
|
|
if (FAILED(pti->scResult))
|
|
return pti->scResult;
|
|
|
|
punkOuter = NULL;
|
|
if (thopOp == THOP_IFACEGENOWNER)
|
|
{
|
|
// Obtain the outer unknown that is being passed to the 32 bit world
|
|
thopWeakOffset = *pti->pThop++;
|
|
INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
|
|
if(punkOuter) {
|
|
// Aggregation across 16-32 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 ThunkInterface1632(pti, iidx, thop, punkOuter);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_OIFI_1632, public
|
|
//
|
|
// Synopsis: Convert OLEINPLACEFRAMEINFO
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 26-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_OIFI_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
VPVOID vpoifi16;
|
|
OIFI16 UNALIGNED *poifi16;
|
|
OLEINPLACEFRAMEINFO oifi32;
|
|
OLEINPLACEFRAMEINFO *poifi32;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
|
|
|
|
// OIFIs are out-only parameters for their contents
|
|
// However, cb is in/out, so we need to copy cb on the way in
|
|
// Furthermore, cb may not be set to a valid value, in which
|
|
// case the documentation mentions that it should be assumed
|
|
// that this is an OLE 2.0 OIFI
|
|
// This thop simply ignores cb on the way in and always sets
|
|
// it to the OLE 2.0 size
|
|
// Since we're out-only, this always works since the number of
|
|
// fields we thunk is the size of the structure that we give out
|
|
// If OLEINPLACEFRAMEINFO is extended, this thop will break
|
|
|
|
// Assert that OLEINPLACEFRAMEINFO is what we expect it to be
|
|
thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
|
|
|
|
GET_STACK16(pti, vpoifi16, VPVOID);
|
|
|
|
poifi32 = NULL;
|
|
if (vpoifi16 != 0)
|
|
{
|
|
poifi16 = (OIFI16 UNALIGNED *) GetWritePtr16(pti, vpoifi16, sizeof(OIFI16));
|
|
if (NULL != poifi16)
|
|
{
|
|
poifi32 = &oifi32;
|
|
|
|
// OIFI's may be an out only parameters but if the "cb" field is
|
|
// "in" RPC doesn't slice up structs, so the whole thing is "in"
|
|
// as well. We are Thoping here but if we want this to match
|
|
// the RPC sematics then we need to copy all the fields.
|
|
|
|
poifi32 = &oifi32;
|
|
poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
|
|
poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
|
|
poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
|
|
poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
|
|
|
|
if (poifi16->haccel == NULL)
|
|
{
|
|
poifi32->haccel = NULL;
|
|
}
|
|
else
|
|
{
|
|
// WOW will clean up any dangling accelerator tables when
|
|
// tasks die
|
|
poifi32->haccel = HACCEL_32(poifi16->haccel);
|
|
if (poifi32->haccel == NULL)
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
WOWRELVDMPTR(vpoifi16);
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if (poifi32 != NULL)
|
|
{
|
|
poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
|
|
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
poifi16->cb = sizeof(OIFI16);
|
|
poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
|
|
poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
|
|
poifi16->cAccelEntries =
|
|
ClampULongToUShort(poifi32->cAccelEntries);
|
|
|
|
if (poifi32->haccel == NULL)
|
|
{
|
|
poifi16->haccel = NULL;
|
|
}
|
|
else
|
|
{
|
|
// WOW will clean up any dangling accelerator tables when
|
|
// tasks die
|
|
poifi16->haccel = HACCEL_16(poifi32->haccel);
|
|
if (poifi16->haccel == NULL)
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
#if DBG == 1
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Out1632 OIFI: "
|
|
"%p {%d, %d, 0x%p, 0x%p, %d} -> "
|
|
"%p {%d, %d, 0x%04X, 0x%04X, %d}\n",
|
|
poifi32, poifi32->cb, poifi32->fMDIApp,
|
|
poifi32->hwndFrame, poifi32->haccel,
|
|
poifi32->cAccelEntries,
|
|
vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
|
|
(DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
|
|
poifi16->cAccelEntries));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (FAILED(dwResult))
|
|
{
|
|
memset(poifi16, 0, sizeof(OIFI16));
|
|
}
|
|
|
|
RELVDMPTR(vpoifi16);
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_STGMEDIUM_1632, public
|
|
//
|
|
// Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
|
|
// structure
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_STGMEDIUM_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
BOOL fThopInput;
|
|
BOOL fThopOutput;
|
|
VPVOID vpstgmedium16;
|
|
STGMEDIUM UNALIGNED *lpstgmedium16;
|
|
STGMEDIUM *lpstgmedium32;
|
|
STGMEDIUM stgmedium32;
|
|
DWORD dwSize;
|
|
SCODE sc;
|
|
BOOL fReleaseParam;
|
|
SHORT fTransferOwnership;
|
|
FORMATETC *pfe;
|
|
THOP thopFeOffset;
|
|
BOOL fReversedTYMED_NULL = FALSE;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
|
|
|
|
fThopInput = IS_THOP_IN(pti);
|
|
fThopOutput = IS_THOP_OUT(pti);
|
|
|
|
//
|
|
// We currently don't have any unmodified or inout thops for STGMEDIUMs
|
|
//
|
|
thkAssert( (fThopInput || fThopOutput) &&
|
|
(fThopInput != fThopOutput) &&
|
|
"STGMEDIUM must be input or output only" );
|
|
|
|
// +2 thop byte indicates whether there's a FORMATETC to look at
|
|
// or not
|
|
// We need to reference this now before the stack is modified
|
|
// by argument recovery
|
|
thopFeOffset = *(pti->pThop+2);
|
|
if (thopFeOffset > 0)
|
|
{
|
|
INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
|
|
}
|
|
else
|
|
{
|
|
pfe = NULL;
|
|
}
|
|
|
|
GET_STACK16(pti, vpstgmedium16, VPVOID);
|
|
|
|
// Next thop byte indicates whether there's an ownership transfer
|
|
// argument or not
|
|
pti->pThop++;
|
|
fReleaseParam = (BOOL)*pti->pThop++;
|
|
|
|
if (fReleaseParam)
|
|
{
|
|
GET_STACK16(pti, fTransferOwnership, SHORT);
|
|
}
|
|
else
|
|
{
|
|
fTransferOwnership = FALSE;
|
|
}
|
|
|
|
// Skip FORMATETC offset thop
|
|
pti->pThop++;
|
|
|
|
lpstgmedium32 = NULL;
|
|
|
|
if ( vpstgmedium16 != 0 )
|
|
{
|
|
if ( fThopInput )
|
|
{
|
|
// This code supports GetDataHere() passing TYMED_NULL. It then
|
|
// behaves like GetData(). This is not per the OLE spec.
|
|
// According to every OLE spec TYMED_NULL is an invalid type in
|
|
// GetDataHere(). But AlexGo says that 16bit inproc servers
|
|
// did support this, especially the Default Handler / Clipboard.
|
|
|
|
lpstgmedium16 = (STGMEDIUM FAR *)GetReadPtr16(pti, vpstgmedium16,
|
|
sizeof(STGMEDIUM));
|
|
|
|
thkAssert(lpstgmedium16);
|
|
// To fix a prefix bug... vpstgmedium should never be invalid, but
|
|
// if it is, we'll get back NULL, so we'll return E_UNEXPECTED.
|
|
if (lpstgmedium16)
|
|
{
|
|
if (lpstgmedium16->tymed == TYMED_NULL &&
|
|
!fTransferOwnership)
|
|
{
|
|
WOWRELVDMPTR(vpstgmedium16);
|
|
|
|
memset(&stgmedium32, 0, sizeof(stgmedium32));
|
|
thkAssert( TYMED_NULL == 0 ); // Don't need to set tymed to 0
|
|
|
|
fThopInput = FALSE;
|
|
fThopOutput = TRUE;
|
|
fReversedTYMED_NULL = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WOWRELVDMPTR(vpstgmedium16);
|
|
|
|
sc = ConvertStgMed1632(pti, vpstgmedium16, &stgmedium32,
|
|
pfe, fTransferOwnership, &dwSize);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
lpstgmedium32 = &stgmedium32;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
if ( fThopOutput )
|
|
{
|
|
thkAssert( fThopOutput );
|
|
|
|
lpstgmedium16 = (STGMEDIUM FAR *)GetWritePtr16(pti, vpstgmedium16,
|
|
sizeof(STGMEDIUM));
|
|
if ( lpstgmedium16 != NULL )
|
|
{
|
|
lpstgmedium32 = &stgmedium32;
|
|
WOWRELVDMPTR(vpstgmedium16);
|
|
}
|
|
|
|
// 32->16 sets tymed to TYMED_NULL before passing
|
|
// on the STGMEDIUM because some apps incorrectly check for this
|
|
// I'm assuming this isn't necessary for 16->32 because 32-bit
|
|
// apps can't rely on tymed being NULL since nothing in the 32-bit
|
|
// code sets it that way for out parameters
|
|
// DrewB 5/30
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
|
|
|
|
if (fReleaseParam)
|
|
{
|
|
TO_STACK32(pti, (BOOL)fTransferOwnership, BOOL);
|
|
}
|
|
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( lpstgmedium32 != NULL)
|
|
{
|
|
if ( fThopInput )
|
|
{
|
|
if (!fTransferOwnership || FAILED(dwResult))
|
|
{
|
|
sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
|
|
dwSize, TRUE, pfe);
|
|
if (FAILED(sc))
|
|
{
|
|
dwResult = (DWORD)sc;
|
|
}
|
|
}
|
|
else if (SUCCEEDED(dwResult))
|
|
{
|
|
lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
|
|
if (lpstgmedium16->pUnkForRelease == NULL)
|
|
{
|
|
RELVDMPTR(vpstgmedium16);
|
|
sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
|
|
0, FALSE, pfe);
|
|
thkAssert(SUCCEEDED(sc));
|
|
}
|
|
else
|
|
{
|
|
RELVDMPTR(vpstgmedium16);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
thkAssert( fThopOutput );
|
|
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
|
|
pfe, FALSE, &dwSize);
|
|
if (FAILED(sc))
|
|
{
|
|
dwResult = (DWORD)sc;
|
|
ReleaseStgMedium(lpstgmedium32);
|
|
}
|
|
else if (lpstgmedium32->pUnkForRelease == NULL)
|
|
{
|
|
sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
|
|
dwSize, FALSE, pfe);
|
|
thkAssert(SUCCEEDED(sc));
|
|
}
|
|
}
|
|
|
|
// Clear the [out] parameters if the call failed.
|
|
// Unless it had previously been an [in] parameter.
|
|
// We don't want to erase the caller's [in] argument.
|
|
|
|
if (FAILED(dwResult) && !fReversedTYMED_NULL)
|
|
{
|
|
lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
|
|
memset(lpstgmedium16, 0, sizeof(STGMEDIUM));
|
|
RELVDMPTR(vpstgmedium16);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertStatStg3216, public
|
|
//
|
|
// Synopsis: Converts a STATSTG
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [pss32] - STATSTG
|
|
// [vpss16] - STATSTG
|
|
// [vpstrPreAlloc] - Preallocated string memory or NULL
|
|
// [cchPreAlloc] - Amount preallocated
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [vpss16]
|
|
//
|
|
// History: 14-May-94 DrewB Created
|
|
//
|
|
// Notes: Assumes input STATSTG memory is valid
|
|
// Assumes task memory for the string
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertStatStg3216(THUNKINFO *pti,
|
|
STATSTG *pss32,
|
|
VPVOID vpss16,
|
|
VPSTR vpstrPreAlloc,
|
|
UINT cchPreAlloc)
|
|
{
|
|
STATSTG UNALIGNED *pss16;
|
|
SCODE sc;
|
|
VPSTR vpstr16;
|
|
|
|
sc = ConvertTaskString3216(pti, pss32->pwcsName,
|
|
vpstrPreAlloc, cchPreAlloc,
|
|
&vpstr16);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
pss16 = FIXVDMPTR(vpss16, STATSTG);
|
|
memcpy(pss16, pss32, sizeof(STATSTG));
|
|
pss16->pwcsName = (LPOLESTR)vpstr16;
|
|
RELVDMPTR(vpss16);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_STATSTG_1632, public
|
|
//
|
|
// Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_STATSTG_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
VPVOID vpstatstg16;
|
|
STATSTG UNALIGNED *lpstatstg16;
|
|
VPSTR vpstr;
|
|
STATSTG statstg32;
|
|
STATSTG *lpstatstg32;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
|
|
|
|
//
|
|
// We currently don't have any input thops for STATSTGs
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
|
|
"STATSTG must be output only" );
|
|
|
|
GET_STACK16(pti, vpstatstg16, VPVOID);
|
|
|
|
lpstatstg32 = NULL;
|
|
|
|
lpstatstg16 = (STATSTG FAR *)GetWritePtr16( pti, vpstatstg16,
|
|
sizeof(STATSTG) );
|
|
if ( lpstatstg16 != NULL )
|
|
{
|
|
statstg32.pwcsName = NULL;
|
|
lpstatstg32 = &statstg32;
|
|
|
|
vpstr = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
|
|
if (vpstr == 0)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
|
|
WOWRELVDMPTR(vpstatstg16);
|
|
}
|
|
|
|
TO_STACK32(pti, lpstatstg32, STATSTG FAR *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( lpstatstg32 != NULL )
|
|
{
|
|
if ( SUCCEEDED(dwResult) )
|
|
{
|
|
SCODE sc;
|
|
|
|
sc = ConvertStatStg3216(pti, &statstg32, vpstatstg16,
|
|
vpstr, CWCSTRINGPREALLOC);
|
|
if (FAILED(sc))
|
|
{
|
|
dwResult = sc;
|
|
}
|
|
}
|
|
|
|
if (FAILED(dwResult))
|
|
{
|
|
TaskFree16(vpstr);
|
|
|
|
lpstatstg16 = FIXVDMPTR(vpstatstg16, STATSTG);
|
|
memset(lpstatstg16, 0, sizeof(STATSTG));
|
|
RELVDMPTR(vpstatstg16);
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_DVTARGETDEVICE_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_DVTARGETDEVICE_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
UINT uiSize;
|
|
DVTARGETDEVICE *lpdv32;
|
|
VPVOID vpdv16;
|
|
SCODE sc;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
|
|
|
|
//
|
|
// We currently don't have any output thops for DVTARGETDEVICEs
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
|
|
"DVTARGETDEVICE must be input only" );
|
|
|
|
//
|
|
// Processing for a DVTARGETDEVICE FAR * as input
|
|
//
|
|
GET_STACK16(pti, vpdv16, VPVOID);
|
|
|
|
lpdv32 = NULL;
|
|
|
|
if ( vpdv16 != 0 )
|
|
{
|
|
sc = ConvertDvtd1632(pti, vpdv16, ArStack32, FrStack32, &lpdv32,
|
|
&uiSize);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if (lpdv32 != NULL)
|
|
{
|
|
FrStack32(lpdv32, uiSize);
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_FORMATETC_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_FORMATETC_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
BOOL fThopInput;
|
|
BOOL fThopOutput;
|
|
VPVOID vpformatetc16;
|
|
FORMATETC16 UNALIGNED *lpformatetc16;
|
|
LPFORMATETC lpformatetc32;
|
|
FORMATETC formatetc32;
|
|
DVTARGETDEVICE *lpdv32;
|
|
SCODE sc;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
|
|
|
|
fThopInput = IS_THOP_IN(pti);
|
|
fThopOutput = IS_THOP_OUT(pti);
|
|
|
|
//
|
|
// We have only input and output thops, not both, or neither
|
|
//
|
|
thkAssert( (fThopInput || fThopOutput) &&
|
|
(fThopInput != fThopOutput) &&
|
|
"formatetc must be input or output only" );
|
|
|
|
lpdv32 = NULL;
|
|
|
|
GET_STACK16(pti, vpformatetc16, VPVOID);
|
|
|
|
if ( vpformatetc16 == 0 )
|
|
{
|
|
lpformatetc32 = NULL;
|
|
}
|
|
else
|
|
{
|
|
lpformatetc32 = &formatetc32;
|
|
|
|
if ( fThopInput )
|
|
{
|
|
sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, FALSE);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
thkAssert( fThopOutput );
|
|
//
|
|
// The below memset is needed at least for the DATA_S_SAMEFORMATETC
|
|
// case. This allows it to be cleaned up because all its pointers
|
|
// will be null.
|
|
//
|
|
memset( &formatetc32, 0, sizeof(formatetc32) );
|
|
lpformatetc16 = (LPFORMATETC16)GetWritePtr16(pti, vpformatetc16,
|
|
sizeof(FORMATETC16));
|
|
WOWRELVDMPTR(vpformatetc16);
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, lpformatetc32, LPFORMATETC);
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( fThopInput )
|
|
{
|
|
if (lpformatetc32 != NULL && lpformatetc32->ptd != NULL)
|
|
{
|
|
TaskFree32(lpformatetc32->ptd);
|
|
}
|
|
}
|
|
|
|
if ( fThopOutput && vpformatetc16 != NULL)
|
|
{
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, TRUE);
|
|
if (FAILED(sc))
|
|
{
|
|
dwResult = sc;
|
|
}
|
|
}
|
|
|
|
if (FAILED(dwResult))
|
|
{
|
|
lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
|
|
memset(lpformatetc16, 0, sizeof(FORMATETC16));
|
|
RELVDMPTR(vpformatetc16);
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_LOGPALETTE_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
|
|
// and converts 32-bit LOGPALETTE returned to 16-bit structure
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_LOGPALETTE_1632 ( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
UINT uiSize;
|
|
LPLOGPALETTE lplogpal32;
|
|
VPVOID vplogpal16;
|
|
LOGPALETTE UNALIGNED *lplogpal16;
|
|
VPVOID vp16;
|
|
LPVOID UNALIGNED *lp16;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
|
|
|
|
//
|
|
// It must be either an input or output LOGPALETTE
|
|
//
|
|
thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
|
|
(*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
|
|
"Hey, LOGPALETTE can't be input and output!" );
|
|
|
|
lplogpal32 = NULL;
|
|
|
|
if ( (*pti->pThop & THOP_IN) != 0 )
|
|
{
|
|
//
|
|
// Processing for a LPLOGPALETTE as input
|
|
//
|
|
GET_STACK16(pti, vplogpal16, VPVOID);
|
|
|
|
if ( vplogpal16 != 0 )
|
|
{
|
|
// Copy over the input LOGPALETTE structure
|
|
lplogpal16 = (LPLOGPALETTE)GetReadPtr16( pti, vplogpal16,
|
|
sizeof(LOGPALETTE) );
|
|
|
|
if ( lplogpal16 != NULL )
|
|
{
|
|
uiSize = CBPALETTE(lplogpal16->palNumEntries);
|
|
|
|
WOWRELVDMPTR(vplogpal16);
|
|
|
|
lplogpal16 = (LPLOGPALETTE)GetReadPtr16(pti, vplogpal16,
|
|
uiSize);
|
|
if ( lplogpal16 != NULL )
|
|
{
|
|
lplogpal32 = (LPLOGPALETTE)CoTaskMemAlloc(uiSize);
|
|
if ( lplogpal32 == NULL )
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
memcpy( lplogpal32, lplogpal16, uiSize );
|
|
}
|
|
|
|
WOWRELVDMPTR(vplogpal16);
|
|
}
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, lplogpal32, LPLOGPALETTE);
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( lplogpal32 )
|
|
{
|
|
CoTaskMemFree( lplogpal32 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Processing for LPLPLOGPALETTE as output
|
|
//
|
|
|
|
thkAssert((*pti->pThop & THOP_OUT) != 0);
|
|
|
|
GET_STACK16(pti, vp16, VPVOID);
|
|
|
|
vplogpal16 = (VPVOID)TaskMalloc16(CBPALETTE(NPALETTEPREALLOC));
|
|
if (vplogpal16 == 0)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TO_STACK32(pti, &lplogpal32, LPLOGPALETTE *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( SUCCEEDED(dwResult) && lplogpal32 != NULL )
|
|
{
|
|
//
|
|
// Copy the returned LOGPALETTE into 16-bit memory
|
|
//
|
|
uiSize = CBPALETTE(lplogpal32->palNumEntries);
|
|
if (uiSize > CBPALETTE(NPALETTEPREALLOC))
|
|
{
|
|
TaskFree16(vplogpal16);
|
|
vplogpal16 = (VPVOID)TaskMalloc16(uiSize);
|
|
if ( vplogpal16 == 0 )
|
|
{
|
|
dwResult = (DWORD)E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if (vplogpal16 != 0)
|
|
{
|
|
lplogpal16 = (LPLOGPALETTE)WOWFIXVDMPTR(vplogpal16, uiSize);
|
|
if ( lplogpal16 == NULL )
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
vplogpal16 = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy( lplogpal16, lplogpal32, uiSize );
|
|
|
|
WOWRELVDMPTR(vplogpal16);
|
|
}
|
|
}
|
|
|
|
TaskFree32( lplogpal32 );
|
|
}
|
|
else
|
|
{
|
|
TaskFree16(vplogpal16);
|
|
vplogpal16 = 0;
|
|
}
|
|
|
|
//
|
|
// Update the value pointed to by the parameter on the 16-bit stack
|
|
//
|
|
lp16 = FIXVDMPTR(vp16, LPVOID);
|
|
if ( lp16 == NULL )
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
*lp16 = (LPVOID)vplogpal16;
|
|
RELVDMPTR(vp16);
|
|
}
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_CRGIID_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit CRGIID to 32-bit CRGIID structure
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_CRGIID_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
DWORD dwCount;
|
|
VPVOID vpiid16;
|
|
IID UNALIGNED *lpiid16;
|
|
IID *lpiid32;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
|
|
|
|
//
|
|
// We currently don't have any output thops for CRGIIDs
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
|
|
"CRGIID must be unmodified only" );
|
|
|
|
GET_STACK16(pti, dwCount, DWORD);
|
|
GET_STACK16(pti, vpiid16, VPVOID);
|
|
|
|
lpiid32 = NULL;
|
|
|
|
if ( vpiid16 != 0 )
|
|
{
|
|
lpiid16 = (IID UNALIGNED *)GetReadPtr16( pti, vpiid16,
|
|
dwCount*sizeof(IID) );
|
|
if ( lpiid16 != NULL )
|
|
{
|
|
lpiid32 = (IID FAR *)CoTaskMemAlloc( dwCount * sizeof(IID) );
|
|
if ( lpiid32 == NULL )
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
memcpy( lpiid32, lpiid16, dwCount*sizeof(IID) );
|
|
}
|
|
|
|
WOWRELVDMPTR(vpiid16);
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, dwCount, DWORD);
|
|
TO_STACK32(pti, lpiid32, IID FAR *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( lpiid32 != NULL )
|
|
{
|
|
CoTaskMemFree( lpiid32 );
|
|
}
|
|
return( dwResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_INTERFACEINFO_1632, public
|
|
//
|
|
// Synopsis: Converts an INTERFACEINFO
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 19-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_INTERFACEINFO_1632(THUNKINFO *pti)
|
|
{
|
|
INTERFACEINFO *pii32;
|
|
INTERFACEINFO ii32;
|
|
INTERFACEINFO16 UNALIGNED *pii16;
|
|
VPVOID vpii16;
|
|
DWORD dwResult;
|
|
IUnknown *punk32;
|
|
VPVOID vpvUnk16;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
|
|
thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
|
|
|
|
pii32 = NULL;
|
|
punk32 = NULL;
|
|
|
|
GET_STACK16(pti, vpii16, VPVOID);
|
|
if (vpii16 != 0)
|
|
{
|
|
pii16 = (INTERFACEINFO16 UNALIGNED *)
|
|
GetReadPtr16(pti, vpii16, sizeof(INTERFACEINFO16));
|
|
if (pii16 != NULL)
|
|
{
|
|
if (pii16->pUnk != NULL)
|
|
{
|
|
vpvUnk16 = pii16->pUnk;
|
|
|
|
WOWRELVDMPTR(vpii16);
|
|
|
|
punk32 =
|
|
pti->pThkMgr->FindProxy3216(NULL, vpvUnk16, NULL,
|
|
INDEX_IIDIDX(THI_IUnknown),
|
|
FALSE, NULL);
|
|
if (punk32 == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
|
|
pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
|
|
}
|
|
|
|
pii32 = &ii32;
|
|
pii32->pUnk = punk32;
|
|
pii32->iid = pii16->iid;
|
|
pii32->wMethod = pii16->wMethod;
|
|
|
|
WOWRELVDMPTR(vpii16);
|
|
|
|
thkDebugOut((DEB_ARGS,
|
|
"In1632 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
|
|
vpii16, pii32, pii32->pUnk, pii16->pUnk,
|
|
IidOrInterfaceString(&pii32->iid), pii32->wMethod));
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, pii32, INTERFACEINFO *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if(punk32) {
|
|
// Release the 32-bit interface as it is an IN parameter
|
|
punk32->Release();
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_RETURNTYPE_1632, public
|
|
//
|
|
// Synopsis: Thunks the return value of a call
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Feb-94 DrewB Created
|
|
//
|
|
// Notes: This thunk assumes that the return value will always fit
|
|
// in 32 bits and that the thops for it are only one thop
|
|
// long. This fits the existing APIs and methods
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_RETURNTYPE_1632(THUNKINFO *pti)
|
|
{
|
|
THOP thops[2];
|
|
DWORD dwResult;
|
|
ALIAS alias;
|
|
VPVOID vpvPreAlloc = 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 ((vpvPreAlloc =
|
|
pti->pThkMgr->CanGetNewProxy1632(iidx)) == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
break;
|
|
|
|
case THOP_ALIAS32:
|
|
thkAssert(thops[1] == ALIAS_CREATE);
|
|
|
|
// The value used for preallocation doesn't really matter
|
|
// as long as it's unique and not INVALID_VALUE
|
|
// In our case we know that we won't have to deal with nested
|
|
// preallocations so uniqueness is not as much of an issue
|
|
// By using INVALID_HANDLE_VALUE, we can be sure that there
|
|
// won't already be an entry with that value already in the
|
|
// alias table since we're aliasing handles
|
|
alias = gAliases32.AddValue((DWORD)INVALID_HANDLE_VALUE);
|
|
if (alias == INVALID_ALIAS)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
}
|
|
break;
|
|
}
|
|
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
// Now that we have the return value thunk it from 32->16
|
|
// We must use pti->scResult to check for failure rather than
|
|
// dwResult because dwResult may not be an SCODE
|
|
|
|
switch(thops[0])
|
|
{
|
|
case THOP_COPY:
|
|
// Only handle DWORD copies
|
|
thkAssert(thops[1] == sizeof(DWORD));
|
|
break;
|
|
|
|
case THOP_SHORTLONG:
|
|
// For boolean results, not necessary to clamp
|
|
dwResult = (DWORD)(SHORT)*(LONG *)&dwResult;
|
|
break;
|
|
|
|
case THOP_IFACE | THOP_IN:
|
|
// 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)
|
|
{
|
|
if (FAILED(pti->scResult))
|
|
{
|
|
dwResult = 0;
|
|
}
|
|
else
|
|
{
|
|
IUnknown *punk = (IUnknown *) dwResult;
|
|
dwResult =
|
|
(DWORD)pti->pThkMgr->FindProxy1632(vpvPreAlloc,
|
|
(IUnknown *)dwResult, NULL,
|
|
iidx, NULL);
|
|
|
|
// Release actual interface as it is an OUT parameter
|
|
// This could be the last release on the interface if the
|
|
// above call failed;
|
|
punk->Release();
|
|
thkAssert(dwResult);
|
|
|
|
thkDebugOut((DEB_ARGS, "Ret1632 %s %p\n",
|
|
inInterfaceNames[thops[1]].pszInterface,
|
|
dwResult));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pti->pThkMgr->FreeNewProxy1632(vpvPreAlloc, iidx);
|
|
}
|
|
break;
|
|
|
|
case THOP_ALIAS32:
|
|
if (dwResult != 0)
|
|
{
|
|
if (FAILED(pti->scResult))
|
|
{
|
|
dwResult = 0;
|
|
}
|
|
else
|
|
{
|
|
gAliases32.SetValue(alias, dwResult);
|
|
|
|
thkDebugOut((DEB_ARGS, "Ret1632 ALIAS32: 0x%08lX -> 0x%04lX\n",
|
|
dwResult, alias));
|
|
|
|
dwResult = (DWORD)alias;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
thkAssert(!"Unhandled 1632 return type");
|
|
break;
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_IFACE_1632, public
|
|
//
|
|
// Synopsis: Thunks a known interface pointer
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Feb-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_IFACE_1632(THUNKINFO *pti)
|
|
{
|
|
IIDIDX iidx;
|
|
THOP thop, thopOp, thopWeakOffset;
|
|
IUnknown *punkOuter;
|
|
|
|
thop = *pti->pThop++;
|
|
thopOp = thop & THOP_OPMASK;
|
|
|
|
thkAssert( thopOp == THOP_IFACE
|
|
|| thopOp == THOP_IFACEOWNER
|
|
|| thopOp == THOP_IFACENOADDREF
|
|
|| 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);
|
|
|
|
punkOuter = NULL;
|
|
if ( thopOp == THOP_IFACEOWNER
|
|
|| thopOp == THOP_IFACENOADDREF)
|
|
{
|
|
thopWeakOffset = *pti->pThop++;
|
|
INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
|
|
if(punkOuter && (thopOp==THOP_IFACEOWNER)) {
|
|
// Aggregation across 16-32 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 ThunkInterface1632(pti, iidx, thop, punkOuter);
|
|
}
|
|
|
|
typedef struct tagOLESTREAMOBJECT
|
|
{
|
|
OLESTREAM os;
|
|
VPVOID vpolestream16;
|
|
} OLESTREAMOBJECT, FAR * LPOLESTREAMOBJECT;
|
|
|
|
#define OLESTREAM_GET 0
|
|
#define OLESTREAM_PUT 1
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: OLESTREAM_Callback, private
|
|
//
|
|
// Synopsis: Handles callbacks into 16-bit world for OLESTREAM methods
|
|
//
|
|
// Arguments: [dwMethod] - Index of method to invoke
|
|
// [lposo] - Pointer to 32 LPOLESTREAM
|
|
// [lpv] - Pointer to 32 bit buffer
|
|
// [dwCount] - Size of 32 bit buffer
|
|
//
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 11-Mar-94 BobDay Created
|
|
// 29-May-94 TerryRu Converted to call WOWCallBackEx directly.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD OLESTREAM_Callback( DWORD dwMethod,
|
|
LPOLESTREAM lpos,
|
|
LPVOID lpv,
|
|
DWORD dwCount )
|
|
{
|
|
const DWORD cbStack = sizeof( DWORD ) +
|
|
sizeof( VPVOID ) + sizeof( VPVOID );
|
|
|
|
BYTE b32Args[cbStack];
|
|
DWORD dwResult;
|
|
|
|
VPVOID vpvVtbl16;
|
|
VTBLFN vpfn16;
|
|
|
|
VPVOID vpolestream16;
|
|
LPOLESTREAMOBJECT lposo;
|
|
|
|
VPVOID vp16;
|
|
LPVOID lp16;
|
|
|
|
|
|
lposo = (LPOLESTREAMOBJECT)lpos;
|
|
vpolestream16 = lposo->vpolestream16;
|
|
|
|
// Get pointer to 16 bit this pointer
|
|
|
|
vpvVtbl16 = (VPVOID)*FIXVDMPTR( vpolestream16, VPVOID );
|
|
RELVDMPTR(vpolestream16);
|
|
vpfn16 = (VTBLFN)*FIXVDMPTR( vpvVtbl16+dwMethod*sizeof(VPVOID),
|
|
VPVOID );
|
|
RELVDMPTR(vpvVtbl16+dwMethod*sizeof(VPVOID));
|
|
|
|
//
|
|
// now thop the IN 32 bit-block of memory to 16 bit block
|
|
//
|
|
|
|
vp16 = WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
|
|
if ( vp16 == NULL )
|
|
{
|
|
return (DWORD) E_OUTOFMEMORY;
|
|
}
|
|
|
|
if ( dwMethod == OLESTREAM_PUT )
|
|
{
|
|
lp16 = WOWFIXVDMPTR( vp16, dwCount );
|
|
memcpy( lp16, lpv, dwCount );
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
|
|
// setup 32 bit arguements.
|
|
*(DWORD *)(b32Args) = dwCount;
|
|
*(VPVOID *)(b32Args+4) = vp16;
|
|
*(VPVOID *)(b32Args+8) = vpolestream16;
|
|
|
|
if ( !CallbackTo16Ex( (DWORD)vpfn16, WCB16_PASCAL, cbStack, b32Args,
|
|
&dwResult) )
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
|
|
if ( dwMethod == OLESTREAM_GET )
|
|
{
|
|
|
|
lp16 = WOWFIXVDMPTR( vp16, dwCount );
|
|
memcpy( (LPVOID) lpv, lp16, dwCount );
|
|
WOWRELVDMPTR(vp16);
|
|
|
|
}
|
|
|
|
WgtUnlockFree(vp16);
|
|
|
|
thkDebugOut((DEB_INVOKES, "OLESTREAM_Callback returns 0x%08lX\n",
|
|
dwResult));
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: OLESTREAM_Get_Proxy, private
|
|
//
|
|
// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Get
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 11-Mar-94 BobDay Created
|
|
// 29-May-94 TerryRu Now calls OLESTREAM::Get using Pascal
|
|
// calling conventions.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD OLESTREAM_Get_Proxy(
|
|
LPOLESTREAM lpos,
|
|
void FAR * lpv,
|
|
DWORD dwCount
|
|
)
|
|
{
|
|
return OLESTREAM_Callback( OLESTREAM_GET, lpos, lpv, dwCount );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: OLESTREAM_Put_Proxy, private
|
|
//
|
|
// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Put
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 11-Mar-94 BobDay Created
|
|
// 29-May-94 TerryRu Now call OLESTREAM::Put using pascal
|
|
// calling conventions.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD OLESTREAM_Put_Proxy(
|
|
LPOLESTREAM lpos,
|
|
const void FAR* lpv,
|
|
DWORD dwCount
|
|
)
|
|
{
|
|
return OLESTREAM_Callback( OLESTREAM_PUT, lpos,(LPVOID) lpv, dwCount );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_OLESTREAM_1632, public
|
|
//
|
|
// Synopsis: Thunks an OLESTREAM parameter from 16-bit to 32-bit
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 14-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
_OLESTREAMVTBL osVtbl =
|
|
{
|
|
OLESTREAM_Get_Proxy,
|
|
OLESTREAM_Put_Proxy
|
|
};
|
|
|
|
DWORD Thop_OLESTREAM_1632(THUNKINFO *pti)
|
|
{
|
|
OLESTREAMOBJECT osObject;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OLESTREAM);
|
|
|
|
//
|
|
// Ignore the THOP_INPUT/THOP_OUTPUT, it is always just an interface
|
|
//
|
|
|
|
osObject.os.lpstbl = &osVtbl;
|
|
GET_STACK16(pti, osObject.vpolestream16, VPVOID);
|
|
|
|
TO_STACK32(pti, &osObject, LPOLESTREAMOBJECT );
|
|
|
|
pti->pThop++;
|
|
return EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_RPCOLEMESSAGE_1632, public
|
|
//
|
|
// Synopsis: Converts 16-bit RPCOLEMESSAGE to 32-bit RPCOLEMESSAGE
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Feb-94 BobDay Created
|
|
// 28-May-94 JohannP Rewritten
|
|
// 13-Aug-94 Rickhi made it work for GetBuffer when the
|
|
// buffer size grows, commented better
|
|
//
|
|
// CODEWORK: this routine is inefficient. since it cant tell why it was
|
|
// called (GetBuffer/SendReceive/Invoke/FreeBuffer) it always
|
|
// copies the data, when it only really needs to in Invoke and
|
|
// in SendReceive.
|
|
//
|
|
// Context: This routine will "Thop" a client side RPCOLEMESSGE (aka "rom")
|
|
// three times. The first time for the "getbuffer" call, the second
|
|
// time for the "SendRecieve", and the third time for the "freebuffer".
|
|
// This make it confusing, some calls allocate a buffer but don't
|
|
// free it. Other calls free a buffer they didn't allocate. A good
|
|
// way to see what is happening is to step through several calls to
|
|
// this routine with a debugger and note the pointer values.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Thop_RPCOLEMESSAGE_1632( THUNKINFO *pti )
|
|
{
|
|
DWORD dwResult;
|
|
PRPCOLEMESSAGE prom32;
|
|
VPVOID vprom16;
|
|
RPCOLEMESSAGE UNALIGNED *prom16;
|
|
LPVOID lp16;
|
|
RPCOLEMESSAGE rom32;
|
|
BOOL fAllocNew = FALSE;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
|
|
|
|
//
|
|
// We currently have only INOUT RPCOLEMESSAGE
|
|
//
|
|
thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
|
|
"RPCOLEMESSAGE must be input/output only" );
|
|
|
|
//
|
|
// Processing for a RPCOLEMESSAGE FAR * as input/output
|
|
//
|
|
GET_STACK16(pti, vprom16, VPVOID);
|
|
|
|
prom32 = NULL;
|
|
if ( vprom16 != 0 )
|
|
{
|
|
// Copy over the input RPCOLEMESSAGE structure
|
|
prom16 = (RPCOLEMESSAGE UNALIGNED *)
|
|
GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
|
|
if ( prom16 != NULL )
|
|
{
|
|
// Note: ROM_THUNK_FIELD(prom) holds the pointer to the 32 bit rom
|
|
// in case the buffer is not NULL
|
|
|
|
// Note: this assert is not valid when a fault happens on the
|
|
// server side. In that case, the return buffer is NULLed
|
|
// by the 16bit stub but the THUNK_FIELD is non-null.
|
|
|
|
//thkAssert((prom16->Buffer == NULL &&
|
|
// ROM_THUNK_FIELD(prom16) == NULL) ||
|
|
// (prom16->Buffer != NULL &&
|
|
// ROM_THUNK_FIELD(prom16) != NULL));
|
|
|
|
if (prom16->Buffer != NULL)
|
|
{
|
|
prom32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
|
|
|
|
if ( prom32->Buffer != NULL )
|
|
{
|
|
// we use the min size of the two buffers because when
|
|
// the stub (server side) calls GetBuffer he is supplying
|
|
// the old pBuffer with the new (and potentially larger)
|
|
// cbBuffer
|
|
|
|
DWORD cbSizeMin = (prom16->cbBuffer <= prom32->cbBuffer) ?
|
|
prom16->cbBuffer : prom32->cbBuffer;
|
|
|
|
lp16 = (LPVOID)GetReadPtr16(pti,
|
|
(VPVOID)prom16->Buffer,
|
|
cbSizeMin);
|
|
if (lp16 == NULL)
|
|
{
|
|
prom32 = NULL;
|
|
}
|
|
else
|
|
{
|
|
memcpy( prom32->Buffer, lp16, prom32->cbBuffer );
|
|
WOWRELVDMPTR((VPVOID)prom16->Buffer);
|
|
}
|
|
}
|
|
|
|
if (prom32)
|
|
{
|
|
// the stub might be asking for a larger buffer for output
|
|
// parameters than it was given for input parameters. We have
|
|
// to figure that out here by comparing the 16bit size with
|
|
// the 32bit size.
|
|
|
|
fAllocNew = (prom32->cbBuffer < prom16->cbBuffer);
|
|
prom32->cbBuffer = prom16->cbBuffer;
|
|
}
|
|
else
|
|
{
|
|
fAllocNew = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rom32 = *prom16;
|
|
prom32 = &rom32;
|
|
}
|
|
|
|
WOWRELVDMPTR(vprom16);
|
|
}
|
|
}
|
|
|
|
TO_STACK32(pti, prom32, PRPCOLEMESSAGE);
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
|
|
if ( prom32 != NULL )
|
|
{
|
|
prom16 = (RPCOLEMESSAGE UNALIGNED *)
|
|
GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
|
|
if ( prom16 == NULL )
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
if (prom32->Buffer == NULL)
|
|
{
|
|
// RELEASE THE BUFFER AND ROM:
|
|
// Free the 16 bit buffer, copy the 32 bit rom into
|
|
// the 16 bit rom and free the 32bit rom, if it was
|
|
// allocated
|
|
//
|
|
if (prom16->Buffer != 0)
|
|
{
|
|
TaskFree16((VPVOID)prom16->Buffer);
|
|
}
|
|
|
|
*prom16 = *prom32;
|
|
|
|
if (prom32 != &rom32)
|
|
{
|
|
TaskFree32(prom32);
|
|
prom32 = NULL;
|
|
}
|
|
ROM_THUNK_FIELD(prom16) = NULL;
|
|
}
|
|
else
|
|
{
|
|
// ALLOCATE AND/OR COPYBACK THE BUFFER AND ROM:
|
|
RPCOLEMESSAGE *pr32;
|
|
LPVOID pBuffer;
|
|
|
|
// Create a message to save the 32-bit message in
|
|
// Use the existing one in the thunk field if we can
|
|
if (ROM_THUNK_FIELD(prom16) == NULL)
|
|
{
|
|
pr32 = (RPCOLEMESSAGE *)
|
|
TaskMalloc32(sizeof(RPCOLEMESSAGE));
|
|
}
|
|
else
|
|
{
|
|
pr32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
|
|
}
|
|
*pr32 = *prom32;
|
|
|
|
//
|
|
// Allocate an output buffer and copy the buffer back
|
|
//
|
|
if ( (prom16->Buffer == NULL)
|
|
|| (prom16->cbBuffer < prom32->cbBuffer)
|
|
|| fAllocNew)
|
|
{
|
|
if (prom16->Buffer != NULL)
|
|
{
|
|
TaskFree16((VPVOID) prom16->Buffer);
|
|
}
|
|
|
|
pBuffer = (LPVOID)TaskMalloc16(prom32->cbBuffer );
|
|
}
|
|
else
|
|
{
|
|
pBuffer = prom16->Buffer;
|
|
}
|
|
|
|
*prom16 = *prom32;
|
|
prom16->Buffer = pBuffer;
|
|
ROM_THUNK_FIELD(prom16) = pr32;
|
|
|
|
if (prom16->Buffer == NULL)
|
|
{
|
|
dwResult = (DWORD)E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
lp16 = (LPVOID)GetReadPtr16(pti,
|
|
(VPVOID)prom16->Buffer,
|
|
prom16->cbBuffer);
|
|
if ( lp16 == NULL )
|
|
{
|
|
dwResult = (DWORD)E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
memcpy( lp16, prom32->Buffer,
|
|
prom32->cbBuffer );
|
|
WOWRELVDMPTR((VPVOID)prom16->Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
WOWRELVDMPTR(vprom16);
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_ALIAS32_1632, public
|
|
//
|
|
// Synopsis: Handles 16-bit aliases to 32-bit quantities
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 27-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_ALIAS32_1632(THUNKINFO *pti)
|
|
{
|
|
ALIAS alias;
|
|
DWORD dwValue;
|
|
THOP thopAction;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == 0);
|
|
|
|
pti->pThop++;
|
|
|
|
GET_STACK16(pti, alias, ALIAS);
|
|
|
|
// Second byte indicates how the alias should be handled
|
|
thopAction = *pti->pThop++;
|
|
|
|
if (alias != 0)
|
|
{
|
|
switch(thopAction)
|
|
{
|
|
case ALIAS_RESOLVE:
|
|
dwValue = gAliases32.AliasValue(alias);
|
|
break;
|
|
|
|
case ALIAS_REMOVE:
|
|
dwValue = gAliases32.AliasValue(alias);
|
|
gAliases32.RemoveAlias(alias);
|
|
break;
|
|
|
|
default:
|
|
thkAssert(!"Default hit in Thop_ALIAS32_1632");
|
|
dwValue = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwValue = 0;
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "In1632 ALIAS32: 0x%04X -> 0x%08lX\n",
|
|
alias, dwValue));
|
|
|
|
TO_STACK32(pti, dwValue, DWORD);
|
|
|
|
return EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_ENUM_1632, public
|
|
//
|
|
// Synopsis: Thunks Enum::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is the start of a 2-byte thop. The next thop
|
|
// byte references a function in the enumerator table, rather
|
|
// than the standard thop table.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_ENUM_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == 0);
|
|
|
|
//
|
|
// Get then next thop byte and execute it as a Enum thop
|
|
//
|
|
pti->pThop++;
|
|
return EXECUTE_ENUMTHOP1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CallbackProcessing_1632, public
|
|
//
|
|
// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 3-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
typedef struct tagCallbackControl
|
|
{
|
|
DWORD dwContinue;
|
|
VPVOID vpfn16;
|
|
} CALLBACKCONTROL;
|
|
|
|
BOOL CallbackProcessing_1632( DWORD dwContinue )
|
|
{
|
|
DWORD dwResult;
|
|
CALLBACKCONTROL *lpcbc;
|
|
|
|
lpcbc = (CALLBACKCONTROL *)dwContinue;
|
|
|
|
// The callback function must be FAR PASCAL
|
|
// It's declared CALLBACK in the methods so this is ensured
|
|
dwResult = CallbackTo16( lpcbc->vpfn16, lpcbc->dwContinue );
|
|
|
|
return (BOOL)((WORD)dwResult); // Ignore HIWORD
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_CALLBACK_1632, public
|
|
//
|
|
// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 3-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_CALLBACK_1632(THUNKINFO *pti)
|
|
{
|
|
VPVOID vpfn16;
|
|
DWORD dwContinue;
|
|
CALLBACKCONTROL cbc;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == 0);
|
|
|
|
GET_STACK16(pti, vpfn16, VPVOID);
|
|
GET_STACK16(pti, dwContinue, DWORD);
|
|
|
|
if ( vpfn16 == 0 )
|
|
{
|
|
TO_STACK32(pti, NULL, LPVOID);
|
|
TO_STACK32(pti, dwContinue, DWORD);
|
|
}
|
|
else
|
|
{
|
|
cbc.vpfn16 = vpfn16;
|
|
cbc.dwContinue = dwContinue;
|
|
|
|
TO_STACK32(pti, CallbackProcessing_1632, LPVOID);
|
|
TO_STACK32(pti, (DWORD)&cbc, DWORD);
|
|
}
|
|
|
|
pti->pThop++;
|
|
return EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_CLSCONTEXT_1632, public
|
|
//
|
|
// Synopsis: Converts a class context flags DWORD
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 29-Jun-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_CLSCONTEXT_1632(THUNKINFO *pti)
|
|
{
|
|
DWORD dwClsContext;
|
|
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == 0);
|
|
|
|
GET_STACK16(pti, dwClsContext, DWORD);
|
|
|
|
// When passing a 16-bit class context on to 32-bits,
|
|
// add on a flag to indicate that this is a 16-bit request
|
|
// in the inproc server case
|
|
|
|
if (dwClsContext & CLSCTX_INPROC_SERVER)
|
|
{
|
|
dwClsContext |= CLSCTX_INPROC_SERVER16;
|
|
}
|
|
|
|
TO_STACK32(pti, dwClsContext, DWORD);
|
|
|
|
pti->pThop++;
|
|
return EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_FILENAME_1632, public
|
|
//
|
|
// Synopsis: Converts a filename string
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Aug-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_FILENAME_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
|
|
|
|
// Can be in or out only
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
|
|
(*pti->pThop & THOP_IOMASK) == THOP_OUT);
|
|
|
|
if ((*pti->pThop & THOP_IN) != 0)
|
|
{
|
|
// No special processing is necessary for filenames going
|
|
// from 16->32 since it isn't possible for 16-bit code to
|
|
// generate a filename which can't be handled in 32-bits
|
|
|
|
return ThunkInString1632(pti);
|
|
}
|
|
else
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OUT) != 0);
|
|
|
|
// Convert filenames going from 32->16 to short filenames
|
|
// to avoid any possible problems with non-8.3 names.
|
|
|
|
return ThunkOutString1632(pti, TRUE);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_SIZEDSTRING_1632, public
|
|
//
|
|
// Synopsis: Converts strings which cannot exceed a given length
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Sep-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_SIZEDSTRING_1632(THUNKINFO *pti)
|
|
{
|
|
thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
|
|
thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
|
|
|
|
// For 16->32, there are no limits on string length so
|
|
// thunk the string normally
|
|
|
|
// Advance once to account for the length byte
|
|
// ThunkInString will advance again
|
|
|
|
pti->pThop++;
|
|
return ThunkInString1632(pti);
|
|
}
|
|
|
|
#define THOP_FN(x) Thop_ ## x ## _1632
|
|
|
|
DWORD (*CONST aThopFunctions1632[])(THUNKINFO *) =
|
|
{
|
|
|
|
// x = Implemented
|
|
// ? = Mysteriously not needed
|
|
// = Left to do
|
|
//
|
|
// ^
|
|
// |
|
|
// +===+
|
|
// |
|
|
// v
|
|
//
|
|
ThunkCall1632, // x Terminating THOP
|
|
Thop_ShortToLong_1632, // x SHORTLONG
|
|
Thop_WordToDword_1632, // x WORDDWORD
|
|
Thop_Copy_1632, // x COPY
|
|
THOP_FN(LPSTR), // x LPSTR
|
|
THOP_FN(LPLPSTR), // x LPLPSTR
|
|
THOP_FN(BUFFER), // x BUFFER
|
|
Thop_UserHandle_1632, // x HUSER
|
|
Thop_GdiHandle_1632, // x HGDI
|
|
THOP_FN(SIZE), // x SIZE
|
|
THOP_FN(RECT), // x RECT
|
|
THOP_FN(MSG), // x MSG
|
|
THOP_FN(HRESULT), // x HRESULT
|
|
THOP_FN(STATSTG), // x STATSTG
|
|
THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
|
|
THOP_FN(STGMEDIUM), // x STGMEDIUM
|
|
THOP_FN(FORMATETC), // x FORMATETC
|
|
THOP_FN(HACCEL), // x HACCEL
|
|
THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
|
|
THOP_FN(BINDOPTS), // x BIND_OPTS
|
|
THOP_FN(LOGPALETTE), // x LOGPALETTE
|
|
THOP_FN(SNB), // x SNB
|
|
THOP_FN(CRGIID), // x CRGIID
|
|
THOP_FN(OLESTREAM), // x OLESTREAM
|
|
THOP_FN(HTASK), // x HTASK
|
|
THOP_FN(INTERFACEINFO), // x INTERFACEINFO
|
|
THOP_FN(IFACE), // x IFACE
|
|
THOP_FN(IFACE), // x IFACEOWNER
|
|
THOP_FN(IFACE), // x IFACENOADDREF
|
|
Thop_ERROR_1632, // x IFACECLEAN
|
|
THOP_FN(IFACEGEN), // x IFACEGEN
|
|
THOP_FN(IFACEGEN), // x IFACEGENOWNER
|
|
THOP_FN(IFACE), // x UNKOUTER
|
|
Thop_ERROR_1632, // x UNKINNER
|
|
Thop_ERROR_1632, // x ROUTINE_INDEX
|
|
THOP_FN(RETURNTYPE), // x RETURN_TYPE
|
|
THOP_FN(NULL), // x NULL
|
|
Thop_ERROR_1632, // x ERROR
|
|
THOP_FN(ENUM), // x ENUM
|
|
THOP_FN(CALLBACK), // x CALLBACK
|
|
THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
|
|
THOP_FN(ALIAS32), // x ALIAS32
|
|
THOP_FN(CLSCONTEXT), // x CLSCONTEXT
|
|
THOP_FN(FILENAME), // x FILENAME
|
|
THOP_FN(SIZEDSTRING), // x SIZEDSTRING
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: General_Enum_1632, private
|
|
//
|
|
// Synopsis: Thunking for standard OLE enumerator interface ::Next member
|
|
// function.
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
// [uiSize32] - 32-bit information size
|
|
// [uiSize16] - 16-bit information size
|
|
// [pfnCallback] - Data thunking callback
|
|
// [pfnCleanup] - Thunking cleanup
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This handler is called from many IXXXEnum::Next handlers thop
|
|
// thunks to do the standard sorts of "buffer of structures"
|
|
// processing.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#define MAX_ALLOCA_STRUCT 10
|
|
|
|
DWORD General_Enum_1632(
|
|
THUNKINFO *pti,
|
|
UINT uiSize32,
|
|
UINT uiSize16,
|
|
SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
|
|
void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
|
|
{
|
|
DWORD dwResult;
|
|
ULONG ulCount;
|
|
VPVOID vpstruct16;
|
|
VPVOID vpfetched16;
|
|
LPVOID lpstruct32;
|
|
LPVOID lpstruct32Iterate;
|
|
VPVOID vpstruct16Iterate;
|
|
ULONG ulFetched32;
|
|
ULONG *lpfetched32;
|
|
ULONG UNALIGNED *lpfetched16;
|
|
ULONG ulIterate;
|
|
LPVOID lp16;
|
|
BOOL fError;
|
|
SCODE sc;
|
|
|
|
dwResult = (DWORD)S_OK;
|
|
|
|
GET_STACK16(pti, ulCount, ULONG );
|
|
GET_STACK16(pti, vpstruct16, VPVOID );
|
|
GET_STACK16(pti, vpfetched16, VPVOID );
|
|
|
|
//
|
|
// THIS ROUTINE CAN DEAL WITH dwResult RATHER THAN pti->scResult BECAUSE
|
|
// WE KNOW THIS IS THE ONLY THOP FOR THIS FUNCTION! NO OTHER CLEANUP
|
|
// WILL HAVE TO BE DONE!
|
|
//
|
|
ulFetched32 = 0;
|
|
lpfetched32 = &ulFetched32;
|
|
lp16 = NULL;
|
|
lpstruct32 = NULL;
|
|
|
|
if ( vpstruct16 != 0 )
|
|
{
|
|
if ( ulCount == 0 )
|
|
{
|
|
dwResult = (DWORD)E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Verify we have write access to the 16-bit memory.
|
|
//
|
|
lp16 = GetWritePtr16(pti, vpstruct16, uiSize16*ulCount);
|
|
if ( lp16 == NULL )
|
|
{
|
|
dwResult = (DWORD)E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
if ( ulCount > MAX_ALLOCA_STRUCT )
|
|
{
|
|
lpstruct32 = (LPVOID)CoTaskMemAlloc( ulCount * uiSize32 );
|
|
if (lpstruct32 == NULL)
|
|
{
|
|
dwResult = (DWORD)E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpstruct32 = (LPVOID)STACKALLOC32( ulCount * uiSize32 );
|
|
if (lpstruct32 == NULL)
|
|
{
|
|
dwResult = (DWORD)E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
WOWRELVDMPTR(vpstruct16);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(dwResult))
|
|
{
|
|
TO_STACK32(pti, ulCount, ULONG);
|
|
TO_STACK32(pti, lpstruct32, LPVOID);
|
|
TO_STACK32(pti, lpfetched32, ULONG FAR *);
|
|
|
|
pti->pThop++;
|
|
dwResult = EXECUTE_THOP1632(pti);
|
|
}
|
|
|
|
if ( SUCCEEDED(dwResult) )
|
|
{
|
|
if ( vpstruct16 != 0 )
|
|
{
|
|
// Some apps (MsWorks3 is one) return S_FALSE and do not return
|
|
// the number of elements retrieved. The only thing we can
|
|
// do is ignore the enumeration since we don't know how many
|
|
// were actually set. Of course, we can't ignore all enumerations
|
|
// when the return is S_FALSE so we only handle the case
|
|
// where S_FALSE was returned on a enumeration of one element,
|
|
// in which we can be sure there isn't any valid data
|
|
if (dwResult == (DWORD)S_FALSE && ulCount == 1)
|
|
{
|
|
ulFetched32 = 0;
|
|
}
|
|
|
|
//
|
|
// Iterate through all of the structures, converting them
|
|
// into 16-bit
|
|
//
|
|
fError = FALSE;
|
|
ulIterate = 0;
|
|
vpstruct16Iterate = vpstruct16;
|
|
lpstruct32Iterate = lpstruct32;
|
|
|
|
while ( ulIterate < ulFetched32 )
|
|
{
|
|
//
|
|
// Callback to the callback function to do any specific
|
|
// processing
|
|
//
|
|
sc = (*pfnCallback)( pti, lpstruct32Iterate,
|
|
vpstruct16Iterate );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
fError = TRUE;
|
|
dwResult = sc;
|
|
}
|
|
|
|
vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
|
|
uiSize16);
|
|
lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
|
|
uiSize32);
|
|
|
|
ulIterate++;
|
|
}
|
|
|
|
if ( fError )
|
|
{
|
|
//
|
|
// Cleanup all these guys
|
|
//
|
|
ulIterate = 0;
|
|
vpstruct16Iterate = vpstruct16;
|
|
lpstruct32Iterate = lpstruct32;
|
|
|
|
while ( ulIterate <= ulFetched32 )
|
|
{
|
|
(*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
|
|
vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
|
|
uiSize16);
|
|
lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
|
|
uiSize32);
|
|
|
|
ulIterate++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(dwResult) && lp16 != NULL)
|
|
{
|
|
memset(lp16, 0, ulCount*uiSize16);
|
|
}
|
|
|
|
//
|
|
// Free up any space we've allocated
|
|
//
|
|
if (lpstruct32 != NULL)
|
|
{
|
|
if ( ulCount > MAX_ALLOCA_STRUCT )
|
|
{
|
|
CoTaskMemFree( lpstruct32 );
|
|
}
|
|
else
|
|
{
|
|
STACKFREE32(lpstruct32, ulCount*uiSize32);
|
|
}
|
|
}
|
|
|
|
if ( vpfetched16 != 0 )
|
|
{
|
|
lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
|
|
*lpfetched16 = ulFetched32;
|
|
RELVDMPTR(vpfetched16);
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_STRING_1632, public
|
|
//
|
|
// Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
|
|
// space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
VPSTR vpstr;
|
|
VPSTR UNALIGNED *pvpstr16;
|
|
SCODE sc;
|
|
|
|
vpstr = 0;
|
|
sc = ConvertTaskString3216(pti, *(LPOLESTR *)lp32, NULL, 0,
|
|
&vpstr);
|
|
|
|
pvpstr16 = FIXVDMPTR(vp16, VPSTR);
|
|
*pvpstr16 = vpstr;
|
|
RELVDMPTR(vp16);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_STRING_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
VPSTR UNALIGNED *lpvpstr16;
|
|
VPSTR vpstr16;
|
|
|
|
lpvpstr16 = FIXVDMPTR( vp16, VPSTR );
|
|
vpstr16 = *lpvpstr16;
|
|
RELVDMPTR(vp16);
|
|
|
|
if ( vpstr16 != 0 )
|
|
{
|
|
TaskFree16( vpstr16 );
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_STRING_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumSTRING::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_STRING_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(LPOLESTR),
|
|
sizeof(VPSTR),
|
|
Callback_STRING_1632,
|
|
Cleanup_STRING_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_UNKNOWN_1632, public
|
|
//
|
|
// Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
VPVOID vpunknown16;
|
|
SCODE sc = S_OK;
|
|
|
|
vpunknown16 =
|
|
pti->pThkMgr->FindProxy1632(NULL, *(LPUNKNOWN *)lp32, NULL,
|
|
INDEX_IIDIDX(THI_IUnknown), NULL);
|
|
|
|
// Release the actual 32-bit IUnknown as it is a OUT parameter
|
|
// This could be the last release on the interface if the
|
|
// above call failed;
|
|
(*((LPUNKNOWN *) lp32))->Release();
|
|
|
|
if(!vpunknown16) {
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
|
|
*FIXVDMPTR( vp16, VPVOID ) = vpunknown16;
|
|
RELVDMPTR(vp16);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_UNKNOWN_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
LPUNKNOWN lpunknown32;
|
|
VPVOID vpunknown16;
|
|
|
|
vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
|
|
RELVDMPTR(vp16);
|
|
lpunknown32 = *(LPUNKNOWN *)lp32;
|
|
|
|
if(vpunknown16) {
|
|
// Release the proxy to 32-bit interface
|
|
pti->pThkMgr->ReleaseProxy1632(vpunknown16);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_UNKNOWN_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumUNKNOWN::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_UNKNOWN_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(LPUNKNOWN),
|
|
sizeof(LPUNKNOWN),
|
|
Callback_UNKNOWN_1632,
|
|
Cleanup_UNKNOWN_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_STATSTG_1632, public
|
|
//
|
|
// Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
(FIXVDMPTR(vp16, STATSTG))->pwcsName = NULL;
|
|
RELVDMPTR(vp16);
|
|
return ConvertStatStg3216(pti, (STATSTG *)lp32, vp16,
|
|
NULL, 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_STATSTG_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
STATSTG UNALIGNED *lpstatstg16;
|
|
VPVOID vpstr;
|
|
|
|
lpstatstg16 = FIXVDMPTR( vp16, STATSTG );
|
|
vpstr = (VPVOID)lpstatstg16->pwcsName;
|
|
RELVDMPTR(vp16);
|
|
|
|
if ( vpstr != 0)
|
|
{
|
|
TaskFree16( vpstr );
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_STATSTG_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumSTATSTG::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_STATSTG_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(STATSTG),
|
|
sizeof(STATSTG),
|
|
Callback_STATSTG_1632,
|
|
Cleanup_STATSTG_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_FORMATETC_1632, public
|
|
//
|
|
// Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
(FIXVDMPTR(vp16, FORMATETC16))->ptd = NULL;
|
|
RELVDMPTR(vp16);
|
|
return ConvertFetc3216(pti, (FORMATETC *)lp32, vp16, TRUE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_FORMATETC_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
FORMATETC16 UNALIGNED *lpformatetc16;
|
|
VPVOID vptd;
|
|
|
|
lpformatetc16 = FIXVDMPTR( vp16, FORMATETC16 );
|
|
vptd = lpformatetc16->ptd;
|
|
RELVDMPTR(vp16);
|
|
|
|
if (vptd != 0)
|
|
{
|
|
TaskFree16(vptd);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_FORMATETC_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumFORMATETC::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_FORMATETC_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(FORMATETC),
|
|
sizeof(FORMATETC16),
|
|
Callback_FORMATETC_1632,
|
|
Cleanup_FORMATETC_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_STATDATA_1632, public
|
|
//
|
|
// Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
SCODE Callback_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
SCODE sc;
|
|
LPSTATDATA lpstatdata32;
|
|
STATDATA16 UNALIGNED *lpstatdata16;
|
|
VPVOID vpadv16;
|
|
|
|
sc = S_OK;
|
|
|
|
lpstatdata32 = (LPSTATDATA)lp32;
|
|
|
|
if (lpstatdata32->pAdvSink != NULL)
|
|
{
|
|
// We don't know whether it's an AdviseSink or
|
|
// an AdviseSink2, so pass AdviseSink2 since it's
|
|
// a superset of AdviseSink and will work for both
|
|
|
|
vpadv16 = pti->pThkMgr->FindProxy1632(NULL, lpstatdata32->pAdvSink, NULL,
|
|
INDEX_IIDIDX(THI_IAdviseSink2),
|
|
NULL);
|
|
|
|
// Release the actual 32-bit IAdviseSink as it is a OUT parameter
|
|
// This could be the last release on the interface if the
|
|
// above call failed;
|
|
lpstatdata32->pAdvSink->Release();
|
|
|
|
if(!vpadv16) {
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vpadv16 = 0;
|
|
}
|
|
|
|
lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
|
|
lpstatdata16->formatetc.ptd = NULL;
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
// If this fails the AdviseSink proxy will be cleaned up in
|
|
// the cleanup function later
|
|
|
|
sc = ConvertFetc3216(pti,
|
|
&lpstatdata32->formatetc,
|
|
vp16+FIELD_OFFSET(STATDATA16, formatetc), TRUE);
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
lpstatdata16->advf = lpstatdata32->advf;
|
|
lpstatdata16->pAdvSink = vpadv16;
|
|
lpstatdata16->dwConnection = lpstatdata32->dwConnection;
|
|
}
|
|
|
|
RELVDMPTR(vp16);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_STATDATA_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
STATDATA *lpstatdata32;
|
|
STATDATA16 UNALIGNED *lpstatdata16;
|
|
LPADVISESINK lpadv32;
|
|
VPVOID vptd;
|
|
|
|
lpstatdata32 = (STATDATA FAR *)lp32;
|
|
lpadv32 = lpstatdata32->pAdvSink;
|
|
|
|
lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
|
|
vptd = lpstatdata16->formatetc.ptd;
|
|
RELVDMPTR(vp16);
|
|
|
|
if(lpstatdata16->pAdvSink) {
|
|
// Release the proxy to 32-bit interface
|
|
pti->pThkMgr->ReleaseProxy1632((VPVOID) lpstatdata32->pAdvSink);
|
|
}
|
|
|
|
if (vptd != 0)
|
|
{
|
|
TaskFree16(vptd);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_STATDATA_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumSTATDATA::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_STATDATA_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(STATDATA),
|
|
sizeof(STATDATA16),
|
|
Callback_STATDATA_1632,
|
|
Cleanup_STATDATA_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_MONIKER_1632, public
|
|
//
|
|
// Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
VPVOID vpmoniker16;
|
|
SCODE sc = S_OK;
|
|
|
|
vpmoniker16 = pti->pThkMgr->FindProxy1632(NULL, *(LPMONIKER *)lp32, NULL,
|
|
INDEX_IIDIDX(THI_IMoniker),
|
|
NULL);
|
|
|
|
// Release the actual 32-bit IMoniker as it is a OUT parameter
|
|
// This could be the last release on the interface if the
|
|
// above call failed;
|
|
(*(LPMONIKER *)lp32)->Release();
|
|
|
|
if(!vpmoniker16) {
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
|
|
*FIXVDMPTR(vp16, VPVOID) = vpmoniker16;
|
|
RELVDMPTR(vp16);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_MONIKER_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
LPMONIKER lpmoniker32;
|
|
VPVOID vpmoniker16;
|
|
|
|
vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
|
|
RELVDMPTR(vp16);
|
|
lpmoniker32 = *(LPMONIKER *)lp32;
|
|
|
|
if(vpmoniker16) {
|
|
pti->pThkMgr->ReleaseProxy1632(vpmoniker16);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_MONIKER_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumMONIKER::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_MONIKER_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(LPMONIKER),
|
|
sizeof(LPMONIKER),
|
|
Callback_MONIKER_1632,
|
|
Cleanup_MONIKER_1632 );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Callback_OLEVERB_1632, public
|
|
//
|
|
// Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
|
|
// address space.
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: SCODE indicating success/failure
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Callback_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
SCODE sc;
|
|
OLEVERB *lpoleverb32;
|
|
OLEVERB UNALIGNED *lpoleverb16;
|
|
VPSTR vpstr;
|
|
|
|
lpoleverb32 = (LPOLEVERB)lp32;
|
|
vpstr = 0;
|
|
sc = ConvertTaskString3216(pti, lpoleverb32->lpszVerbName, NULL, 0,
|
|
&vpstr);
|
|
lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
|
|
lpoleverb16->lpszVerbName = (LPOLESTR)vpstr;
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
lpoleverb16->lVerb = lpoleverb32->lVerb;
|
|
lpoleverb16->fuFlags = lpoleverb32->fuFlags;
|
|
lpoleverb16->grfAttribs = lpoleverb32->grfAttribs;
|
|
}
|
|
RELVDMPTR(vp16);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Cleanup_OLEVERB_1632, public
|
|
//
|
|
// Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
|
|
// or 32-bit)
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [lp32] - Pointer to 32-bit returned structure
|
|
// [lp16] - Pointer to 16-bit output structure
|
|
//
|
|
// Returns: nothing, should NEVER fail
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Cleanup_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
|
|
{
|
|
OLEVERB UNALIGNED *lpoleverb16;
|
|
VPVOID vpstr;
|
|
|
|
lpoleverb16 = FIXVDMPTR( vp16, OLEVERB );
|
|
vpstr = (VPVOID)lpoleverb16->lpszVerbName;
|
|
RELVDMPTR(vp16);
|
|
|
|
if ( vpstr != 0 )
|
|
{
|
|
TaskFree16( vpstr );
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Thop_Enum_OLEVERB_1632, public
|
|
//
|
|
// Synopsis: Thunks IEnumOLEVERB::Next parameters
|
|
//
|
|
// Arguments: [pti] - Thunk state information
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 1-Mar-94 BobDay Created
|
|
//
|
|
// Notes: This thunk is 2nd part of a 2-byte thop.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD Thop_Enum_OLEVERB_1632(THUNKINFO *pti)
|
|
{
|
|
return General_Enum_1632(pti,
|
|
sizeof(OLEVERB),
|
|
sizeof(OLEVERB),
|
|
Callback_OLEVERB_1632,
|
|
Cleanup_OLEVERB_1632 );
|
|
}
|
|
|
|
#define THOP_EFN(x) Thop_Enum_ ## x ## _1632
|
|
|
|
DWORD (*CONST aThopEnumFunctions1632[])(THUNKINFO *) =
|
|
{
|
|
THOP_EFN(STRING), // STRING
|
|
THOP_EFN(UNKNOWN), // UNKNOWN
|
|
THOP_EFN(STATSTG), // STATSTG
|
|
THOP_EFN(FORMATETC), // FORMATETC
|
|
THOP_EFN(STATDATA), // STATDATA
|
|
THOP_EFN(MONIKER), // MONIKER
|
|
THOP_EFN(OLEVERB), // OLEVERB
|
|
};
|
|
|
|
|