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.
4557 lines
115 KiB
4557 lines
115 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
|
//
|
|
// File: thoputil.cxx
|
|
//
|
|
// Contents: Utility routines for thunking
|
|
//
|
|
// History: 01-Mar-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
|
|
#include <vdmdbg.h>
|
|
#include <valid.h>
|
|
|
|
//
|
|
// Chicago doesn't support the NT ExpLdr API, use the new Chicago
|
|
// WOWGetDescriptor that copies the LDT info to a provided buffer.
|
|
//
|
|
#if defined(_CHICAGO_)
|
|
extern "C" WOWGetDescriptor(VPVOID, VDMLDT_ENTRY *);
|
|
#else
|
|
extern "C" DECLSPEC_IMPORT VDMLDT_ENTRY *ExpLdt;
|
|
#endif
|
|
|
|
#include "struct16.hxx"
|
|
|
|
#define CF_INVALID ((CLIPFORMAT)0)
|
|
|
|
#define OBJDESC_CF(cf) \
|
|
((cf) == g_cfObjectDescriptor || (cf) == g_cfLinkSourceDescriptor)
|
|
|
|
// Alias manager for THOP_ALIAS32
|
|
CAliases gAliases32;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IidToIidIdx, public
|
|
//
|
|
// Synopsis: Looks up an interface index by IID
|
|
// If it's not found, it returns the IID pointer
|
|
//
|
|
// Arguments: [riid] - IID
|
|
//
|
|
// Returns: Index or IID
|
|
//
|
|
// History: 23-Feb-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
IIDIDX IidToIidIdx(REFIID riid)
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < THI_COUNT; idx++)
|
|
{
|
|
if (IsEqualIID(riid, *aittIidToThi[idx].piid))
|
|
{
|
|
return INDEX_IIDIDX(aittIidToThi[idx].iThi);
|
|
}
|
|
}
|
|
|
|
return IID_IIDIDX(&riid);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TaskMalloc32, public
|
|
//
|
|
// Synopsis: Task allocation for 32-bits
|
|
//
|
|
// History: 01-Mar-94 DrewB Created
|
|
//
|
|
// Notes: Temporary until CoTaskMemAlloc is hooked up
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef COTASK_DEFINED
|
|
LPVOID TaskMalloc32(SIZE_T cb)
|
|
{
|
|
IMalloc *pm;
|
|
LPVOID pv;
|
|
|
|
if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
pv = pm->Alloc(cb);
|
|
pm->Release();
|
|
}
|
|
return pv;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TaskFree32, public
|
|
//
|
|
// Synopsis: Task free for 32-bits
|
|
//
|
|
// History: 01-Mar-94 DrewB Created
|
|
//
|
|
// Notes: Temporary until CoTaskMemAlloc is hooked up
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void TaskFree32(LPVOID pv)
|
|
{
|
|
IMalloc *pm;
|
|
|
|
if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
|
|
{
|
|
thkAssert(!"CoGetMalloc failed");
|
|
}
|
|
else
|
|
{
|
|
pm->Free(pv);
|
|
pm->Release();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TaskMalloc16, public
|
|
//
|
|
// Synopsis: Allocates 16-bit task memory
|
|
//
|
|
// Arguments: [uiSize] - Amount of memory to allocate
|
|
//
|
|
// Returns: VPVOID for memory allocated
|
|
//
|
|
// History: 01-Mar-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD TaskMalloc16( UINT uiSize )
|
|
{
|
|
return CallbackTo16(gdata16Data.fnTaskAlloc, uiSize);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TaskFree16, public
|
|
//
|
|
// Synopsis: Frees 16-bit task memory
|
|
//
|
|
// Arguments: [vpvoid] - VPVOID of allocated memory
|
|
//
|
|
// History: 01-Mar-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void TaskFree16( DWORD vpvoid )
|
|
{
|
|
CallbackTo16(gdata16Data.fnTaskFree, vpvoid);
|
|
}
|
|
|
|
// List of 16/32 HRESULT mappings for mapping functions
|
|
struct SHrMapping
|
|
{
|
|
HRESULT hr16;
|
|
HRESULT hr32;
|
|
};
|
|
|
|
// Since we're including 32-bit headers in this code we can use
|
|
// the defines for the 32-bit values but we must specify the
|
|
// 16-bit values explicitly
|
|
static SHrMapping hmMappings[] =
|
|
{
|
|
0x80000001, E_NOTIMPL,
|
|
0x80000002, E_OUTOFMEMORY,
|
|
0x80000003, E_INVALIDARG,
|
|
0x80000004, E_NOINTERFACE,
|
|
0x80000005, E_POINTER,
|
|
0x80000006, E_HANDLE,
|
|
0x80000007, E_ABORT,
|
|
0x80000008, E_FAIL,
|
|
0x80000009, E_ACCESSDENIED
|
|
};
|
|
#define NMAPPINGS (sizeof(hmMappings)/sizeof(hmMappings[0]))
|
|
|
|
#define HR16_ERROR 0x80000000
|
|
#define HR16_MAP_FIRST 1
|
|
#define HR16_MAP_LAST 9
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TransformHRESULT_1632, public
|
|
//
|
|
// Synopsis: Translates a 16-bit hresult into a 32-bit hresult
|
|
//
|
|
// Arguments: [hresult] - 16-bit hresult to transform
|
|
//
|
|
// History: 15-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult )
|
|
{
|
|
ULONG ulIndex;
|
|
|
|
// We only map error codes
|
|
if (hresult & HR16_ERROR)
|
|
{
|
|
// The 16-bit HRESULTs to be mapped are known quantities
|
|
// whose values are sequential, so we can map directly from
|
|
// the value to an array index
|
|
|
|
ulIndex = hresult & ~HR16_ERROR;
|
|
if (ulIndex >= HR16_MAP_FIRST && ulIndex <= HR16_MAP_LAST)
|
|
{
|
|
// Known value, index array to find 32-bit HRESULT
|
|
return hmMappings[ulIndex-HR16_MAP_FIRST].hr32;
|
|
}
|
|
}
|
|
|
|
// No mapping found, so return the original
|
|
return hresult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TransformHRESULT_3216, public
|
|
//
|
|
// Synopsis: Translates a 32-bit hresult into a 16-bit hresult
|
|
//
|
|
// Arguments: [hresult] - 32-bit hresult to transform
|
|
//
|
|
// History: 15-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult )
|
|
{
|
|
int i;
|
|
SHrMapping *phm;
|
|
|
|
// We don't know the true values of 32-bit HRESULTs since we're
|
|
// using the defines and they may change, so we have to look up
|
|
// the hard way
|
|
|
|
phm = hmMappings;
|
|
for (i = 0; i < NMAPPINGS; i++)
|
|
{
|
|
if (phm->hr32 == (HRESULT)hresult)
|
|
{
|
|
return phm->hr16;
|
|
}
|
|
|
|
phm++;
|
|
}
|
|
|
|
// No mapping found, so return the original
|
|
return hresult;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RecordStackState, public debug
|
|
//
|
|
// Synopsis: Records the current state of the stack
|
|
//
|
|
// Arguments: [psr] - Storage space for information
|
|
//
|
|
// Modifies: [psr]
|
|
//
|
|
// History: 28-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
void RecordStackState16(SStackRecord *psr)
|
|
{
|
|
CStackAllocator *psa;
|
|
|
|
psa = TlsThkGetStack16();
|
|
psa->RecordState(psr);
|
|
}
|
|
|
|
void RecordStackState32(SStackRecord *psr)
|
|
{
|
|
CStackAllocator *psa;
|
|
|
|
psa = TlsThkGetStack32();
|
|
psa->RecordState(psr);
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CheckStackState, public debug
|
|
//
|
|
// Synopsis: Checks recorded information about the stack against its
|
|
// current state
|
|
//
|
|
// Arguments: [psr] - Recorded information
|
|
//
|
|
// History: 28-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
void CheckStackState16(SStackRecord *psr)
|
|
{
|
|
CStackAllocator *psa;
|
|
|
|
psa = TlsThkGetStack16();
|
|
psa->CheckState(psr);
|
|
}
|
|
|
|
void CheckStackState32(SStackRecord *psr)
|
|
{
|
|
CStackAllocator *psa;
|
|
|
|
psa = TlsThkGetStack32();
|
|
psa->CheckState(psr);
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Convert_VPSTR_to_LPOLESTR
|
|
//
|
|
// Synopsis: Converts 16-bit VPSTR to 32-bit LPOLESTR pointer
|
|
//
|
|
// Arguments: [vpstr] - VPSTR
|
|
// [lpOleStr] - OLESTR
|
|
// [uiSizeInPlace] - Amount of data available in [lpOleStr]
|
|
// for in-place conversion (in characters, not bytes)
|
|
// including nul
|
|
//
|
|
// Returns: Pointer to LPOLESTR with data
|
|
//
|
|
// History: 24-Feb-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPOLESTR Convert_VPSTR_to_LPOLESTR(
|
|
THUNKINFO *pti,
|
|
VPSTR vpstr,
|
|
LPOLESTR lpOleStr,
|
|
UINT uiSizeInPlace
|
|
)
|
|
{
|
|
LPSTR lpstr;
|
|
UINT uiSize;
|
|
LPOLESTR lpOleStrResult;
|
|
UINT cChars;
|
|
|
|
// We shouldn't be calling here for null strings
|
|
thkAssert( vpstr != NULL );
|
|
|
|
lpstr = GetStringPtr16(pti, vpstr, CCHMAXSTRING, &uiSize);
|
|
if ( lpstr == NULL )
|
|
{
|
|
//
|
|
// GetStringPtr will have filled in the pti->scResult
|
|
//
|
|
return( NULL );
|
|
}
|
|
|
|
// The string has to have at least one character in it
|
|
// because it must be null-terminated to be valid
|
|
thkAssert(uiSize > 0);
|
|
|
|
lpOleStrResult = lpOleStr;
|
|
|
|
if ( uiSize > uiSizeInPlace )
|
|
{
|
|
lpOleStrResult = (LPOLESTR)TaskMalloc32(uiSize*sizeof(OLECHAR));
|
|
if (lpOleStrResult == NULL)
|
|
{
|
|
pti->scResult = E_OUTOFMEMORY;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
cChars = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0,
|
|
lpstr,
|
|
uiSize,
|
|
lpOleStrResult,
|
|
uiSize );
|
|
|
|
WOWRELVDMPTR(vpstr);
|
|
|
|
if ( cChars == 0 )
|
|
{
|
|
if (lpOleStrResult != lpOleStr)
|
|
{
|
|
TaskFree32(lpOleStrResult);
|
|
}
|
|
|
|
pti->scResult = E_UNEXPECTED;
|
|
return( NULL );
|
|
}
|
|
else
|
|
{
|
|
return( lpOleStrResult );
|
|
}
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Convert_LPOLESTR_to_VPSTR
|
|
//
|
|
// Synopsis: Converts 32-bit LPOLESTR to 16-bit VPSTR pointer
|
|
//
|
|
// Arguments: [lpOleStr] - OLESTR
|
|
// [vpstr] - VPSTR
|
|
// [uiSize32] - Length of OLESTR in characters (not bytes)
|
|
// including nul
|
|
// [uiSize16] - Byte length of buffer referred to by VPSTR
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Feb-94 BobDay Created
|
|
//
|
|
// Notes: Always converts in place
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Convert_LPOLESTR_to_VPSTR(
|
|
LPCOLESTR lpOleStr,
|
|
VPSTR vpstr,
|
|
UINT uiSize32,
|
|
UINT uiSize16
|
|
)
|
|
{
|
|
LPSTR lpstr;
|
|
UINT cChars;
|
|
SCODE sc;
|
|
|
|
sc = S_OK;
|
|
|
|
lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
|
|
|
|
cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0,
|
|
lpOleStr,
|
|
uiSize32,
|
|
lpstr,
|
|
uiSize16,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( cChars == 0 && uiSize32 != 0 )
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
}
|
|
|
|
WOWRELVDMPTR(vpstr);
|
|
|
|
return sc;
|
|
}
|
|
#ifdef _CHICAGO_
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Convert_LPSTR_to_VPSTR
|
|
//
|
|
// Synopsis: Converts 32-bit LPSTR to 16-bit VPSTR pointer
|
|
//
|
|
// Arguments: [lpOleStr] - LPSTR
|
|
// [vpstr] - VPSTR
|
|
// [uiSize32] - Length of LPSTR in bytes including nul
|
|
// [uiSize16] - Byte length of buffer referred to by VPSTR
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 10-21-95 KevinRo Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE Convert_LPSTR_to_VPSTR(
|
|
LPCSTR lpOleStr,
|
|
VPSTR vpstr,
|
|
UINT uiSize32,
|
|
UINT uiSize16
|
|
)
|
|
{
|
|
LPSTR lpstr;
|
|
|
|
lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
|
|
|
|
memcpy(lpstr,lpOleStr,uiSize32);
|
|
|
|
WOWRELVDMPTR(vpstr);
|
|
|
|
return S_OK;
|
|
}
|
|
#endif // _CHICAGO_
|
|
|
|
// Selector bit constants
|
|
#define SEL_TI 0x0004
|
|
#define SEL_RPL 0x0003
|
|
#define SEL_INDEX 0xfff8
|
|
|
|
#define IS_LDT_SELECTOR(sel) (((sel) & SEL_TI) == SEL_TI)
|
|
|
|
// LDT bit constants
|
|
#define LTYPE_APP 0x0010
|
|
#define LTYPE_CODE 0x0008
|
|
#define LTYPE_CREAD 0x0002
|
|
#define LTYPE_DDOWN 0x0004
|
|
#define LTYPE_DWRITE 0x0002
|
|
|
|
// Pointer access types, or'able
|
|
// Defined to be the same as thop in/out so that no translation
|
|
// is necessary for checks on thop memory access
|
|
#define PACC_READ THOP_IN
|
|
#define PACC_WRITE THOP_OUT
|
|
#define PACC_CODE 1 // Special for CODE PTRs
|
|
|
|
// Information about a VDM pointer
|
|
typedef struct _VPTRDESC
|
|
{
|
|
BYTE *pbFlat;
|
|
DWORD dwLengthLeft;
|
|
} VPTRDESC;
|
|
|
|
// VDM memory is always zero-based on Win95
|
|
#ifndef _CHICAGO_
|
|
DWORD dwBaseVDMMemory = 0xFFFFFFFF;
|
|
#else
|
|
#define dwBaseVDMMemory 0
|
|
#endif
|
|
|
|
// Extended success returns from GetPtr16Description
|
|
#define S_GDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
|
|
#define S_SYSLDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 2)
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetPtr16Description, public
|
|
//
|
|
// Synopsis: Validates access for a VDM pointer and returns
|
|
// information about it
|
|
// Also forces not-present segments into memory by
|
|
// touching them
|
|
//
|
|
// Arguments: [vp] - VDM pointer
|
|
// [grfAccess] - Desired access
|
|
// [dwSize] - Desired size of access, must be >= 1
|
|
// [pvpd] - VPTRDESC out
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pvpd]
|
|
//
|
|
// History: 26-Apr-94 DrewB Created
|
|
//
|
|
// Notes: Returns fixed memory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE GetPtr16Description(VPVOID vp,
|
|
WORD grfAccess,
|
|
DWORD dwSize,
|
|
VPTRDESC *pvpd)
|
|
{
|
|
VDMLDT_ENTRY *vle;
|
|
#if defined(_CHICAGO_)
|
|
VDMLDT_ENTRY LdtEntry;
|
|
#endif
|
|
WORD wSel;
|
|
WORD wOff;
|
|
DWORD dwLength;
|
|
|
|
thkAssert(vp != 0);
|
|
thkAssert(dwSize > 0);
|
|
thkAssert(grfAccess != 0);
|
|
|
|
wSel = (WORD)(vp >> 16);
|
|
wOff = (WORD)(vp & 0xffff);
|
|
|
|
pvpd->dwLengthLeft = 0xffff-wOff+1; // Default length remaining
|
|
|
|
if (!IS_LDT_SELECTOR(wSel))
|
|
{
|
|
// According to the WOW developers, the only GDT selector
|
|
// is for the BIOS data area so we should never see one
|
|
|
|
thkDebugOut((DEB_ERROR, "GDT selector: 0x%04X\n", wSel));
|
|
|
|
// Handle it just in case
|
|
pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
|
|
|
|
return S_GDTENTRY;
|
|
}
|
|
|
|
#if defined(_CHICAGO_)
|
|
vle = &LdtEntry;
|
|
if (!WOWGetDescriptor(vp, vle))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
#else
|
|
vle = (VDMLDT_ENTRY *)((BYTE *)(ExpLdt)+(wSel & SEL_INDEX));
|
|
#endif
|
|
|
|
if ((vle->HighWord.Bits.Type & LTYPE_APP) == 0)
|
|
{
|
|
// According to the WOW developers, they don't use
|
|
// system segments so we should never see one
|
|
|
|
thkDebugOut((DEB_ERROR, "System descriptor: 0x%04X\n", wSel));
|
|
|
|
// Handle it just in case
|
|
pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
|
|
|
|
return S_SYSLDTENTRY;
|
|
}
|
|
|
|
// Do as much up-front validation as possible
|
|
// Since the segment may not be present, we are restricted to
|
|
// only checking the access permissions
|
|
|
|
if (vle->HighWord.Bits.Type & LTYPE_CODE)
|
|
{
|
|
// Validate access for code segments
|
|
// Code segments are never writable
|
|
|
|
if (((grfAccess & PACC_READ) &&
|
|
(vle->HighWord.Bits.Type & LTYPE_CREAD) == 0) ||
|
|
(grfAccess & PACC_WRITE))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Validate access for data segments
|
|
// Data segments are always readable never executable
|
|
|
|
if (((grfAccess & PACC_WRITE) &&
|
|
(vle->HighWord.Bits.Type & LTYPE_DWRITE) == 0) ||
|
|
(grfAccess & PACC_CODE))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
// Bring in segment if it's not present
|
|
if (!vle->HighWord.Bits.Pres)
|
|
{
|
|
// We've validated access permissions and segments must
|
|
// always be at least one byte long so it's safe to
|
|
// touch the first byte to bring it in
|
|
|
|
// On Win95, this will call GlobalFix on the pointer
|
|
// to ensure that it stays in memory
|
|
WOWCallback16(gdata16Data.fnTouchPointer16, vp);
|
|
|
|
#if defined(_CHICAGO_)
|
|
// Since we only copy the descriptor, recopy it now.
|
|
WOWGetDescriptor(vp, vle);
|
|
#endif
|
|
|
|
thkAssert(vle->HighWord.Bits.Pres);
|
|
}
|
|
#ifdef _CHICAGO_
|
|
else
|
|
{
|
|
// Lock the LDT entry (as best as we can) by fixing it
|
|
// This prevents global blocks from being relocated during
|
|
// heap compaction
|
|
WOWGetVDMPointerFix(vp, dwSize, TRUE);
|
|
}
|
|
#endif
|
|
|
|
|
|
dwLength = ((DWORD)vle->LimitLow |
|
|
((DWORD)vle->HighWord.Bits.LimitHi << 16))+1;
|
|
if (vle->HighWord.Bits.Granularity)
|
|
{
|
|
// 4K granularity
|
|
dwLength <<= 12;
|
|
}
|
|
|
|
if ((vle->HighWord.Bits.Type & LTYPE_CODE) ||
|
|
(vle->HighWord.Bits.Type & LTYPE_DDOWN) == 0)
|
|
{
|
|
// Validate length for code and normal data segments
|
|
|
|
if (wOff+dwSize > dwLength)
|
|
{
|
|
WOWRELVDMPTR(vp);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pvpd->dwLengthLeft = dwLength-wOff;
|
|
}
|
|
else
|
|
{
|
|
// Expand-down segment
|
|
|
|
if (wOff < dwLength)
|
|
{
|
|
WOWRELVDMPTR(vp);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Check for wraparound
|
|
|
|
if (vle->HighWord.Bits.Granularity)
|
|
{
|
|
// Compiler - This should be +1, but
|
|
// the compiler generates a warning about an overflow
|
|
// in constant arithmetic
|
|
pvpd->dwLengthLeft = 0xffffffff-wOff;
|
|
}
|
|
|
|
if (dwSize > pvpd->dwLengthLeft)
|
|
{
|
|
WOWRELVDMPTR(vp);
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
// VDM memory is always zero-based on Win95
|
|
#ifndef _CHICAGO_
|
|
if ( dwBaseVDMMemory == 0xFFFFFFFF )
|
|
{
|
|
dwBaseVDMMemory = (DWORD)WOWGetVDMPointer(0, 0, FALSE);
|
|
}
|
|
#endif
|
|
|
|
// Translate the pointer even on Win95 because forcing the segment
|
|
// present may have changed its address
|
|
pvpd->pbFlat = (BYTE *)(dwBaseVDMMemory +
|
|
wOff +
|
|
( (DWORD)vle->BaseLow |
|
|
( (DWORD)vle->HighWord.Bytes.BaseMid << 16) |
|
|
( (DWORD)vle->HighWord.Bytes.BaseHi << 24) ) );
|
|
|
|
#if DBG == 1
|
|
if (pvpd->pbFlat != WOWGetVDMPointer(vp, dwSize, TRUE))
|
|
{
|
|
thkDebugOut((DEB_ERROR, "GetPtr16Description: "
|
|
"%p computed, %p system\n",
|
|
pvpd->pbFlat, WOWGetVDMPointer(vp, dwSize, TRUE)));
|
|
}
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetReadPtr16
|
|
//
|
|
// Synopsis: Validates a 16-bit pointer for reading and converts it into
|
|
// a flat 32 pointer.
|
|
//
|
|
// Arguments: [pti] - THUNKINFO * for updating error code
|
|
// [vp] - 16-bit pointer to validate/convert
|
|
// [dwSize] - Length to validate
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID *
|
|
GetReadPtr16(
|
|
THUNKINFO *pti,
|
|
VPVOID vp,
|
|
DWORD dwSize )
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
sc = GetPtr16Description(vp, PACC_READ, dwSize, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return vpd.pbFlat;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetWritePtr16
|
|
//
|
|
// Synopsis: Validates a 16-bit pointer for writing and converts it into
|
|
// a flat 32 pointer.
|
|
//
|
|
// Arguments: [pti] - THUNKINFO * for updating error code
|
|
// [vp] - 16-bit pointer to validate/convert
|
|
// [dwSize] - Length to validate
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID *
|
|
GetWritePtr16(
|
|
THUNKINFO *pti,
|
|
VPVOID vp,
|
|
DWORD dwSize )
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
sc = GetPtr16Description(vp, PACC_WRITE, dwSize, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return vpd.pbFlat;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetCodePtr16
|
|
//
|
|
// Synopsis: Validates a 16-bit pointer for execution and converts it
|
|
// into a flat 32 pointer.
|
|
//
|
|
// Arguments: [pti] - THUNKINFO * for updating error code
|
|
// [vp] - 16-bit pointer to validate/convert
|
|
// [dwSize] - Length to validate
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Jul-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID *
|
|
GetCodePtr16(
|
|
THUNKINFO *pti,
|
|
VPVOID vp,
|
|
DWORD dwSize )
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
sc = GetPtr16Description(vp, PACC_CODE, dwSize, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return vpd.pbFlat;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetReadWritePtr16
|
|
//
|
|
// Synopsis: Validates a 16-bit pointer for reading and writing and
|
|
// converts it into a flat 32 pointer.
|
|
//
|
|
// Arguments: [pti] - THUNKINFO * for updating error code
|
|
// [vp] - 16-bit pointer to validate/convert
|
|
// [dwSize] - Length to validate
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID *
|
|
GetReadWritePtr16(
|
|
THUNKINFO *pti,
|
|
VPVOID vp,
|
|
DWORD dwSize )
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
sc = GetPtr16Description(vp, PACC_READ | PACC_WRITE, dwSize, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return vpd.pbFlat;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetStringPtr16
|
|
//
|
|
// Synopsis: Validates a 16-bit pointer to a string for reading and
|
|
// converts it (the pointer) into a flat 32 pointer. It also
|
|
// returns the length, since it has to compute it anyway.
|
|
//
|
|
// Arguments: [pti] - THUNKINFO * for updating error code
|
|
// [vp] - 16-bit pointer to validate/convert
|
|
// [cchMax] - Maximum legal length
|
|
// [lpSize] - Place to return length
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Mar-94 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CHAR *
|
|
GetStringPtr16(
|
|
THUNKINFO *pti,
|
|
VPSTR vp,
|
|
UINT cchMax,
|
|
PUINT lpSize )
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
// Check the first byte to ensure read access to the segment
|
|
sc = GetPtr16Description(vp, PACC_READ, 1, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
UINT cchLen;
|
|
BYTE *pb;
|
|
BOOL fMbLead;
|
|
|
|
pb = vpd.pbFlat;
|
|
|
|
if (pb == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// Restrict zero-termination search to cchMax characters
|
|
// or valid remaining memory
|
|
// Since we specified one in GetPtr16Description, dwLengthLeft
|
|
// is one off here
|
|
cchMax = min(cchMax, vpd.dwLengthLeft+1);
|
|
|
|
cchLen = 0;
|
|
fMbLead = FALSE;
|
|
while (cchMax > 0)
|
|
{
|
|
cchLen++;
|
|
|
|
if (*pb == 0 && !fMbLead)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
fMbLead = (BOOL)g_abLeadTable[*pb++];
|
|
cchMax--;
|
|
}
|
|
}
|
|
|
|
if (cchMax > 0)
|
|
{
|
|
*lpSize = cchLen;
|
|
return (LPSTR)vpd.pbFlat;
|
|
}
|
|
|
|
Exit:
|
|
{
|
|
pti->scResult = E_INVALIDARG;
|
|
WOWRELVDMPTR(vp);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ValidatePtr16, public
|
|
//
|
|
// Synopsis: Calls an appropriate validation routine for 16-bit
|
|
// memory based on in/out status
|
|
//
|
|
// Arguments: [pti] - Thunk info, can be NULL for no validation
|
|
// [vp16] - 16-bit pointer
|
|
// [dwSize] - Size
|
|
// [thopInOut] - In/out type
|
|
//
|
|
// Returns: Pointer or NULL
|
|
//
|
|
// Modifies: [pti]->scResult for errors
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
// Notes: 0 - No validation
|
|
// THOP_IN - Read validation
|
|
// THOP_OUT - Write validation
|
|
// THOP_INOUT - Read/write validation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID *
|
|
ValidatePtr16(THUNKINFO *pti,
|
|
VPVOID vp16,
|
|
DWORD dwSize,
|
|
THOP thopInOut)
|
|
{
|
|
VPTRDESC vpd;
|
|
SCODE sc;
|
|
|
|
thopInOut &= THOP_INOUT;
|
|
if (thopInOut != 0)
|
|
{
|
|
sc = GetPtr16Description(vp16, thopInOut, dwSize, &vpd);
|
|
if (FAILED(sc))
|
|
{
|
|
pti->scResult = sc;
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return vpd.pbFlat;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return WOWFIXVDMPTR(vp16, dwSize);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsValidInterface16, public
|
|
//
|
|
// Synopsis: Validates that a provided 16-bit interface is really valid
|
|
// (uses the same validation technique as 16-bit OLE 2.01)
|
|
//
|
|
// Arguments: [pti] - Thunk info, can be NULL for no validation
|
|
// [vp16] - 16-bit pointer
|
|
//
|
|
// Returns: BOOL - true for valid, false for invalid
|
|
//
|
|
// Modifies: [pti]->scResult for errors
|
|
//
|
|
// History: 22-Jul-92 BobDay Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp )
|
|
{
|
|
VPVOID UNALIGNED *pvpv;
|
|
VPVOID vpvtbl;
|
|
VPVOID vpfn;
|
|
LPVOID lpfn;
|
|
|
|
//
|
|
// Make sure we can read the vtbl pointer from the object.
|
|
//
|
|
pvpv = (VPVOID FAR *)GetReadPtr16(pti, vp, sizeof(VPVOID));
|
|
if ( pvpv == NULL )
|
|
{
|
|
thkDebugOut((DEB_WARN, "IsValidInterface16: "
|
|
"Interface ptr invalid %p\n", vp));
|
|
return FALSE;
|
|
}
|
|
|
|
vpvtbl = *pvpv; // Read the vtbl ptr
|
|
|
|
WOWRELVDMPTR(vp);
|
|
|
|
// Make sure we can read the first entry from the vtbl (QI)
|
|
|
|
pvpv = (VPVOID FAR *)GetReadPtr16(pti, vpvtbl, sizeof(VPVOID));
|
|
if ( pvpv == NULL )
|
|
{
|
|
thkDebugOut((DEB_WARN, "Vtbl ptr invalid %p:%p\n", vp, vpvtbl));
|
|
return FALSE;
|
|
}
|
|
|
|
vpfn = *pvpv; // Get the QI Function
|
|
|
|
WOWRELVDMPTR(vpvtbl);
|
|
|
|
if ( vpfn == 0 )
|
|
{
|
|
thkDebugOut((DEB_WARN, "QI function NULL %p:%p\n", vp, vpvtbl));
|
|
pti->scResult = E_INVALIDARG;
|
|
return FALSE;
|
|
}
|
|
|
|
// Why it has to be 9 bytes long, I have no idea.
|
|
// This check was taken from valid.cpp in
|
|
// \src\ole2\dll\src\debug the 16-bit ole2.01
|
|
// sources...
|
|
lpfn = (LPVOID)GetCodePtr16(pti, vpfn, 9);
|
|
|
|
WOWRELVDMPTR(vpfn);
|
|
|
|
if ( lpfn == NULL )
|
|
{
|
|
thkDebugOut((DEB_WARN, "QI function ptr invalid %p:%p:%p\n",
|
|
vp,vpvtbl,vpfn));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GuidString, debug public
|
|
//
|
|
// Synopsis: Converts a guid to a string
|
|
//
|
|
// Arguments: [pguid] - GUID
|
|
//
|
|
// Returns: Pointer to string
|
|
//
|
|
// History: 08-Mar-94 DrewB Created
|
|
//
|
|
// Notes: Uses a static buffer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
|
|
#pragma pack(1)
|
|
struct SplitGuid
|
|
{
|
|
DWORD dw1;
|
|
WORD w1;
|
|
WORD w2;
|
|
BYTE b[8];
|
|
};
|
|
#pragma pack()
|
|
|
|
char *GuidString(GUID const *pguid)
|
|
{
|
|
static char ach[39];
|
|
SplitGuid *psg = (SplitGuid *)pguid;
|
|
|
|
wsprintfA(ach, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
|
psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
|
|
psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
|
|
return ach;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DBG == 1
|
|
char *apszThopNames[] =
|
|
{
|
|
"THOP_END",
|
|
"THOP_SHORTLONG",
|
|
"THOP_WORDDWORD",
|
|
"THOP_COPY",
|
|
"THOP_LPSTR",
|
|
"THOP_LPLPSTR",
|
|
"THOP_BUFFER",
|
|
"THOP_HUSER",
|
|
"THOP_HGDI",
|
|
"THOP_SIZE",
|
|
"THOP_RECT",
|
|
"THOP_MSG",
|
|
"THOP_HRESULT",
|
|
"THOP_STATSTG",
|
|
"THOP_DVTARGETDEVICE",
|
|
"THOP_STGMEDIUM",
|
|
"THOP_FORMATETC",
|
|
"THOP_HACCEL",
|
|
"THOP_OIFI",
|
|
"THOP_BINDOPTS",
|
|
"THOP_LOGPALETTE",
|
|
"THOP_SNB",
|
|
"THOP_CRGIID",
|
|
"THOP_OLESTREAM",
|
|
"THOP_HTASK",
|
|
"THOP_INTERFACEINFO",
|
|
"THOP_IFACE",
|
|
"THOP_IFACEOWNER",
|
|
"THOP_IFACENOADDREF",
|
|
"THOP_IFACECLEAN",
|
|
"THOP_IFACEGEN",
|
|
"THOP_IFACEGENOWNER",
|
|
"THOP_UNKOUTER",
|
|
"THOP_UNKINNER",
|
|
"THOP_ROUTINEINDEX",
|
|
"THOP_RETURNTYPE",
|
|
"THOP_NULL",
|
|
"THOP_ERROR",
|
|
"THOP_ENUM",
|
|
"THOP_CALLBACK",
|
|
"THOP_RPCOLEMESSAGE",
|
|
"THOP_ALIAS32",
|
|
"THOP_CLSCONTEXT",
|
|
"THOP_FILENAME",
|
|
"THOP_SIZEDSTRING"
|
|
};
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ThopName, debug public
|
|
//
|
|
// Synopsis: Returns the string name of a thop
|
|
//
|
|
// Arguments: [thop] - Thop
|
|
//
|
|
// Returns: Pointer to string
|
|
//
|
|
// History: 11-Mar-94 DrewB Created
|
|
//
|
|
// Notes: Uses a static buffer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
char *ThopName(THOP thop)
|
|
{
|
|
static char achString[80];
|
|
char *psz;
|
|
|
|
thkAssert((thop & THOP_OPMASK) < THOP_LASTOP);
|
|
thkAssert(THOP_LASTOP ==
|
|
(sizeof(apszThopNames)/sizeof(apszThopNames[0])));
|
|
|
|
strcpy(achString, apszThopNames[thop & THOP_OPMASK]);
|
|
|
|
psz = achString+strlen(achString);
|
|
if (thop & THOP_IN)
|
|
{
|
|
strcpy(psz, " | THOP_IN");
|
|
psz += strlen(psz);
|
|
}
|
|
if (thop & THOP_OUT)
|
|
{
|
|
strcpy(psz, " | THOP_OUT");
|
|
}
|
|
|
|
return achString;
|
|
}
|
|
#endif
|
|
|
|
#if DBG == 1
|
|
char *apszEnumThopNames[] =
|
|
{
|
|
"STRING",
|
|
"UNKNOWN",
|
|
"STATSTG",
|
|
"FORMATETC",
|
|
"STATDATA",
|
|
"MONIKER",
|
|
"OLEVERB"
|
|
};
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EnumThopName, debug public
|
|
//
|
|
// Synopsis: Returns the string name of an enum thop
|
|
//
|
|
// Arguments: [thopEnum] - Thop
|
|
//
|
|
// Returns: Pointer to string
|
|
//
|
|
// History: 11-Mar-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
char *EnumThopName(THOP thopEnum)
|
|
{
|
|
thkAssert(thopEnum <
|
|
(sizeof(apszEnumThopNames)/sizeof(apszEnumThopNames[0])));
|
|
return apszEnumThopNames[thopEnum];
|
|
}
|
|
#endif
|
|
|
|
#if DBG == 1
|
|
// Maintain current thunking invocation nesting level
|
|
int _iThunkNestingLevel = 1;
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NestingSpaces, debug public
|
|
//
|
|
// Synopsis: Spaces for each nesting level
|
|
//
|
|
// History: 22-Mar-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
|
|
#define NESTING_SPACES 32
|
|
#define SPACES_PER_LEVEL 2
|
|
|
|
static char achSpaces[NESTING_SPACES+1] = " ";
|
|
|
|
void NestingSpaces(char *psz)
|
|
{
|
|
int iSpaces, i;
|
|
|
|
iSpaces = _iThunkNestingLevel*SPACES_PER_LEVEL;
|
|
|
|
while (iSpaces > 0)
|
|
{
|
|
i = min(iSpaces, NESTING_SPACES);
|
|
memcpy(psz, achSpaces, i);
|
|
psz += i;
|
|
*psz = 0;
|
|
iSpaces -= i;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NestingLevelString, debug public
|
|
//
|
|
// Synopsis: Provides a string describing the nesting level
|
|
//
|
|
// History: 22-Mar-94 DrewB Created
|
|
//
|
|
// Notes: Uses a static buffer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
char *NestingLevelString(void)
|
|
{
|
|
static char ach[256];
|
|
char *psz;
|
|
|
|
if ((thkInfoLevel & DEB_NESTING) == 0)
|
|
{
|
|
return "";
|
|
}
|
|
|
|
wsprintfA(ach, "%2d:", _iThunkNestingLevel);
|
|
psz = ach+strlen(ach);
|
|
|
|
if (sizeof(ach)/SPACES_PER_LEVEL <= _iThunkNestingLevel)
|
|
{
|
|
strcpy(psz, "...");
|
|
}
|
|
else
|
|
{
|
|
NestingSpaces(psz);
|
|
}
|
|
return ach;
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IidOrInterfaceString, debug public
|
|
//
|
|
// Synopsis: Returns the interface name for known interfaces or
|
|
// the IID string itself
|
|
//
|
|
// Arguments: [piid] - IID
|
|
//
|
|
// Returns: char *
|
|
//
|
|
// History: 18-Jun-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
char *IidOrInterfaceString(IID const *piid)
|
|
{
|
|
return IidIdxString(IidToIidIdx(*piid));
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IidIdxString, debug public
|
|
//
|
|
// Synopsis: Returns the interface name for known interfaces or
|
|
// the IID string itself
|
|
//
|
|
// Arguments: [iidx] - IID or index
|
|
//
|
|
// Returns: char *
|
|
//
|
|
// History: 07-Jul-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
char *IidIdxString(IIDIDX iidx)
|
|
{
|
|
if (IIDIDX_IS_IID(iidx))
|
|
{
|
|
return GuidString(IIDIDX_IID(iidx));
|
|
}
|
|
else if (IIDIDX_INDEX(iidx) == THI_COUNT)
|
|
{
|
|
// Special case here because of IMalloc's unusual unthunked-
|
|
// but-indexed existence
|
|
return "IMalloc";
|
|
}
|
|
else
|
|
{
|
|
return inInterfaceNames[IIDIDX_INDEX(iidx)].pszInterface;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Handler routines, public
|
|
//
|
|
// Synopsis: Generic conversion routines for the generic thop handler
|
|
//
|
|
// Arguments: [pbFrom] - Data to convert from
|
|
// [pbTo] - Buffer to convert into
|
|
// [cbFrom] - Size of source data
|
|
// [cbTo] - Size of destination data
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FhCopyMemory, public
|
|
//
|
|
// Synopsis: Handler routine for memory copies
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == cbTo);
|
|
|
|
memcpy(pbTo, pbFrom, cbFrom);
|
|
|
|
#if DBG == 1
|
|
if (cbFrom == sizeof(DWORD))
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Arg DWORD: 0x%08lX\n",
|
|
*(DWORD UNALIGNED *)pbFrom));
|
|
}
|
|
else if (cbFrom == sizeof(LARGE_INTEGER))
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Arg 8 byte: 0x%08lX:%08lX\n",
|
|
*(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
|
|
*(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
|
|
}
|
|
else if (cbFrom == sizeof(GUID))
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Arg 16 byte: 0x%08lX:%08lX:%08lX:%08lX\n",
|
|
*(DWORD UNALIGNED *)(pbFrom+3*sizeof(DWORD)),
|
|
*(DWORD UNALIGNED *)(pbFrom+2*sizeof(DWORD)),
|
|
*(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
|
|
*(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_ARGS, "Arg %d byte copy\n", cbFrom));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FhShortToLong, FhLongToShort, public
|
|
//
|
|
// Synopsis: Signed int conversion
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(SHORT));
|
|
thkAssert(cbTo == sizeof(LONG));
|
|
|
|
*(LONG UNALIGNED *)pbTo = (LONG)*(SHORT UNALIGNED *)pbFrom;
|
|
|
|
thkDebugOut((DEB_ARGS, "ShToLo %d -> %d\n",
|
|
*(SHORT UNALIGNED *)pbFrom, *(LONG UNALIGNED *)pbTo));
|
|
}
|
|
|
|
void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(LONG));
|
|
thkAssert(cbTo == sizeof(SHORT));
|
|
|
|
// Not used in situations where clamping is meaningful
|
|
*(SHORT UNALIGNED *)pbTo = (SHORT)*(LONG UNALIGNED *)pbFrom;
|
|
|
|
thkDebugOut((DEB_ARGS, "LoToSh %d -> %d\n",
|
|
*(LONG UNALIGNED *)pbFrom, *(SHORT UNALIGNED *)pbTo));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FhWordToDword, FhDwordToWord, public
|
|
//
|
|
// Synopsis: Handler routine for memory copies
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(WORD));
|
|
thkAssert(cbTo == sizeof(DWORD));
|
|
|
|
*(DWORD UNALIGNED *)pbTo = (DWORD)*(WORD UNALIGNED *)pbFrom;
|
|
|
|
thkDebugOut((DEB_ARGS, "WoToDw 0x%04lX -> 0x%08lX\n",
|
|
*(WORD UNALIGNED *)pbFrom, *(DWORD UNALIGNED *)pbTo));
|
|
}
|
|
|
|
void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(DWORD));
|
|
thkAssert(cbTo == sizeof(WORD));
|
|
|
|
// Not used in situations where clamping is meaningful
|
|
*(WORD UNALIGNED *)pbTo = (WORD)*(DWORD UNALIGNED *)pbFrom;
|
|
|
|
thkDebugOut((DEB_ARGS, "DwToWo 0x%08lX -> 0x%04lX\n",
|
|
*(DWORD UNALIGNED *)pbFrom, *(WORD UNALIGNED *)pbTo));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Handle routines, public
|
|
//
|
|
// Synopsis: Handler routine for Windows handles
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HAND16));
|
|
thkAssert(cbTo == sizeof(HANDLE));
|
|
|
|
*(HBITMAP *)pbTo = HBITMAP_32(*(HBITMAP16 UNALIGNED *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HGdi: 0x%04lX -> 0x%p\n",
|
|
*(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
|
|
}
|
|
|
|
void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HANDLE));
|
|
thkAssert(cbTo == sizeof(HAND16));
|
|
|
|
*(HAND16 UNALIGNED *)pbTo = HBITMAP_16(*(HANDLE *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HGdi: 0x%p -> 0x%04lX\n",
|
|
*(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
|
|
}
|
|
|
|
void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HAND16));
|
|
thkAssert(cbTo == sizeof(HANDLE));
|
|
|
|
// Even though the constant is WOW_TYPE_FULLHWND, it
|
|
// works for any user handle
|
|
|
|
*(HANDLE *)pbTo = WOWHandle32(*(HAND16 UNALIGNED *)pbFrom,
|
|
WOW_TYPE_FULLHWND);
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HUser: 0x%04lX -> 0x%p\n",
|
|
*(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
|
|
}
|
|
|
|
void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HANDLE));
|
|
thkAssert(cbTo == sizeof(HAND16));
|
|
|
|
*(HAND16 UNALIGNED *)pbTo = HWND_16(*(HANDLE *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HUser: 0x%p -> 0x%04lX\n",
|
|
*(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
|
|
}
|
|
|
|
void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HAND16));
|
|
thkAssert(cbTo == sizeof(HANDLE));
|
|
|
|
*(HANDLE *)pbTo = HACCEL_32(*(HAND16 UNALIGNED *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HACCEL: 0x%04lX -> 0x%p\n",
|
|
*(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
|
|
}
|
|
|
|
void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HANDLE));
|
|
thkAssert(cbTo == sizeof(HAND16));
|
|
|
|
*(HAND16 UNALIGNED *)pbTo = HACCEL_16(*(HANDLE *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HACCEL: 0x%p -> 0x%04lX\n",
|
|
*(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
|
|
}
|
|
|
|
void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
HAND16 h16;
|
|
DWORD h32;
|
|
thkAssert(cbFrom == sizeof(HAND16));
|
|
thkAssert(cbTo == sizeof(HANDLE));
|
|
|
|
h16 = *(HAND16 UNALIGNED *)pbFrom;
|
|
if ( h16 == 0 )
|
|
{
|
|
h32 = 0;
|
|
}
|
|
else
|
|
{
|
|
h32 = HTASK_32(h16);
|
|
}
|
|
*(DWORD *)pbTo = h32;
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HTASK: 0x%04lX -> 0x%p\n", h16, h32));
|
|
}
|
|
|
|
void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
HAND16 h16;
|
|
HANDLE h32;
|
|
|
|
thkAssert(cbFrom == sizeof(HANDLE));
|
|
thkAssert(cbTo == sizeof(HAND16));
|
|
|
|
h32 = *(HANDLE *)pbFrom;
|
|
if ( h32 == NULL )
|
|
{
|
|
h16 = 0;
|
|
}
|
|
else
|
|
{
|
|
h16 = HTASK_16(h32);
|
|
}
|
|
*(HAND16 UNALIGNED *)pbTo = h16;
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HTASK: 0x%p -> 0x%04lX\n",h32, h16));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HRESULT routines, public
|
|
//
|
|
// Synopsis: Handler routine for HRESULTs
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HRESULT));
|
|
thkAssert(cbTo == sizeof(HRESULT));
|
|
|
|
*(HRESULT *)pbTo = TransformHRESULT_1632(*(HRESULT UNALIGNED *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HRESULT: 0x%08lX -> 0x%08lX\n",
|
|
*(HRESULT UNALIGNED *)pbFrom, *(HRESULT *)pbTo));
|
|
}
|
|
|
|
void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(HRESULT));
|
|
thkAssert(cbTo == sizeof(HRESULT));
|
|
|
|
*(HRESULT UNALIGNED *)pbTo = TransformHRESULT_3216(*(HRESULT *)pbFrom);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HRESULT: 0x%08lX -> 0x%08lX\n",
|
|
*(HRESULT *)pbFrom, *(HRESULT UNALIGNED *)pbTo));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NULL routines, public
|
|
//
|
|
// Synopsis: Handler routine for NULL
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
thkAssert(cbFrom == sizeof(void *));
|
|
thkAssert(cbTo == sizeof(void *));
|
|
|
|
thkDebugOut((DEB_WARN, "FhNull: %p NULL value not NULL\n", pbFrom));
|
|
*(void UNALIGNED **)pbTo = NULL;
|
|
|
|
thkDebugOut((DEB_ARGS, "Arg NULL\n"));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Rect routines, public
|
|
//
|
|
// Synopsis: Handler routines for RECT
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
RECT *pr32;
|
|
RECT16 UNALIGNED * pr16;
|
|
|
|
thkAssert(cbFrom == sizeof(RECT16));
|
|
thkAssert(cbTo == sizeof(RECT));
|
|
|
|
pr16 = (RECT16 UNALIGNED *)pbFrom;
|
|
pr32 = (RECT *)pbTo;
|
|
|
|
pr32->left = (LONG)pr16->left; // Sign extend
|
|
pr32->top = (LONG)pr16->top; // Sign extend
|
|
pr32->right = (LONG)pr16->right; // Sign extend
|
|
pr32->bottom = (LONG)pr16->bottom; // Sign extend
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 RECT: {%d, %d, %d, %d}\n",
|
|
pr32->left, pr32->top, pr32->right, pr32->bottom));
|
|
}
|
|
|
|
void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
RECT *pr32;
|
|
RECT16 UNALIGNED *pr16;
|
|
|
|
thkAssert(cbFrom == sizeof(RECT));
|
|
thkAssert(cbTo == sizeof(RECT16));
|
|
|
|
pr32 = (RECT *)pbFrom;
|
|
pr16 = (RECT16 UNALIGNED *)pbTo;
|
|
|
|
pr16->left = ClampLongToShort(pr32->left);
|
|
pr16->top = ClampLongToShort(pr32->top);
|
|
pr16->right = ClampLongToShort(pr32->right);
|
|
pr16->bottom = ClampLongToShort(pr32->bottom);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 RECT: {%d, %d, %d, %d}\n",
|
|
pr32->left, pr32->top, pr32->right, pr32->bottom));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Size routines, public
|
|
//
|
|
// Synopsis: Handler routines for SIZE
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
SIZE16 UNALIGNED *psize16;
|
|
SIZE *psize32;
|
|
|
|
thkAssert(cbFrom == sizeof(SIZE16));
|
|
thkAssert(cbTo == sizeof(SIZE));
|
|
|
|
psize16 = (SIZE16 UNALIGNED *)pbFrom;
|
|
psize32 = (SIZE *)pbTo;
|
|
|
|
psize32->cx = (LONG)psize16->cx;
|
|
psize32->cy = (LONG)psize16->cy;
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 SIZE: {%d, %d}\n",
|
|
psize32->cx, psize32->cy));
|
|
}
|
|
|
|
void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
SIZE16 UNALIGNED *psize16;
|
|
SIZE *psize32;
|
|
|
|
thkAssert(cbFrom == sizeof(SIZE));
|
|
thkAssert(cbTo == sizeof(SIZE16));
|
|
|
|
psize32 = (SIZE *)pbFrom;
|
|
psize16 = (SIZE16 UNALIGNED *)pbTo;
|
|
|
|
psize16->cx = ClampLongToShort(psize32->cx);
|
|
psize16->cy = ClampLongToShort(psize32->cy);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 SIZE: {%d, %d}\n",
|
|
psize32->cx, psize32->cy));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Message routines, public
|
|
//
|
|
// Synopsis: Handler routines for MSG
|
|
//
|
|
// History: 05-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
MSG16 UNALIGNED *pmsg16;
|
|
MSG *pmsg32;
|
|
|
|
thkAssert(cbFrom == sizeof(MSG16));
|
|
thkAssert(cbTo == sizeof(MSG));
|
|
|
|
pmsg16 = (MSG16 UNALIGNED *)pbFrom;
|
|
pmsg32 = (MSG *)pbTo;
|
|
|
|
pmsg32->hwnd = HWND_32(pmsg16->hwnd);
|
|
pmsg32->message = (UINT)pmsg16->message;
|
|
pmsg32->wParam = (WPARAM)pmsg16->wParam; // Should we sign extend?
|
|
pmsg32->lParam = (LPARAM)pmsg16->lParam;
|
|
pmsg32->time = pmsg16->time;
|
|
pmsg32->pt.x = (LONG)(SHORT)LOWORD(pmsg16->pt); // Sign extend
|
|
pmsg32->pt.y = (LONG)(SHORT)HIWORD(pmsg16->pt); // Sign extend
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
|
|
"0x%08lX, {%d, %d}}\n",
|
|
pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
|
|
pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
|
|
pmsg32->pt.y));
|
|
}
|
|
|
|
void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
|
|
{
|
|
MSG16 UNALIGNED *pmsg16;
|
|
MSG *pmsg32;
|
|
|
|
thkAssert(cbFrom == sizeof(MSG));
|
|
thkAssert(cbTo == sizeof(MSG16));
|
|
|
|
pmsg32 = (MSG *)pbFrom;
|
|
pmsg16 = (MSG16 UNALIGNED *)pbTo;
|
|
|
|
pmsg16->hwnd = HWND_16(pmsg32->hwnd);
|
|
pmsg16->message = (WORD)pmsg32->message;
|
|
pmsg16->wParam = (WORD)pmsg32->wParam; // Sign truncate
|
|
pmsg16->lParam = (LONG)pmsg32->lParam;
|
|
pmsg16->time = pmsg32->time;
|
|
pmsg16->pt = MAKELONG(ClampLongToShort(pmsg32->pt.x),
|
|
ClampLongToShort(pmsg32->pt.y));
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
|
|
"0x%08lX, {%d, %d}}\n",
|
|
pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
|
|
pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
|
|
pmsg32->pt.y));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ALLOCROUTINE, public
|
|
//
|
|
// Synopsis: A routine which allocates memory
|
|
//
|
|
// Arguments: [cb] - Amount to allocate
|
|
//
|
|
// Returns: Pointer to memory
|
|
//
|
|
// History: 19-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FREEROUTINE, public
|
|
//
|
|
// Synopsis: A routine which frees memory
|
|
//
|
|
// Arguments: [pv] - Memory to free
|
|
// [cb] - Size of memory to free
|
|
//
|
|
// History: 19-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void *ArTask16(UINT cb)
|
|
{
|
|
return (void *)TaskMalloc16(cb);
|
|
}
|
|
|
|
void FrTask16(void *pv, UINT cb)
|
|
{
|
|
TaskFree16((VPVOID)pv);
|
|
}
|
|
|
|
void *ArTask32(UINT cb)
|
|
{
|
|
return TaskMalloc32(cb);
|
|
}
|
|
|
|
void FrTask32(void *pv, UINT cb)
|
|
{
|
|
TaskFree32(pv);
|
|
}
|
|
|
|
void *ArStack16(UINT cb)
|
|
{
|
|
return (void *)STACKALLOC16(cb);
|
|
}
|
|
|
|
void FrStack16(void *pv, UINT cb)
|
|
{
|
|
STACKFREE16((VPVOID)pv, cb);
|
|
}
|
|
|
|
void *ArStack32(UINT cb)
|
|
{
|
|
// Can't use STACKALLOC32 on NT since it may be _alloca which wouldn't
|
|
// live beyond this routine
|
|
#ifdef _CHICAGO_
|
|
return STACKALLOC32(cb);
|
|
#else
|
|
return (void *)LocalAlloc(LMEM_FIXED, cb);
|
|
#endif
|
|
}
|
|
|
|
void FrStack32(void *pv, UINT cb)
|
|
{
|
|
#ifdef _CHICAGO_
|
|
STACKFREE32(pv, cb);
|
|
#else
|
|
LocalFree(pv);
|
|
#endif
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertDvtd1632, private
|
|
//
|
|
// Synopsis: Converts a DVTARGETDEVICE from 16 to 32-bits
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [vpdvtd16] - Source
|
|
// [pfnAlloc] - ALLOCROUTINE
|
|
// [pfnFree] - FREEROUTINE
|
|
// [ppdvtd32] - Destination
|
|
// [pcbSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppdvtd32]
|
|
// [pcbSize]
|
|
//
|
|
// History: 18-Apr-94 DrewB Created
|
|
//
|
|
// Notes: [pfnAlloc/Free] must deal with 32-bit memory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertDvtd1632(THUNKINFO *pti,
|
|
VPVOID vpdvtd16,
|
|
ALLOCROUTINE pfnAlloc,
|
|
FREEROUTINE pfnFree,
|
|
DVTARGETDEVICE **ppdvtd32,
|
|
UINT *pcbSize)
|
|
{
|
|
DVTARGETDEVICE UNALIGNED *pdvtd16;
|
|
DVTARGETDEVICE *pdvtd32;
|
|
DVTDINFO dvtdi;
|
|
|
|
pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
|
|
sizeof(DVTARGETDEVICE));
|
|
if (pdvtd16 == NULL)
|
|
{
|
|
return pti->scResult;
|
|
}
|
|
|
|
pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
|
|
pdvtd16->tdSize);
|
|
|
|
WOWRELVDMPTR(vpdvtd16);
|
|
|
|
if (pdvtd16 == NULL)
|
|
{
|
|
return pti->scResult;
|
|
}
|
|
|
|
pti->scResult = UtGetDvtd16Info( pdvtd16, &dvtdi );
|
|
|
|
if ( FAILED(pti->scResult) )
|
|
{
|
|
WOWRELVDMPTR(vpdvtd16);
|
|
return pti->scResult;
|
|
}
|
|
|
|
pdvtd32 = (DVTARGETDEVICE *)pfnAlloc(dvtdi.cbConvertSize);
|
|
if (pdvtd32 == NULL)
|
|
{
|
|
WOWRELVDMPTR(vpdvtd16);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
pti->scResult = UtConvertDvtd16toDvtd32( pdvtd16, &dvtdi, pdvtd32 );
|
|
|
|
WOWRELVDMPTR(vpdvtd16);
|
|
|
|
if ( FAILED(pti->scResult) )
|
|
{
|
|
pfnFree(pdvtd32, dvtdi.cbConvertSize);
|
|
return pti->scResult;
|
|
}
|
|
|
|
*ppdvtd32 = pdvtd32;
|
|
*pcbSize = dvtdi.cbConvertSize;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertDvtd3216, private
|
|
//
|
|
// Synopsis: Converts a DVTARGETDEVICE from 32 to 16-bits
|
|
//
|
|
// Arguments: [pti] - Thunking state information
|
|
// [pdvtd32] - Source
|
|
// [pfnAlloc] - Allocator
|
|
// [pfnFree] - Freer
|
|
// [ppvdvtd16] - Destination
|
|
// [pcbSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvdvtd16]
|
|
// [pcbSize]
|
|
//
|
|
// History: 18-Apr-94 DrewB Created
|
|
//
|
|
// Notes: [pfnAlloc/Free] must deal with 16-bit memory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertDvtd3216(THUNKINFO *pti,
|
|
DVTARGETDEVICE *pdvtd32,
|
|
ALLOCROUTINE pfnAlloc,
|
|
FREEROUTINE pfnFree,
|
|
VPVOID *ppvdvtd16,
|
|
UINT *pcbSize)
|
|
{
|
|
DVTARGETDEVICE UNALIGNED *pdvtd16;
|
|
VPVOID vpdvtd16;
|
|
DVTDINFO dvtdi;
|
|
|
|
if (IsBadReadPtr(pdvtd32, sizeof(DVTARGETDEVICE)) ||
|
|
IsBadReadPtr(pdvtd32, pdvtd32->tdSize))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pti->scResult = UtGetDvtd32Info( pdvtd32, &dvtdi );
|
|
|
|
if ( FAILED(pti->scResult) )
|
|
{
|
|
return pti->scResult;
|
|
}
|
|
|
|
vpdvtd16 = (VPVOID)pfnAlloc(dvtdi.cbConvertSize);
|
|
if (vpdvtd16 == 0)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
pdvtd16 = (DVTARGETDEVICE UNALIGNED *)WOWFIXVDMPTR(vpdvtd16,
|
|
dvtdi.cbConvertSize);
|
|
|
|
pti->scResult = UtConvertDvtd32toDvtd16( pdvtd32, &dvtdi, pdvtd16 );
|
|
|
|
WOWRELVDMPTR(vpdvtd16);
|
|
|
|
if ( FAILED(pti->scResult) )
|
|
{
|
|
pfnFree((void *)vpdvtd16, dvtdi.cbConvertSize);
|
|
return pti->scResult;
|
|
}
|
|
|
|
*ppvdvtd16 = vpdvtd16;
|
|
*pcbSize = dvtdi.cbConvertSize;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#if !defined(_CHICAGO_)
|
|
|
|
SCODE ConvertHDrop1632(HMEM16 hg16, HGLOBAL* phg32)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
*phg32 = CopyDropFilesFrom16(hg16);
|
|
if (!*phg32)
|
|
sc = E_INVALIDARG;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
SCODE ConvertHDrop3216(HGLOBAL hg32, HMEM16* phg16)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
*phg16 = CopyDropFilesFrom32(hg32);
|
|
if (!*phg16)
|
|
sc = E_INVALIDARG;
|
|
|
|
return sc;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertHGlobal1632, public
|
|
//
|
|
// Synopsis: Creates a 32-bit HGLOBAL for a 16-bit HGLOBAL
|
|
//
|
|
// Arguments: [pti] - Thunk info, can be NULL for no validation
|
|
// [hg16] - 16-bit HGLOBAL
|
|
// [thopInOut] - Validation type
|
|
// [phg32] - 32-bit HGLOBAL in/out
|
|
// [pdwSize] - Size in/out
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg32]
|
|
// [pdwSize]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
// Notes: If [phg32] is non-NULL on entry, [pdwSize] must be set
|
|
// appropriately also
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertHGlobal1632(THUNKINFO *pti,
|
|
HMEM16 hg16,
|
|
THOP thopInOut,
|
|
HGLOBAL *phg32,
|
|
DWORD *pdwSize)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vpdata16;
|
|
LPVOID lpdata16;
|
|
LPVOID lpdata32;
|
|
HGLOBAL hg32;
|
|
DWORD dwSize;
|
|
BOOL fOwn;
|
|
|
|
sc = S_OK;
|
|
|
|
vpdata16 = WOWGlobalLockSize16( hg16, &dwSize );
|
|
if ( vpdata16 == 0 )
|
|
{
|
|
sc = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
if (*phg32 != 0 && *pdwSize == dwSize)
|
|
{
|
|
hg32 = *phg32;
|
|
fOwn = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hg32 = GlobalAlloc( GMEM_MOVEABLE, dwSize );
|
|
fOwn = TRUE;
|
|
}
|
|
|
|
if ( hg32 == 0 )
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
lpdata32 = GlobalLock( hg32 );
|
|
|
|
lpdata16 = (LPVOID)ValidatePtr16(pti, vpdata16, dwSize, thopInOut);
|
|
if ( lpdata16 != NULL )
|
|
{
|
|
memcpy( lpdata32, lpdata16, dwSize );
|
|
WOWRELVDMPTR(vpdata16);
|
|
}
|
|
else
|
|
{
|
|
sc = pti->scResult;
|
|
}
|
|
|
|
GlobalUnlock(hg32);
|
|
|
|
if (FAILED(sc) && fOwn)
|
|
{
|
|
GlobalFree(hg32);
|
|
}
|
|
}
|
|
|
|
WOWGlobalUnlock16( hg16 );
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
if (*phg32 != 0 && hg32 != *phg32)
|
|
{
|
|
GlobalFree(*phg32);
|
|
}
|
|
|
|
*phg32 = hg32;
|
|
*pdwSize = dwSize;
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 HGLOBAL: 0x%04X -> 0x%p, %u\n",
|
|
hg16, hg32, dwSize));
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertHGlobal3216, public
|
|
//
|
|
// Synopsis: Creates a 16-bit HGLOBAL for a 32-bit HGLOBAL
|
|
//
|
|
// Arguments: [pti] - Thunk info, can be NULL for no validation
|
|
// [hg32] - 32-bit HGLOBAL
|
|
// [thopInOut] - Validation type
|
|
// [phg16] - 16-bit HGLOBAL in/out
|
|
// [pdwSize] - Size in/out
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg16]
|
|
// [pdwSize]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
// Notes: If [phg16] is non-NULL on entry, [pdwSize] must be set
|
|
// appropriately also
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertHGlobal3216(THUNKINFO *pti,
|
|
HGLOBAL hg32,
|
|
THOP thopInOut,
|
|
HMEM16 *phg16,
|
|
DWORD *pdwSize)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vpdata16;
|
|
LPVOID lpdata16;
|
|
LPVOID lpdata32;
|
|
HMEM16 hg16;
|
|
DWORD dwSize;
|
|
BOOL fOwn;
|
|
|
|
sc = S_OK;
|
|
|
|
dwSize = (DWORD) GlobalSize(hg32);
|
|
if (dwSize == 0)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
lpdata32 = GlobalLock(hg32);
|
|
|
|
if (*phg16 != 0 && *pdwSize == dwSize)
|
|
{
|
|
hg16 = *phg16;
|
|
vpdata16 = WOWGlobalLock16(hg16);
|
|
fOwn = FALSE;
|
|
}
|
|
else
|
|
{
|
|
vpdata16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
|
|
dwSize, &hg16);
|
|
fOwn = TRUE;
|
|
}
|
|
|
|
if (vpdata16 == 0)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
lpdata16 = (LPVOID)WOWFIXVDMPTR( vpdata16, dwSize );
|
|
if ( lpdata16 == NULL )
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
memcpy( lpdata16, lpdata32, dwSize );
|
|
|
|
WOWRELVDMPTR(vpdata16);
|
|
}
|
|
|
|
WOWGlobalUnlock16( hg16 );
|
|
|
|
if (FAILED(sc) && fOwn)
|
|
{
|
|
WOWGlobalFree16(hg16);
|
|
}
|
|
}
|
|
|
|
GlobalUnlock(hg32);
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
if (*phg16 != 0 && hg16 != *phg16)
|
|
{
|
|
WOWGlobalFree16(*phg16);
|
|
}
|
|
|
|
*phg16 = hg16;
|
|
*pdwSize = dwSize;
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 HGLOBAL: 0x%p -> 0x%04X, %u\n",
|
|
hg32, hg16, dwSize));
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertMfPict1632, public
|
|
//
|
|
// Synopsis: Converts a 16-bit METAFILEPICT to 32-bit
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [hg16] - 16-bit HGLOBAL containing METAFILEPICT
|
|
// [phg32] - 32-bit HGLOBAL return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg32]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertMfPict1632(THUNKINFO *pti,
|
|
HMEM16 hg16,
|
|
HGLOBAL *phg32)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vpmfp16;
|
|
METAFILEPICT16 UNALIGNED *pmfp16;
|
|
METAFILEPICT *pmfp32;
|
|
HGLOBAL hg32;
|
|
DWORD dwSize;
|
|
#if DBG == 1
|
|
BOOL fSaveToFile = FALSE;
|
|
#endif
|
|
|
|
thkDebugOut((DEB_ITRACE, "In ConvertMfPict1632(%p, 0x%04X, %p)\n",
|
|
pti, hg16, phg32));
|
|
|
|
*phg32 = 0;
|
|
sc = S_OK;
|
|
|
|
vpmfp16 = WOWGlobalLockSize16( hg16, &dwSize );
|
|
if ( vpmfp16 == 0 || dwSize < sizeof(METAFILEPICT16))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hg32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
|
|
if ( hg32 == 0 )
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pmfp32 = (METAFILEPICT *)GlobalLock( hg32 );
|
|
|
|
pmfp16 = (METAFILEPICT16 UNALIGNED *)GetReadPtr16(pti, vpmfp16,
|
|
dwSize);
|
|
if ( pmfp16 != NULL )
|
|
{
|
|
pmfp32->mm = (LONG)pmfp16->mm;
|
|
pmfp32->xExt = (LONG)pmfp16->xExt;
|
|
pmfp32->yExt = (LONG)pmfp16->yExt;
|
|
|
|
pmfp32->hMF = HMETAFILE_32(pmfp16->hMF);
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 METAFILEPICT: "
|
|
"{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
|
|
pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF,
|
|
pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF));
|
|
|
|
WOWRELVDMPTR(vpmfp16);
|
|
|
|
#if DBG == 1
|
|
if (fSaveToFile)
|
|
{
|
|
HMETAFILE hmf;
|
|
|
|
hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
|
|
if (hmf != NULL)
|
|
{
|
|
DeleteMetaFile(hmf);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sc = pti->scResult;
|
|
}
|
|
|
|
GlobalUnlock(hg32);
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
GlobalFree(hg32);
|
|
}
|
|
}
|
|
|
|
WOWGlobalUnlock16( hg16 );
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
*phg32 = hg32;
|
|
}
|
|
|
|
thkDebugOut((DEB_ITRACE, "Out ConvertMfPict1632 => 0x%08lX, 0x%p\n",
|
|
sc, *phg32));
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertMfPict3216, public
|
|
//
|
|
// Synopsis: Converts a 32-bit METAFILEPICT to 16-bit
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [hg32] - 32-bit HGLOBAL containing METAFILEPICT
|
|
// [phg16] - 16-bit HGLOBAL return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg16]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertMfPict3216(THUNKINFO *pti,
|
|
HGLOBAL hg32,
|
|
HMEM16 *phg16)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vpmfp16;
|
|
METAFILEPICT16 UNALIGNED *pmfp16;
|
|
METAFILEPICT *pmfp32;
|
|
DWORD dwSize;
|
|
HMEM16 hg16;
|
|
#if DBG == 1
|
|
BOOL fSaveToFile = FALSE;
|
|
#endif
|
|
|
|
thkDebugOut((DEB_ITRACE, "In ConvertMfPict3216(%p, 0x%p, %p)\n",
|
|
pti, hg32, phg16));
|
|
|
|
*phg16 = 0;
|
|
sc = S_OK;
|
|
|
|
dwSize = (DWORD) GlobalSize(hg32);
|
|
pmfp32 = (METAFILEPICT *)GlobalLock(hg32);
|
|
if (dwSize == 0 || dwSize < sizeof(METAFILEPICT) || pmfp32 == NULL)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
vpmfp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
|
|
sizeof(METAFILEPICT16), &hg16);
|
|
if (vpmfp16 == 0)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pmfp16 = FIXVDMPTR(vpmfp16, METAFILEPICT16);
|
|
if ( pmfp16 != NULL )
|
|
{
|
|
pmfp16->mm = (SHORT)pmfp32->mm;
|
|
pmfp16->xExt = ClampLongToShort(pmfp32->xExt);
|
|
pmfp16->yExt = ClampLongToShort(pmfp32->yExt);
|
|
pmfp16->hMF = HMETAFILE_16(pmfp32->hMF);
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 METAFILEPICT: "
|
|
"{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
|
|
pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF,
|
|
pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF));
|
|
|
|
RELVDMPTR(vpmfp16);
|
|
|
|
#if DBG == 1
|
|
if (fSaveToFile)
|
|
{
|
|
HMETAFILE hmf;
|
|
|
|
hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
|
|
if (hmf != NULL)
|
|
{
|
|
DeleteMetaFile(hmf);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
}
|
|
|
|
WOWGlobalUnlock16(hg16);
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
WOWGlobalFree16(hg16);
|
|
}
|
|
}
|
|
|
|
GlobalUnlock(hg32);
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
*phg16 = hg16;
|
|
}
|
|
|
|
thkDebugOut((DEB_ITRACE, "Out ConvertMfPict3216 => 0x%08lX, 0x%04X\n",
|
|
sc, *phg16));
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertObjDesc1632, public
|
|
//
|
|
// Synopsis: Converts an OBJECTDESCRIPTOR structure
|
|
//
|
|
// Arguments: [pti] - THUNKINFO
|
|
// [hg16] - HGLOBAL containing structure
|
|
// [phg32] - Output HGLOBAL
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg32]
|
|
//
|
|
// History: 04-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertObjDesc1632(THUNKINFO *pti,
|
|
HMEM16 hg16,
|
|
HGLOBAL *phg32)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vp16;
|
|
HGLOBAL hg32;
|
|
DWORD dwSize;
|
|
OBJECTDESCRIPTOR UNALIGNED *pod16;
|
|
OBJECTDESCRIPTOR *pod32;
|
|
char *pszFutn, *pszSoc;
|
|
UINT cchFutn, cchSoc;
|
|
UINT cbOffset;
|
|
|
|
sc = S_OK;
|
|
|
|
*phg32 = NULL;
|
|
|
|
vp16 = WOWGlobalLock16(hg16);
|
|
if ( vp16 == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pszFutn = NULL;
|
|
pszSoc = NULL;
|
|
|
|
pod16 = (OBJECTDESCRIPTOR UNALIGNED *)
|
|
GetReadPtr16(pti, vp16, sizeof(OBJECTDESCRIPTOR));
|
|
if (pod16 == NULL)
|
|
{
|
|
sc = pti->scResult;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
dwSize = sizeof(OBJECTDESCRIPTOR);
|
|
|
|
if (pod16->dwFullUserTypeName > 0)
|
|
{
|
|
pszFutn = (char *)GetStringPtr16(pti, vp16+pod16->dwFullUserTypeName,
|
|
CCHMAXSTRING, &cchFutn);
|
|
if (pszFutn == NULL)
|
|
{
|
|
sc = pti->scResult;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
dwSize += cchFutn*sizeof(WCHAR);
|
|
}
|
|
|
|
if (pod16->dwSrcOfCopy > 0)
|
|
{
|
|
pszSoc = (char *)GetStringPtr16(pti, vp16+pod16->dwSrcOfCopy,
|
|
CCHMAXSTRING, &cchSoc);
|
|
if (pszSoc == NULL)
|
|
{
|
|
sc = pti->scResult;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
dwSize += cchSoc*sizeof(WCHAR);
|
|
}
|
|
|
|
hg32 = GlobalAlloc(GMEM_MOVEABLE, dwSize);
|
|
if ( hg32 == 0 )
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
|
|
memcpy(pod32, pod16, sizeof(OBJECTDESCRIPTOR));
|
|
pod32->cbSize = dwSize;
|
|
|
|
cbOffset = sizeof(OBJECTDESCRIPTOR);
|
|
|
|
if (pod16->dwFullUserTypeName > 0)
|
|
{
|
|
if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0, pszFutn, cchFutn,
|
|
(WCHAR *)((BYTE *)pod32+cbOffset),
|
|
cchFutn) == 0)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
goto EH_Free;
|
|
}
|
|
|
|
pod32->dwFullUserTypeName = cbOffset;
|
|
cbOffset += cchFutn*sizeof(WCHAR);
|
|
}
|
|
|
|
if (pod16->dwSrcOfCopy > 0)
|
|
{
|
|
if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0, pszSoc, cchSoc,
|
|
(WCHAR *)((BYTE *)pod32+cbOffset),
|
|
cchSoc) == 0)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
goto EH_Free;
|
|
}
|
|
|
|
pod32->dwSrcOfCopy = cbOffset;
|
|
cbOffset += cchFutn*sizeof(WCHAR);
|
|
}
|
|
|
|
#if DBG == 1
|
|
WCHAR *pwcsFutn, *pwcsSoc;
|
|
if (pod32->dwFullUserTypeName > 0)
|
|
{
|
|
pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
|
|
}
|
|
else
|
|
{
|
|
pwcsFutn = NULL;
|
|
}
|
|
if (pod32->dwSrcOfCopy > 0)
|
|
{
|
|
pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
|
|
}
|
|
else
|
|
{
|
|
pwcsSoc = NULL;
|
|
}
|
|
thkDebugOut((DEB_ARGS, "1632 OBJECTDESCRIPTOR: "
|
|
"{%d, ..., \"%ws\" (%s), \"%ws\" (%s)} %p -> %p\n",
|
|
pod32->cbSize, pwcsFutn, pszFutn, pwcsSoc, pszSoc,
|
|
vp16, pod32));
|
|
#endif
|
|
|
|
GlobalUnlock(hg32);
|
|
|
|
*phg32 = hg32;
|
|
|
|
EH_Unlock:
|
|
if (pszFutn != NULL)
|
|
{
|
|
WOWRELVDMPTR(vp16+pod16->dwFullUserTypeName);
|
|
}
|
|
if (pszSoc != NULL)
|
|
{
|
|
WOWRELVDMPTR(vp16+pod16->dwSrcOfCopy);
|
|
}
|
|
if (pod16 != NULL)
|
|
{
|
|
WOWRELVDMPTR(vp16);
|
|
}
|
|
|
|
WOWGlobalUnlock16(hg16);
|
|
|
|
return sc;
|
|
|
|
EH_Free:
|
|
GlobalUnlock(hg32);
|
|
GlobalFree(hg32);
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertObjDesc3216, public
|
|
//
|
|
// Synopsis: Converts an OBJECTDESCRIPTOR structure
|
|
//
|
|
// Arguments: [pti] - THUNKINFO
|
|
// [hg32] - HGLOBAL containing structure
|
|
// [phg16] - Output HGLOBAL
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [phg16]
|
|
//
|
|
// History: 04-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertObjDesc3216(THUNKINFO *pti,
|
|
HGLOBAL hg32,
|
|
HMEM16 *phg16)
|
|
{
|
|
SCODE sc;
|
|
VPVOID vp16;
|
|
HMEM16 hg16;
|
|
DWORD dwSize;
|
|
OBJECTDESCRIPTOR UNALIGNED *pod16;
|
|
OBJECTDESCRIPTOR *pod32;
|
|
WCHAR *pwcsFutn, *pwcsSoc;
|
|
UINT cchFutn, cchSoc;
|
|
UINT cbOffset;
|
|
|
|
sc = S_OK;
|
|
|
|
pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
|
|
if ( pod32 == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (IsBadReadPtr(pod32, sizeof(OBJECTDESCRIPTOR)))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
dwSize = sizeof(OBJECTDESCRIPTOR);
|
|
|
|
pwcsFutn = NULL;
|
|
if (pod32->dwFullUserTypeName > 0)
|
|
{
|
|
pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
|
|
if (IsBadStringPtrW(pwcsFutn, CCHMAXSTRING))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
cchFutn = lstrlenW(pwcsFutn)+1;
|
|
dwSize += cchFutn*2;
|
|
}
|
|
|
|
pwcsSoc = NULL;
|
|
if (pod32->dwSrcOfCopy > 0)
|
|
{
|
|
pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
|
|
if (IsBadStringPtrW(pwcsSoc, CCHMAXSTRING))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
cchSoc = lstrlenW(pwcsSoc)+1;
|
|
dwSize += cchSoc*2;
|
|
}
|
|
|
|
vp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE, dwSize, &hg16);
|
|
if ( vp16 == 0 )
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
pod16 = FIXVDMPTR(vp16, OBJECTDESCRIPTOR);
|
|
memcpy(pod16, pod32, sizeof(OBJECTDESCRIPTOR));
|
|
pod16->cbSize = dwSize;
|
|
|
|
cbOffset = sizeof(OBJECTDESCRIPTOR);
|
|
|
|
if (pod32->dwFullUserTypeName > 0)
|
|
{
|
|
if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0, pwcsFutn, cchFutn,
|
|
(char *)pod16+cbOffset, 2 * cchFutn,
|
|
NULL, NULL) == 0)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
goto EH_Free;
|
|
}
|
|
|
|
pod16->dwFullUserTypeName = cbOffset;
|
|
cbOffset += cchFutn*2;
|
|
}
|
|
|
|
if (pod32->dwSrcOfCopy > 0)
|
|
{
|
|
if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
|
|
0, pwcsSoc, cchSoc,
|
|
(char *)pod16+cbOffset, 2 * cchSoc,
|
|
NULL, NULL) == 0)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
goto EH_Free;
|
|
}
|
|
|
|
pod16->dwSrcOfCopy = cbOffset;
|
|
cbOffset += cchFutn*2;
|
|
}
|
|
|
|
#if DBG == 1
|
|
char *pszFutn, *pszSoc;
|
|
if (pod16->dwFullUserTypeName > 0)
|
|
{
|
|
pszFutn = (char *)((BYTE *)pod16+pod16->dwFullUserTypeName);
|
|
}
|
|
else
|
|
{
|
|
pszFutn = NULL;
|
|
}
|
|
if (pod16->dwSrcOfCopy > 0)
|
|
{
|
|
pszSoc = (char *)((BYTE *)pod16+pod16->dwSrcOfCopy);
|
|
}
|
|
else
|
|
{
|
|
pszSoc = NULL;
|
|
}
|
|
thkDebugOut((DEB_ARGS, "3216 OBJECTDESCRIPTOR: "
|
|
"{%d, ..., \"%s\" (%ws), \"%s\" (%ws)} %p -> %p\n",
|
|
pod16->cbSize, pszFutn, pwcsFutn, pszSoc, pwcsSoc,
|
|
pod32, vp16));
|
|
#endif
|
|
|
|
RELVDMPTR(vp16);
|
|
|
|
WOWGlobalUnlock16(hg16);
|
|
|
|
*phg16 = hg16;
|
|
|
|
EH_Unlock:
|
|
GlobalUnlock(hg32);
|
|
|
|
return sc;
|
|
|
|
EH_Free:
|
|
WOWGlobalUnlockFree16(vp16);
|
|
goto EH_Unlock;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CSm32ReleaseHandler (srh)
|
|
//
|
|
// Purpose: Provides punkForRelease for 16->32 STGMEDIUM conversion
|
|
//
|
|
// Interface: IUnknown
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CSm32ReleaseHandler : public IUnknown
|
|
{
|
|
public:
|
|
CSm32ReleaseHandler(void)
|
|
{
|
|
_vpvForRelease = NULL;
|
|
}
|
|
~CSm32ReleaseHandler(void)
|
|
{
|
|
}
|
|
|
|
void Init(CThkMgr *pThkMgr,
|
|
STGMEDIUM UNALIGNED *psm16,
|
|
STGMEDIUM *psm32,
|
|
VPVOID vpvForRelease,
|
|
CLIPFORMAT cfFormat)
|
|
{
|
|
// Unfortunately, the MIPS compiler is not smart enough
|
|
// to do the right thing if we just declare psm16 as UNALIGNED -- it
|
|
// doesn't recognize that each member of the structure is also
|
|
// unaligned when it does the structure copy. So...to make
|
|
// sure we don't generate an alignment fault, we just copy each
|
|
// member of the structure directly.
|
|
|
|
_sm16.tymed = psm16->tymed;
|
|
switch(_sm16.tymed) {
|
|
case TYMED_HGLOBAL:
|
|
_sm16.hGlobal = psm16->hGlobal;
|
|
case TYMED_FILE:
|
|
_sm16.lpszFileName = psm16->lpszFileName;
|
|
case TYMED_ISTREAM:
|
|
_sm16.pstm = psm16->pstm;
|
|
case TYMED_ISTORAGE:
|
|
_sm16.pstg = psm16->pstg;
|
|
}
|
|
_sm16.pUnkForRelease = psm16->pUnkForRelease;
|
|
_sm32 = *psm32;
|
|
_vpvForRelease = vpvForRelease;
|
|
_cReferences = 1;
|
|
_cfFormat = cfFormat;
|
|
_pThkMgr = pThkMgr;
|
|
}
|
|
|
|
STDMETHOD(QueryInterface)(REFIID riid, void **ppv)
|
|
{
|
|
if ( IsEqualIID(riid,IID_IUnknown) )
|
|
{
|
|
*ppv = this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_WARN, "Not a QI for IUnknown\n"));
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
STDMETHOD_(ULONG, AddRef)(void)
|
|
{
|
|
return InterlockedIncrement(&_cReferences);
|
|
}
|
|
STDMETHOD_(ULONG, Release)(void);
|
|
|
|
void CallFailed() {
|
|
_vpvForRelease = NULL;
|
|
}
|
|
|
|
private:
|
|
STGMEDIUM _sm16;
|
|
STGMEDIUM _sm32;
|
|
VPVOID _vpvForRelease;
|
|
CLIPFORMAT _cfFormat;
|
|
CThkMgr *_pThkMgr;
|
|
LONG _cReferences;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSm32ReleaseHandler::Release, public
|
|
//
|
|
// Synopsis: Frees resources for the 32-bit copy and then
|
|
// passes the ReleaseStgMedium on to 16-bits
|
|
//
|
|
// Returns: Ref count
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSm32ReleaseHandler::Release(void)
|
|
{
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
VPVOID vpvunk;
|
|
STGMEDIUM *psm32;
|
|
LONG lRet;
|
|
SCODE sc;
|
|
BOOL fCopy;
|
|
DWORD dwSize;
|
|
|
|
lRet = InterlockedDecrement(&_cReferences);
|
|
if (lRet != 0) {
|
|
return lRet;
|
|
}
|
|
|
|
if(_vpvForRelease) {
|
|
// This is the last release on ReleaseHandler
|
|
// Cleanup 32-bit STGMEDIUM after copying it to
|
|
// 16-bit STGMEDIUM.
|
|
fCopy = TRUE;
|
|
}
|
|
else {
|
|
// The current call failed.
|
|
// As the fields in the 16-bit STGMEDIUM are not longer valid,
|
|
// cleanup the 32-bit STGMEDIUM without copying it to
|
|
// 16-bit STGMEDIUM
|
|
fCopy = FALSE;
|
|
}
|
|
|
|
psm16 = &_sm16;
|
|
psm32 = &_sm32;
|
|
|
|
switch(psm32->tymed)
|
|
{
|
|
case TYMED_HGLOBAL:
|
|
// Assumption that OBJECTDESCRIPTOR does not need copyback
|
|
if (fCopy && !OBJDESC_CF(_cfFormat))
|
|
{
|
|
// Do we ever need to do this?
|
|
// Is it valid to rely on the contents of the HGLOBAL
|
|
// at release time?
|
|
|
|
// Is this the right time to copy back?
|
|
|
|
Assert(NULL != psm32->hGlobal);
|
|
|
|
WOWGlobalLockSize16((HMEM16)psm16->hGlobal, &dwSize);
|
|
WOWGlobalUnlock16((HMEM16)psm16->hGlobal);
|
|
|
|
sc = ConvertHGlobal3216(NULL, psm32->hGlobal, 0,
|
|
(HMEM16 *)&psm16->hGlobal, &dwSize);
|
|
// What happens on errors?
|
|
thkAssert(SUCCEEDED(sc));
|
|
}
|
|
|
|
GlobalFree(psm32->hGlobal);
|
|
psm32->hGlobal = NULL;
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
|
|
// Don't delete the handle after a copy since Chicago doesn't actually
|
|
// copy the handle.
|
|
#if !defined(_CHICAGO_)
|
|
METAFILEPICT *pmfp32;
|
|
|
|
pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
|
|
DeleteMetaFile(pmfp32->hMF);
|
|
GlobalUnlock(psm32->hGlobal);
|
|
#endif
|
|
GlobalFree(psm32->hGlobal);
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
// 32-bit handled by ReleaseStgMedium
|
|
// Clean up 16-bit ourselves
|
|
#ifdef SM_FREE_16BIT_FILENAME
|
|
if(fCopy) {
|
|
// 16-bit OLE did not free the filename, so we can't
|
|
// either. This may lead to memory leaks, but there's not
|
|
// really anything we can do about it
|
|
TaskFree16((VPVOID)psm16->lpszFileName);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
if(fCopy) {
|
|
// The proxy to the 16-bit stream interface was released by
|
|
// ReleaseStgMedium
|
|
// Release the reference kept on the 16-bit stream interface
|
|
ReleaseOnObj16((VPVOID) psm16->pstm);
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
if(fCopy) {
|
|
// The proxy to the 16-bit storage interface was released by
|
|
// ReleaseStgMedium
|
|
// Release the reference kept on the 16-bit storage interface
|
|
ReleaseOnObj16((VPVOID) psm16->pstg);
|
|
}
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
case TYMED_NULL:
|
|
// Nothing to release
|
|
break;
|
|
|
|
default:
|
|
thkAssert(!"Unknown tymed in CSm32ReleaseHandler::Release");
|
|
break;
|
|
}
|
|
|
|
// Call Release on the 16-bit vpvForRelease
|
|
if(_vpvForRelease) {
|
|
ReleaseOnObj16(_vpvForRelease);
|
|
_vpvForRelease = NULL;
|
|
}
|
|
|
|
// Clean up this
|
|
delete this;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSm16ReleaseHandler::Init, public
|
|
//
|
|
// Synopsis: Initialize class
|
|
//
|
|
// Arguments: [psm32] - 32-bit STGMEDIUM
|
|
// [psm16] - 16-bit STGMEDIUM
|
|
// [vpvUnkForRelease] - Object for punkForRelease
|
|
// [cfFormat] - Clipboard format associated with STGMEDIUM
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CSm16ReleaseHandler::Init(IUnknown *pThkMgr,
|
|
STGMEDIUM *psm32,
|
|
STGMEDIUM UNALIGNED *psm16,
|
|
IUnknown *punkForRelease,
|
|
CLIPFORMAT cfFormat)
|
|
{
|
|
_avpfnVtbl = gdata16Data.avpfnSm16ReleaseHandlerVtbl;
|
|
_sm32 = *psm32;
|
|
|
|
// Unfortunately, the MIPS compiler is not smart enough
|
|
// to do the right thing if we just (ony) declare psm16 as UNALIGNED,
|
|
// it doesn't recognize that each member of the structure is also
|
|
// unaligned when it does the structure copy. So...to make
|
|
// sure we don't generate an alignment fault, we just copy each
|
|
// member of the structure directly.
|
|
|
|
_sm16.tymed = psm16->tymed;
|
|
_sm16.hGlobal = psm16->hGlobal;
|
|
_sm16.pstm = psm16->pstm;
|
|
_sm16.pstg = psm16->pstg;
|
|
_sm16.pUnkForRelease = psm16->pUnkForRelease;
|
|
|
|
_punkForRelease = punkForRelease;
|
|
_cReferences = 1;
|
|
_cfFormat = cfFormat;
|
|
_pUnkThkMgr = pThkMgr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CSm16ReleaseHandler_Release32, public
|
|
//
|
|
// Synopsis: Handles 32-bit portion of cleaning up STGMEDIUMs for
|
|
// punkForRelease
|
|
//
|
|
// Arguments: [psrh] - this
|
|
// [dw1]
|
|
// [dw2]
|
|
//
|
|
// Returns: punkForRelease->Release()
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(DWORD) CSm16ReleaseHandler_Release32(CSm16ReleaseHandler *psrh,
|
|
DWORD dw1,
|
|
DWORD dw2)
|
|
{
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
STGMEDIUM *psm32;
|
|
DWORD dwSize;
|
|
SCODE sc;
|
|
BOOL fCopy;
|
|
|
|
if(psrh->_punkForRelease) {
|
|
// This is the last release on ReleaseHandler
|
|
// Cleanup 16-bit STGMEDIUM after copying it to
|
|
// 32-bit STGMEDIUM.
|
|
fCopy = TRUE;
|
|
}
|
|
else {
|
|
// The current call failed.
|
|
// As the fields in the 32-bit STGMEDIUM are not longer valid,
|
|
// cleanup the 16-bit STGMEDIUM without copying it to
|
|
// 32-bit STGMEDIUM
|
|
fCopy = FALSE;
|
|
}
|
|
|
|
psm16 = &psrh->_sm16;
|
|
psm32 = &psrh->_sm32;
|
|
switch(psm32->tymed)
|
|
{
|
|
case TYMED_FILE:
|
|
// 16-bit code cleaned up the 16-bit name,
|
|
// now clean up the 32-bit name
|
|
if (fCopy) {
|
|
TaskFree32(psm32->lpszFileName);
|
|
}
|
|
break;
|
|
|
|
case TYMED_HGLOBAL:
|
|
// Assumption that OBJECTDESCRIPTOR does not need copyback
|
|
if(fCopy && !OBJDESC_CF(psrh->_cfFormat))
|
|
{
|
|
// Do we ever need to do this?
|
|
// Copy data back and free global memory
|
|
|
|
dwSize = (DWORD) GlobalSize(psm32->hGlobal);
|
|
|
|
sc = ConvertHGlobal1632(NULL, (HMEM16)psm16->hGlobal, 0,
|
|
&psm32->hGlobal, &dwSize);
|
|
// What happens on errors?
|
|
thkAssert(SUCCEEDED(sc));
|
|
}
|
|
|
|
WOWGlobalFree16((HMEM16)psm16->hGlobal);
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
// Untouched in this case
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
if(fCopy) {
|
|
// The proxy to the 32-bit stream interface was released by
|
|
// ReleaseStgMedium
|
|
// Release the reference kept on the 32-bit stream interface
|
|
psm32->pstm->Release();
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
if(fCopy) {
|
|
// The proxy to the 32-bit stream interface was released by
|
|
// ReleaseStgMedium
|
|
// Release the reference kept on the 32-bit stream interface
|
|
psm32->pstg->Release();
|
|
}
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
case TYMED_NULL:
|
|
// Nothing to release
|
|
break;
|
|
|
|
default:
|
|
thkAssert(!"Unknown tymed in ReleaseStgMedium32");
|
|
break;
|
|
}
|
|
|
|
// Call Release on the 32-bit punkForRelease
|
|
if(fCopy) {
|
|
psrh->_punkForRelease->Release();
|
|
psrh->_punkForRelease = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertStgMed1632, public
|
|
//
|
|
// Synopsis: Converts a 16-bit STGMEDIUM to 32-bits
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
|
|
// [psm32] - 32-bit STGMEDIUM to fill in
|
|
// [pfe] - FORMATETC paired with STGMEDIUM or NULL
|
|
// [pdwSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pdwSize]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
// Notes: [pdwSize] is only set for TYMED_HGLOBAL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertStgMed1632(THUNKINFO *pti,
|
|
VPVOID vpsm16,
|
|
STGMEDIUM *psm32,
|
|
FORMATETC *pfe,
|
|
BOOL fPassingOwnershipIn,
|
|
DWORD *pdwSize)
|
|
{
|
|
SCODE sc;
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
CSm32ReleaseHandler *psrh;
|
|
IUnknown *punkForRelease;
|
|
VPVOID vpvUnk, vpvForRelease;
|
|
HMEM16 hmem16;
|
|
HGDIOBJ hGDI = NULL;
|
|
THKSTATE thkstateSaved;
|
|
|
|
psm16 = (STGMEDIUM UNALIGNED *)
|
|
GetReadPtr16(pti, vpsm16, sizeof(STGMEDIUM));
|
|
if (psm16 == NULL)
|
|
{
|
|
return pti->scResult;
|
|
}
|
|
|
|
sc = S_OK;
|
|
|
|
psm32->tymed = psm16->tymed;
|
|
|
|
vpvForRelease = (VPVOID)psm16->pUnkForRelease;
|
|
WOWRELVDMPTR(vpsm16);
|
|
|
|
if(vpvForRelease) {
|
|
// Create the 32-bit punkForRelease
|
|
thkDebugOut((DEB_WARN, "pUnkForRelease present in StgMedium1632\n"));
|
|
psrh = new CSm32ReleaseHandler;
|
|
if(psrh == NULL)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else {
|
|
psrh = NULL;
|
|
}
|
|
psm32->pUnkForRelease = psrh;
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
|
|
// Word 6 insists on treating BITMAPs as HGLOBALS, which is bogus.
|
|
// If this is the case, just patch the tymed to the correct value
|
|
|
|
if (pfe != NULL)
|
|
{
|
|
if( (pfe->cfFormat == CF_BITMAP || pfe->cfFormat == CF_PALETTE ) &&
|
|
psm16->tymed == TYMED_HGLOBAL )
|
|
{
|
|
DWORD dw = TlsThkGetAppCompatFlags();
|
|
|
|
// if we are in Word 6, then hack the tymed so we thunk the
|
|
// bitmaps as GDI objects
|
|
|
|
if( (dw & OACF_USEGDI ) )
|
|
{
|
|
DWORD dwType;
|
|
|
|
hGDI = HBITMAP_32((HBITMAP16)psm16->hBitmap);
|
|
|
|
// make sure HGDI is either a bitmap or palette
|
|
|
|
dwType = GetObjectType(hGDI);
|
|
if( (pfe->cfFormat == CF_BITMAP && dwType == OBJ_BITMAP) ||
|
|
(pfe->cfFormat == CF_PALETTE && dwType == OBJ_PAL) )
|
|
{
|
|
psm16->tymed = TYMED_GDI;
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_WARN,
|
|
"WARNING! invalid bitmap or palette!\n"));
|
|
hGDI = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_WARN, "WARNING! App trying to transfer a "
|
|
"bitmap or palette on an HGLOBAL\n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
switch( psm16->tymed )
|
|
{
|
|
case TYMED_HGLOBAL:
|
|
hmem16 = (HMEM16)psm16->hGlobal;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if (pfe && OBJDESC_CF(pfe->cfFormat))
|
|
{
|
|
sc = ConvertObjDesc1632(pti, hmem16, &psm32->hGlobal);
|
|
}
|
|
#if !defined(_CHICAGO_)
|
|
|
|
else if (pfe && pfe->cfFormat == CF_HDROP)
|
|
{
|
|
// fix for mapi forms
|
|
// thunk CF_HDROP passed as HGLOBAL format
|
|
sc = ConvertHDrop1632(hmem16, &psm32->hGlobal);
|
|
}
|
|
|
|
#endif
|
|
else
|
|
{
|
|
psm32->hGlobal = 0;
|
|
sc = ConvertHGlobal1632(pti, hmem16, THOP_INOUT,
|
|
&psm32->hGlobal, pdwSize);
|
|
}
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
hmem16 = (HMEM16)psm16->hGlobal;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
sc = ConvertMfPict1632(pti, hmem16, &psm32->hGlobal);
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
psm32->lpszFileName =
|
|
Convert_VPSTR_to_LPOLESTR( pti,
|
|
(VPVOID)psm16->lpszFileName,
|
|
NULL, 0 );
|
|
if (psm32->lpszFileName == NULL)
|
|
{
|
|
sc = pti->scResult;
|
|
}
|
|
else
|
|
{
|
|
#if DBG == 1
|
|
thkDebugOut((DEB_ARGS, "1632 TYMED_FILE: '%ws' (%s)\n",
|
|
psm32->lpszFileName,
|
|
WOWFIXVDMPTR((VPVOID)psm16->lpszFileName, 0)));
|
|
WOWRELVDMPTR((VPVOID)psm16->lpszFileName);
|
|
#endif
|
|
}
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
vpvUnk = (VPVOID)psm16->pstm;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
psm32->pstm =
|
|
(LPSTREAM)pti->pThkMgr->FindProxy3216(NULL, vpvUnk, NULL,
|
|
INDEX_IIDIDX(THI_IStream),
|
|
FALSE, NULL);
|
|
if(psm32->pstm) {
|
|
thkDebugOut((DEB_ARGS, "1632 TYMED_ISTREAM: %p -> %p\n",
|
|
vpvUnk, psm32->pstm));
|
|
}
|
|
else {
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
vpvUnk = (VPVOID)psm16->pstg;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
psm32->pstg =
|
|
(LPSTORAGE)pti->pThkMgr->FindProxy3216(NULL, vpvUnk, NULL,
|
|
INDEX_IIDIDX(THI_IStorage),
|
|
FALSE, NULL);
|
|
if(psm32->pstg) {
|
|
thkDebugOut((DEB_ARGS, "1632 TYMED_ISTORAGE: %p -> %p\n",
|
|
vpvUnk, psm32->pstg));
|
|
}
|
|
else {
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
// if we're in Word6, then we may have already converted the bitmap
|
|
// or palette handle
|
|
if( hGDI == NULL )
|
|
{
|
|
psm32->hBitmap = HBITMAP_32((HBITMAP16)psm16->hBitmap);
|
|
}
|
|
else
|
|
{
|
|
psm32->hBitmap = (HBITMAP)hGDI;
|
|
}
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 TYMED_GDI: 0x%04X -> 0x%p\n",
|
|
psm16->hBitmap, psm32->hBitmap));
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
case TYMED_NULL:
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
default:
|
|
RELVDMPTR(vpsm16);
|
|
sc = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
delete psrh;
|
|
}
|
|
else
|
|
{
|
|
if (psrh)
|
|
{
|
|
CLIPFORMAT cf;
|
|
|
|
if (pfe)
|
|
{
|
|
cf = pfe->cfFormat;
|
|
}
|
|
else
|
|
{
|
|
cf = CF_INVALID;
|
|
}
|
|
thkAssert(vpvForRelease);
|
|
psrh->Init(pti->pThkMgr, FIXVDMPTR(vpsm16, STGMEDIUM), psm32,
|
|
vpvForRelease, cf);
|
|
RELVDMPTR(vpsm16);
|
|
}
|
|
|
|
#if DBG == 1
|
|
if (pfe)
|
|
{
|
|
thkDebugOut((DEB_ARGS, "1632 STGMEDIUM FORMATETC %p {%d}\n",
|
|
pfe, pfe->cfFormat));
|
|
}
|
|
thkDebugOut((DEB_ARGS, "1632 STGMEDIUM: %p {%d, %p, ...} -> "
|
|
"%p {%d, %p, ...}\n", vpsm16, psm16->tymed,
|
|
psm16->pUnkForRelease, psm32, psm32->tymed,
|
|
psm32->pUnkForRelease));
|
|
#endif
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CleanStgMed32, public
|
|
//
|
|
// Synopsis: Cleans up a 32-bit STGMEDIUM
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [psm32] - STGMEDIUM to clean
|
|
// [vpsm16] - Source STGMEDIUM if thunk
|
|
// [dwSize] - Source size if thunk
|
|
// [fIsThunk] - STGMEDIUM was generated by thunking
|
|
// [pfe] - FORMATETC or NULL
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CleanStgMed32(THUNKINFO *pti,
|
|
STGMEDIUM *psm32,
|
|
VPVOID vpsm16,
|
|
DWORD dwSize,
|
|
BOOL fIsThunk,
|
|
FORMATETC *pfe)
|
|
{
|
|
SCODE sc;
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
HMEM16 hmem16;
|
|
VPVOID vpvUnk;
|
|
BOOL fCleanup = TRUE;
|
|
|
|
thkDebugOut((DEB_ITRACE, "In CleanStgMed32(%p, %p, %p, %u, %d, %p)\n",
|
|
pti, psm32, vpsm16, dwSize, fIsThunk, pfe));
|
|
|
|
sc = S_OK;
|
|
|
|
if(fIsThunk && psm32->pUnkForRelease) {
|
|
// This means that the current call failed
|
|
// Inform the 32-bit punkForRelease created during thunking
|
|
// so that it would cleanup 32-bit STGMEDIUM
|
|
((CSm32ReleaseHandler *) (psm32->pUnkForRelease))->CallFailed();
|
|
fCleanup = FALSE;
|
|
}
|
|
|
|
switch( psm32->tymed )
|
|
{
|
|
case TYMED_HGLOBAL:
|
|
if (fIsThunk &&
|
|
(pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
|
|
{
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
hmem16 = (HMEM16)psm16->hGlobal;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
Assert(NULL != psm32->hGlobal);
|
|
|
|
sc = ConvertHGlobal3216(pti, psm32->hGlobal, 0,
|
|
&hmem16, &dwSize);
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->hGlobal = (HGLOBAL)hmem16;
|
|
RELVDMPTR(vpsm16);
|
|
}
|
|
|
|
if(fCleanup) {
|
|
GlobalFree( psm32->hGlobal );
|
|
psm32->hGlobal = NULL;
|
|
}
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
|
|
// Don't delete the handle after a copy since Chicago doesn't actually
|
|
// copy the handle.
|
|
if(fCleanup) {
|
|
#if !defined(_CHICAGO_)
|
|
// Can't modify an MFPICT
|
|
METAFILEPICT *pmfp32;
|
|
|
|
pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
|
|
DeleteMetaFile(pmfp32->hMF);
|
|
GlobalUnlock(psm32->hGlobal);
|
|
#endif
|
|
GlobalFree(psm32->hGlobal);
|
|
}
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
Convert_VPSTR_to_LPOLESTR_free( NULL, psm32->lpszFileName );
|
|
#ifdef SM_FREE_16BIT_FILENAME
|
|
if(fCleanup) {
|
|
// 16-bit OLE did not free the filename, so we can't
|
|
// either. This may lead to memory leaks, but there's not
|
|
// really anything we can do about it
|
|
TaskFree16((VPVOID)psm16->lpszFileName);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
if(fIsThunk) {
|
|
// Release the 32-bit stream interface
|
|
psm32->pstm->Release();
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
if(fIsThunk) {
|
|
// Release the 32-bit storage interface
|
|
psm32->pstg->Release();
|
|
}
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
//
|
|
// No unthunking needed
|
|
//
|
|
break;
|
|
|
|
case TYMED_NULL:
|
|
break;
|
|
|
|
default:
|
|
// Ignore, this case is handled on input
|
|
thkAssert(!"STGMEDIUM with invalid tymed");
|
|
break;
|
|
}
|
|
|
|
if(fIsThunk && psm32->pUnkForRelease) {
|
|
// Release the 32-bit STGMEDIUM pUnkForRelease.
|
|
// 32-bit STGMEDIUM would be cleaned up after the last release
|
|
psm32->pUnkForRelease->Release();
|
|
}
|
|
|
|
thkDebugOut((DEB_ITRACE, "Out CleanStgMed32 => 0x%08lX\n", sc));
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertStgMed3216, public
|
|
//
|
|
// Synopsis: Converts a 32-bit STGMEDIUM to 16-bits
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [psm32] - 32-bit STGMEDIUM
|
|
// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
|
|
// [pfe] - FORMATETC paired with STGMEDIUM or NULL
|
|
// [pdwSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pdwSize]
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
// Notes: [pdwSize] is only set for TYMED_HGLOBAL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertStgMed3216(THUNKINFO *pti,
|
|
STGMEDIUM *psm32,
|
|
VPVOID vpsm16,
|
|
FORMATETC *pfe,
|
|
BOOL fPassingOwnershipIn,
|
|
DWORD *pdwSize)
|
|
{
|
|
SCODE sc;
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
VPVOID vpsrh;
|
|
VPSTR vpstr;
|
|
UINT uiSize;
|
|
VPVOID vpvUnkForRelease;
|
|
VPVOID vpvUnk;
|
|
HMEM16 hmem16;
|
|
THKSTATE thkstateSaved;
|
|
|
|
sc = S_OK;
|
|
|
|
if(psm32->pUnkForRelease) {
|
|
thkDebugOut((DEB_WARN, "pUnkForRelease present in StgMedium3216\n"));
|
|
vpsrh = WOWGlobalAllocLock16(GMEM_MOVEABLE, sizeof(CSm16ReleaseHandler),
|
|
NULL);
|
|
if(vpsrh == 0)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else {
|
|
vpsrh = 0;
|
|
}
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->tymed = psm32->tymed;
|
|
psm16->pUnkForRelease = (IUnknown *)vpsrh;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
switch( psm32->tymed )
|
|
{
|
|
case TYMED_HGLOBAL:
|
|
if (pfe && OBJDESC_CF(pfe->cfFormat))
|
|
{
|
|
sc = ConvertObjDesc3216(pti, psm32->hGlobal, &hmem16);
|
|
}
|
|
#if !defined(_CHICAGO_)
|
|
|
|
else if (pfe && pfe->cfFormat == CF_HDROP)
|
|
{
|
|
// fix for mapi forms
|
|
sc = ConvertHDrop3216(psm32->hGlobal, &hmem16);
|
|
}
|
|
|
|
#endif
|
|
else
|
|
{
|
|
hmem16 = 0;
|
|
sc = ConvertHGlobal3216(pti, psm32->hGlobal, THOP_INOUT,
|
|
&hmem16, pdwSize);
|
|
}
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->hGlobal = (HGLOBAL)hmem16;
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
sc = ConvertMfPict3216(pti, psm32->hGlobal, &hmem16);
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->hGlobal = (HGLOBAL)hmem16;
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
uiSize = lstrlenW(psm32->lpszFileName) + 1;
|
|
vpstr = TaskMalloc16( uiSize*2 );
|
|
if ( vpstr == NULL )
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
sc = Convert_LPOLESTR_to_VPSTR( psm32->lpszFileName,
|
|
vpstr, uiSize, uiSize*2 );
|
|
if (FAILED(sc))
|
|
{
|
|
TaskFree16(vpstr);
|
|
}
|
|
else
|
|
{
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->lpszFileName = (LPOLESTR)vpstr;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
#if DBG == 1
|
|
thkDebugOut((DEB_ARGS, "3216 TYMED_FILE: '%s' (%ws)\n",
|
|
WOWFIXVDMPTR(vpstr, 0),
|
|
psm32->lpszFileName));
|
|
WOWRELVDMPTR(vpstr);
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstm, NULL,
|
|
INDEX_IIDIDX(THI_IStream),
|
|
NULL);
|
|
if (vpvUnk == 0)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_ARGS, "3216 TYMED_ISTREAM: %p -> %p\n",
|
|
psm32->pstm, vpvUnk));
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->pstm = (IStream *)vpvUnk;
|
|
RELVDMPTR(vpsm16);
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstg, NULL,
|
|
INDEX_IIDIDX(THI_IStorage),
|
|
NULL);
|
|
if (vpvUnk == 0)
|
|
{
|
|
sc = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
thkDebugOut((DEB_ARGS, "3216 TYMED_ISTORAGE: %p -> %p\n",
|
|
psm32->pstg, vpvUnk));
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->pstg = (IStorage *)vpvUnk;
|
|
RELVDMPTR(vpsm16);
|
|
}
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
psm16->hBitmap = (HBITMAP)HBITMAP_16(psm32->hBitmap);
|
|
thkDebugOut((DEB_ARGS, "3216 TYMED_GDI: 0x%p -> 0x%04X\n",
|
|
psm32->hBitmap, psm16->hBitmap));
|
|
RELVDMPTR(vpsm16);
|
|
break;
|
|
|
|
case TYMED_NULL:
|
|
break;
|
|
|
|
default:
|
|
sc = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
if (vpsrh != 0)
|
|
{
|
|
WOWGlobalUnlockFree16(vpsrh);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (vpsrh != 0)
|
|
{
|
|
CSm16ReleaseHandler UNALIGNED *psrh;
|
|
CLIPFORMAT cf;
|
|
|
|
if (pfe)
|
|
{
|
|
cf = pfe->cfFormat;
|
|
}
|
|
else
|
|
{
|
|
cf = CF_INVALID;
|
|
}
|
|
thkAssert(psm32->pUnkForRelease);
|
|
psrh = FIXVDMPTR(vpsrh, CSm16ReleaseHandler);
|
|
psrh->Init(pti->pThkMgr, psm32, FIXVDMPTR(vpsm16, STGMEDIUM),
|
|
psm32->pUnkForRelease, cf);
|
|
RELVDMPTR(vpsrh);
|
|
RELVDMPTR(vpsm16);
|
|
}
|
|
|
|
#if DBG == 1
|
|
if (pfe)
|
|
{
|
|
thkDebugOut((DEB_ARGS, "3216 STGMEDIUM FORMATETC %p {%d}\n",
|
|
pfe, pfe->cfFormat));
|
|
}
|
|
thkDebugOut((DEB_ARGS, "3216 STGMEDIUM: %p {%d, %p, ...} -> "
|
|
"%p {%d, %p, ...}\n", psm32, psm32->tymed,
|
|
psm32->pUnkForRelease, vpsm16, psm16->tymed,
|
|
psm16->pUnkForRelease));
|
|
#endif
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CleanStgMed16, public
|
|
//
|
|
// Synopsis: Frees up resources in a 16-bit STGMEDIUM
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [vpsm16] - STGMEDIUM to clean
|
|
// [psm32] - Source STGMEDIUM if thunk
|
|
// [dwSize] - Source size for thunked HGLOBAL
|
|
// [fIsThunk] - If the STGMEDIUM is a result of thunking
|
|
// [pfe] - FORMATETC or NULL
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Apr-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CleanStgMed16(THUNKINFO *pti,
|
|
VPVOID vpsm16,
|
|
STGMEDIUM *psm32,
|
|
DWORD dwSize,
|
|
BOOL fIsThunk,
|
|
FORMATETC *pfe)
|
|
{
|
|
SCODE sc;
|
|
STGMEDIUM UNALIGNED *psm16;
|
|
VPVOID vpvUnk, vpv;
|
|
HMEM16 hmem16;
|
|
BOOL fCleanup = TRUE;
|
|
|
|
thkDebugOut((DEB_ITRACE, "In CleanStgMed16(%p, %p, %p, %u, %d, %p)\n",
|
|
pti, vpsm16, psm32, dwSize, fIsThunk, pfe));
|
|
|
|
sc = S_OK;
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
vpvUnk = (VPVOID)psm16->pUnkForRelease;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if (fIsThunk && vpvUnk)
|
|
{
|
|
// This means that the current call failed
|
|
// Inform the 32-bit punkForRelease created during thunking
|
|
// so that it would cleanup 32-bit STGMEDIUM
|
|
CSm16ReleaseHandler UNALIGNED *psrh;
|
|
|
|
psrh = FIXVDMPTR(vpvUnk, CSm16ReleaseHandler);
|
|
psrh->CallFailed();
|
|
RELVDMPTR(vpvUnk);
|
|
fCleanup = FALSE;
|
|
}
|
|
|
|
psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
|
|
switch( psm16->tymed )
|
|
{
|
|
case TYMED_HGLOBAL:
|
|
hmem16 = (HMEM16)psm16->hGlobal;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if (fIsThunk &&
|
|
(pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
|
|
{
|
|
sc = ConvertHGlobal1632(pti, hmem16, 0,
|
|
&psm32->hGlobal, &dwSize);
|
|
}
|
|
|
|
if(fCleanup)
|
|
WOWGlobalFree16(hmem16);
|
|
|
|
break;
|
|
|
|
case TYMED_MFPICT:
|
|
hmem16 = (HMEM16)psm16->hGlobal;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
|
|
// Don't delete the handle after a copy since Chicago doesn't actually
|
|
// copy the handle.
|
|
if(fCleanup) {
|
|
#if !defined(_CHICAGO_)
|
|
VPVOID vpvmfp16;
|
|
METAFILEPICT16 *pmfp16;
|
|
HMEM16 hmf16;
|
|
|
|
vpvmfp16 = WOWGlobalLock16(hmem16);
|
|
pmfp16 = FIXVDMPTR(vpvmfp16, METAFILEPICT16);
|
|
hmf16 = pmfp16->hMF;
|
|
RELVDMPTR(vpvmfp16);
|
|
|
|
// Relies on the fact that a 16-bit metafile is an HGLOBAL
|
|
WOWGlobalFree16(hmf16);
|
|
|
|
WOWGlobalUnlockFree16(vpvmfp16);
|
|
#else
|
|
WOWGlobalFree16(hmem16);
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case TYMED_FILE:
|
|
vpv = (VPVOID)psm16->lpszFileName;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if(fCleanup)
|
|
TaskFree16(vpv);
|
|
break;
|
|
|
|
case TYMED_ISTREAM:
|
|
vpv = (VPVOID) psm16->pstm;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if(fIsThunk) {
|
|
// Release the 16-bit stream interface
|
|
ReleaseOnObj16(vpv);
|
|
}
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
vpv = (VPVOID) psm16->pstg;
|
|
RELVDMPTR(vpsm16);
|
|
|
|
if(fIsThunk) {
|
|
// Release the 16-bit storage interface
|
|
ReleaseOnObj16(vpv);
|
|
}
|
|
break;
|
|
|
|
case TYMED_GDI:
|
|
RELVDMPTR(vpsm16);
|
|
|
|
//
|
|
// No unthunking needed
|
|
//
|
|
break;
|
|
|
|
case TYMED_NULL:
|
|
RELVDMPTR(vpsm16);
|
|
|
|
break;
|
|
|
|
default:
|
|
// Ignore, this case is handled on input
|
|
thkAssert(!"CleanStgMed16 with invalid tymed");
|
|
break;
|
|
}
|
|
|
|
if(fIsThunk && vpvUnk) {
|
|
// Release the 16-bit STGMEDIUM vpvForRelease.
|
|
// 16-bit STGMEDIUM would be cleaned up after the last release
|
|
ReleaseOnObj16(vpvUnk);
|
|
}
|
|
|
|
thkDebugOut((DEB_ITRACE, "Out CleanStgMed16 => 0x%08lX\n", sc));
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertFetc1632, public
|
|
//
|
|
// Synopsis: Converts a FORMATETC
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [vpfe16] - FORMATETC
|
|
// [pfe32] - FORMATETC
|
|
// [fFree] - Free resources as converting
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pfe32]
|
|
//
|
|
// History: 14-May-94 DrewB Created
|
|
// 11-Dec-00 DickD initialize pdv32 (prefix bug 22397)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertFetc1632(THUNKINFO *pti,
|
|
VPVOID vpfe16,
|
|
FORMATETC *pfe32,
|
|
BOOL fFree)
|
|
{
|
|
FORMATETC16 UNALIGNED *pfe16;
|
|
VPVOID vpdv16;
|
|
DVTARGETDEVICE *pdv32 = NULL;
|
|
UINT cbSize;
|
|
SCODE sc;
|
|
|
|
pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
|
|
vpdv16 = (VPVOID)pfe16->ptd;
|
|
RELVDMPTR(vpfe16);
|
|
|
|
if ( vpdv16 == 0 )
|
|
{
|
|
pdv32 = NULL;
|
|
}
|
|
else
|
|
{
|
|
sc = ConvertDvtd1632(pti, vpdv16, ArTask32, FrTask32,
|
|
&pdv32, &cbSize);
|
|
|
|
if (fFree)
|
|
{
|
|
TaskFree16(vpdv16);
|
|
}
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
|
|
pfe32->cfFormat = pfe16->cfFormat;
|
|
pfe32->ptd = pdv32;
|
|
pfe32->dwAspect = pfe16->dwAspect;
|
|
pfe32->lindex = pfe16->lindex;
|
|
pfe32->tymed = pfe16->tymed;
|
|
|
|
thkDebugOut((DEB_ARGS, "1632 FORMATETC: "
|
|
"%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
|
|
vpfe16, pfe32,
|
|
pfe32->cfFormat,
|
|
pfe32->ptd, vpdv16,
|
|
pfe32->dwAspect,
|
|
pfe32->lindex,
|
|
pfe32->tymed));
|
|
|
|
RELVDMPTR(vpfe16);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertFetc3216, public
|
|
//
|
|
// Synopsis: Converts a FORMATETC
|
|
//
|
|
// Arguments: [pti] - Thunk info
|
|
// [pfe32] - FORMATETC
|
|
// [vpfe16] - FORMATETC
|
|
// [fFree] - Free resources as converting
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [vpfe16]
|
|
//
|
|
// History: 14-May-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE ConvertFetc3216(THUNKINFO *pti,
|
|
FORMATETC *pfe32,
|
|
VPVOID vpfe16,
|
|
BOOL fFree)
|
|
{
|
|
FORMATETC16 UNALIGNED *pfe16;
|
|
DVTARGETDEVICE *pdv32;
|
|
SCODE sc;
|
|
VPVOID vpdv16;
|
|
UINT cbSize;
|
|
|
|
pdv32 = pfe32->ptd;
|
|
if (pdv32 != NULL)
|
|
{
|
|
sc = ConvertDvtd3216(pti, pdv32, ArTask16, FrTask16,
|
|
&vpdv16, &cbSize);
|
|
|
|
if (fFree)
|
|
{
|
|
TaskFree32(pdv32);
|
|
}
|
|
|
|
if (FAILED(sc))
|
|
{
|
|
return sc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vpdv16 = 0;
|
|
}
|
|
|
|
pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
|
|
pfe16->cfFormat = pfe32->cfFormat;
|
|
pfe16->ptd = vpdv16;
|
|
pfe16->dwAspect = pfe32->dwAspect;
|
|
pfe16->lindex = pfe32->lindex;
|
|
pfe16->tymed = pfe32->tymed;
|
|
|
|
thkDebugOut((DEB_ARGS, "3216 FORMATETC: "
|
|
"%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
|
|
pfe32, vpfe16,
|
|
pfe16->cfFormat,
|
|
vpdv16, pdv32,
|
|
pfe16->dwAspect,
|
|
pfe16->lindex,
|
|
pfe16->tymed));
|
|
|
|
RELVDMPTR(vpfe16);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DebugValidateProxy1632, debug public
|
|
//
|
|
// Synopsis: Validates a 16->32 proxy pointer and its memory
|
|
//
|
|
// Arguments: [vpvProxy] - Proxy
|
|
//
|
|
// History: 07-Jul-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
void DebugValidateProxy1632(VPVOID vpvProxy)
|
|
{
|
|
THUNK1632OBJ UNALIGNED *pto;
|
|
THUNKINFO ti;
|
|
|
|
thkAssert(vpvProxy != 0 && "Invalid proxy pointer");
|
|
|
|
pto = (THUNK1632OBJ UNALIGNED *)
|
|
GetReadWritePtr16(&ti, vpvProxy, sizeof(THUNK1632OBJ));
|
|
thkAssert(pto != NULL && "Invalid proxy pointer");
|
|
|
|
thkAssert(pto->dwSignature == PSIG1632 && "Dead or invalid proxy!");
|
|
|
|
thkAssert(pto->cRefLocal>=0 && "Invalid proxy refcount");
|
|
thkAssert(pto->cRefLocal>=pto->cRef && "Invalid proxy refcount");
|
|
thkAssert((pto->cRefLocal>0 && pto->cRef>0) || (pto->cRef==0 && pto->cRefLocal==0));
|
|
thkAssert(pto->pphHolder && "Proxy without a holder");
|
|
|
|
if (!IsValidInterface(pto->punkThis32))
|
|
{
|
|
thkDebugOut((DEB_ERROR, "1632 %p: Invalid proxied object %p\n",
|
|
vpvProxy, pto->punkThis32));
|
|
}
|
|
|
|
WOWRELVDMPTR(vpvProxy);
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DebugValidateProxy3216, debug public
|
|
//
|
|
// Synopsis: Validates a 32->16 proxy pointer and its memory
|
|
//
|
|
// Arguments: [pto] - Proxy
|
|
//
|
|
// History: 07-Jul-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
void DebugValidateProxy3216(THUNK3216OBJ *pto)
|
|
{
|
|
THUNKINFO ti;
|
|
|
|
thkAssert(pto != 0 && "Invalid proxy pointer");
|
|
|
|
thkAssert(!IsBadReadPtr(pto, sizeof(THUNK3216OBJ)) &&
|
|
!IsBadWritePtr(pto, sizeof(THUNK3216OBJ)) &&
|
|
"Invalid proxy pointer");
|
|
|
|
thkAssert(pto->dwSignature == PSIG3216 && "Dead or invalid proxy!");
|
|
|
|
thkAssert(pto->cRefLocal>=0 && "Invalid proxy refcount");
|
|
thkAssert(pto->cRefLocal>=pto->cRef && "Invalid proxy refcount");
|
|
thkAssert((pto->cRefLocal>0 && pto->cRef>0) || (pto->cRef==0 && pto->cRefLocal==0));
|
|
thkAssert(pto->pphHolder && "Proxy without a holder");
|
|
|
|
if (!IsValidInterface16(&ti, pto->vpvThis16))
|
|
{
|
|
thkDebugOut((DEB_ERROR, "3216 %p: Invalid proxied object %p\n",
|
|
pto, pto->vpvThis16));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ClampLongToShort, public
|
|
//
|
|
// Synopsis: Restricts a long value to a short value by clamping
|
|
//
|
|
// Arguments: [l] - Long
|
|
//
|
|
// Returns: Short
|
|
//
|
|
// History: 16-Aug-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SHORT ClampLongToShort(LONG l)
|
|
{
|
|
SHORT s;
|
|
|
|
if (l < SHRT_MIN)
|
|
{
|
|
s = SHRT_MIN;
|
|
thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
|
|
}
|
|
else if (l > SHRT_MAX)
|
|
{
|
|
s = SHRT_MAX;
|
|
thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
|
|
}
|
|
else
|
|
{
|
|
s = (SHORT)l;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ClampULongToUShort, public
|
|
//
|
|
// Synopsis: Restricts an unsigned long value to an unsigned short value
|
|
// by clamping
|
|
//
|
|
// Arguments: [ul] - Long
|
|
//
|
|
// Returns: UShort
|
|
//
|
|
// History: 16-Aug-94 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
USHORT ClampULongToUShort(ULONG ul)
|
|
{
|
|
USHORT us;
|
|
|
|
if (ul > USHRT_MAX)
|
|
{
|
|
us = USHRT_MAX;
|
|
thkDebugOut((DEB_WARN, "ClampULongToUShort: %ld -> %d\n", ul, us));
|
|
}
|
|
else
|
|
{
|
|
us = (USHORT)ul;
|
|
}
|
|
|
|
return us;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertObjDescriptor
|
|
//
|
|
// Synopsis: Exported API called by WOW to convert ObjectDescriptors to
|
|
// the indicated format.
|
|
//
|
|
//
|
|
// Arguments: [hMem] -- Handle to the ObjectDescriptor to convert.
|
|
// [flag] -- Flag indicating which direction the convertion
|
|
// should take place. Valid values are:
|
|
// CFOLE_UNICODE_TO_ANSI.
|
|
// CFOLE_ANSI_TO_UNICODE.
|
|
//
|
|
// Returns: HGLOBAL to the converted ObjectDescriptor,
|
|
// or NULL on failure.
|
|
//
|
|
// History: 8-16-94 terryru Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDAPI_(HGLOBAL) ConvertObjDescriptor( HANDLE hMem, UINT flag )
|
|
{
|
|
|
|
const UINT CFOLE_UNICODE_TO_ANSI = 0;
|
|
const UINT CFOLE_ANSI_TO_UNICODE = 1;
|
|
|
|
THUNKINFO ti;
|
|
HGLOBAL hMem32;
|
|
HMEM16 hMem16;
|
|
|
|
switch ( flag )
|
|
{
|
|
case CFOLE_UNICODE_TO_ANSI:
|
|
if( FAILED( ConvertObjDesc3216( &ti, (HGLOBAL) hMem, &hMem16 )))
|
|
{
|
|
return (HGLOBAL) NULL;
|
|
}
|
|
else
|
|
{
|
|
return (HGLOBAL) hMem16;
|
|
}
|
|
break;
|
|
|
|
case CFOLE_ANSI_TO_UNICODE:
|
|
if( FAILED( ConvertObjDesc1632( &ti, (HMEM16) hMem, &hMem32 )))
|
|
{
|
|
return (HGLOBAL) NULL;
|
|
}
|
|
else
|
|
{
|
|
return (HGLOBAL) hMem32;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
thkAssert(!"ConvertObjDescriptor, Invalid flag");
|
|
break;
|
|
}
|
|
return (HGLOBAL) NULL;
|
|
}
|
|
|
|
#if defined(_CHICAGO_)
|
|
|
|
//
|
|
// A hack so everyone can build Chicago OLE until I write the thunking
|
|
// library later this week.
|
|
//
|
|
// (15-Feb-2000: I find the fact that this comment is still here amazingly
|
|
// entertaining - JohnDoty)
|
|
//
|
|
|
|
#define ERR ((char*) -1)
|
|
|
|
#if DBG==1
|
|
int UnicodeToAnsi(LPSTR sz, LPCWSTR pwsz, LONG cb)
|
|
{
|
|
int ret;
|
|
|
|
ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL);
|
|
|
|
thkAssert(ret != 0 && "Lost characters in thk Unicode->Ansi conversion");
|
|
if (ret == 0)
|
|
{
|
|
DebugBreak();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
#define UnicodeToAnsi(sz,pwsz,cb) WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL)
|
|
#endif
|
|
|
|
|
|
#if DBG==1
|
|
int AnsiToUnicode(LPWSTR pwsz, LPCSTR sz, LONG cb)
|
|
{
|
|
int ret;
|
|
|
|
ret = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb);
|
|
|
|
thkAssert(ret != 0 && "Lost characters in thk Ansi->Unicode conversion");
|
|
if (ret == 0)
|
|
{
|
|
DebugBreak();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
#define AnsiToUnicode(pwsz,sz,cb) MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb)
|
|
#endif
|
|
|
|
|
|
|
|
extern "C"
|
|
DWORD
|
|
WINAPI
|
|
GetShortPathNameX(
|
|
LPCWSTR lpszFullPath,
|
|
LPWSTR lpszShortPath,
|
|
DWORD cchBuffer
|
|
)
|
|
{
|
|
#ifdef DEBUG_OUTPUT
|
|
OutputDebugString("GetShortPathName\n");
|
|
#endif
|
|
|
|
CHAR szFullPath[MAX_PATH];
|
|
CHAR szShortBuffer[MAX_PATH];
|
|
DWORD ret;
|
|
|
|
|
|
UnicodeToAnsi(szFullPath, lpszFullPath, sizeof(szFullPath));
|
|
|
|
if (lpszShortPath == NULL)
|
|
{
|
|
ret = GetShortPathNameA(szFullPath, NULL, cchBuffer);
|
|
}
|
|
else
|
|
{
|
|
ret = GetShortPathNameA(szFullPath, szShortBuffer,
|
|
sizeof(szShortBuffer));
|
|
|
|
thkAssert(ret != cchBuffer &&
|
|
"GetShortPathName - Output buffer too short");
|
|
//
|
|
// Don't convert the buffer if the
|
|
// call to GetShortPathNameA() failed.
|
|
//
|
|
if(0 != ret)
|
|
{
|
|
//
|
|
// Only convert the actual data, not the whole buffer.
|
|
//
|
|
if (cchBuffer > ret + 1)
|
|
cchBuffer = ret + 1;
|
|
|
|
AnsiToUnicode(lpszShortPath, szShortBuffer, cchBuffer);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif // _CHICAGO_
|
|
|