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