|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: COMLOCAL.CXX (16 bit target)
//
// Contents: CompObj APIs
//
// Functions:
//
// History: 16-Dec-93 JohannP Created
//
//--------------------------------------------------------------------------
#include <headers.cxx>
#pragma hdrstop
#include <ole2ver.h>
#include <ole2sp.h>
#include <olecoll.h>
#include <map_kv.h>
#include "comlocal.hxx"
#include "map_htsk.h"
#include "etask.hxx"
#include "call32.hxx"
#include "apilist.hxx"
UINT v_pidHighWord = 1; // incremented each time used
IMalloc FAR* v_pMallocShared = NULL; // is not addrefed
// Note: bug 3698
// MsPub is not calling CoInitialize befor calling OpenStorage to
// preview templates. This pointer has an addref!
// When this pointer is not NULL CoGetMalloc was called prior to CoInitialize
// The pointer is transfered as soon as CoInitialize is called by any task.
IMalloc FAR* v_pMallocPreShared = NULL; BOOL SetupSharedAllocator(Etask FAR& etask);
//+---------------------------------------------------------------------------
//
// Function: TaskAlloc, private
//
// Synopsis: Allocates task memory
//
// Arguments: [cb] - Number of bytes to allocate
//
// Returns: Pointer to memory or NULL
//
// History: 03-Mar-94 DrewB Created
//
//----------------------------------------------------------------------------
LPVOID __loadds FAR PASCAL TaskAlloc(ULONG cb) { HRESULT hr; LPMALLOC lpMalloc = NULL; LPVOID lpv;
hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc); if (FAILED(GetScode(hr)) ) { lpv = NULL; } else { thkAssert(lpMalloc != NULL && "CoGetMalloc pMalloce is NULL\n"); lpv = lpMalloc->Alloc(cb); lpMalloc->Release(); }
return lpv; }
//+---------------------------------------------------------------------------
//
// Function: TaskFree, private
//
// Synopsis: Free task memory
//
// Arguments: [pv] - Memory
//
// History: 03-Mar-94 DrewB Created
//
//----------------------------------------------------------------------------
void __loadds FAR PASCAL TaskFree(LPVOID pv) { HRESULT hr; LPMALLOC lpMalloc;
hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc); if (SUCCEEDED(GetScode(hr))) { lpMalloc->Free(pv); lpMalloc->Release(); } }
//+---------------------------------------------------------------------------
//
// Method: SetupSharedAllocator
//
// Synopsis: Allocats the shared allocator and
// initializes the etask shared allocator
//
// Arguments: [etask] --
//
// Returns:
//
// History: 2-03-95 JohannP (Johann Posch) Created
//
// Notes: call by CoInitialize and DllEntryPoint
//
//----------------------------------------------------------------------------
BOOL SetupSharedAllocator(Etask FAR& etask) { // we must ensure we have a shared allocator now since that is where the
// etask map wiil be stored; if another process already created it, use it;
// this is so we always use the same shared pool of memory for all
// processes (so the DidAlloc method returns 1 for the same call from
// different process); the pointer refers to shared memory within
// the blocks managed by the IMalloc implementation and the
// vtable is always valid on Windows; the global pointer carries
// no ref count on its own; changes might be requires on
// other platforms.
if (v_pMallocPreShared != NULL) { // Note: fix for bug 3698;l MsPub not calling CoInitialize
// transfer addref from preshared to task entry
etask.m_pMallocShared = v_pMallocPreShared; v_pMallocShared = v_pMallocPreShared; v_pMallocPreShared = NULL; } else if (v_pMallocShared != NULL) { (etask.m_pMallocShared = v_pMallocShared)->AddRef(); } else { // sets pMalloc to NULL on error
CoCreateStandardMalloc(MEMCTX_SHARED, &etask.m_pMallocShared); v_pMallocShared = etask.m_pMallocShared; thkAssert(v_pMallocShared != NULL && "SetupSharedAllocator failed!"); } return (v_pMallocShared != NULL) ? TRUE : FALSE; }
//+---------------------------------------------------------------------------
//
// Function: CoInitialize, Split
//
// Synopsis:
//
// Effects:
//
// Arguments: [pMalloc] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 2-28-94 kevinro Created
// 3-08-94 BobDay Added code from \\ole\slm\...\compobj.cpp
//
// Notes:
//
//----------------------------------------------------------------------------
// initialize compobj; errors: S_FALSE, E_OUTOFMEMORY
STDAPI CoInitialize(IMalloc FAR* pMalloc) { LPMALLOC pmlNull = NULL; HRESULT hresult; HTASK htask; Etask etask;
thkDebugOut((DEB_ITRACE, "CoInitialize\n")); thkDebugOut((DEB_APIS16, "CoInitilaize called on Process (%X) \n", GetCurrentProcess()));
// if already init, bump count and return S_FALSE
if ( IsEtaskInit(htask, etask) && IsValidInterface((etask.m_pMalloc)) ) { if ( etask.m_inits != ETASK_FAKE_INIT ) { etask.m_inits++; thkVerify(SetEtask(htask, etask)); return ResultFromScode(S_FALSE); }
//
// CoInitialize has been called after we've done a fake call for them
// we can just take over their allocator and get rid of our fake one.
//
if ( pMalloc != NULL ) { etask.m_pMalloc->Release(); // Get rid of the old task allocator
etask.m_pMalloc = pMalloc; etask.m_pMalloc->AddRef(); } else { //
// It would be nice if we could assert that the fake task
// allocator was a default task allocator. i.e. no operation
// were really needed!
//
}
//
// "We need to have a way to clean up any fake calls to
// CoInitialize. Should the application go away after using one of
// the apis that caused us to do a fake CoInitialize in the first
// place, and should the application exit without really making a
// call to CoInitialize eventually, then we wouldn't know enough to
// clean up... I think this is ok for now. Most apps do call
// CoInitialize eventually."
//
etask.m_inits = 1;
thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
thkVerify(SetEtask(htask, etask)); return ResultFromScode(S_OK); }
// set/create task malloc
if (pMalloc != NULL) { VDATEIFACE( pMalloc ); (etask.m_pMalloc = pMalloc)->AddRef(); } else { if ((hresult = CoCreateStandardMalloc(MEMCTX_TASK, &etask.m_pMalloc)) != NOERROR) return hresult; } thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
// set up the shared allocator
if ( etask.m_pMallocShared == NULL && SetupSharedAllocator(etask) == FALSE) { etask.m_pMalloc->Release(); // was created or AddRef'd above
return ResultFromScode(E_OUTOFMEMORY); }
// now have shared allocator in all cases
thkAssert(etask.m_pMallocShared != NULL);
// init remaining entries and add entry to table for this app/task pair;
// leave maps null for now (they are allocated on demand)
etask.m_pMallocSBlock = NULL; etask.m_pMallocPrivate = NULL; etask.m_pid = MAKELONG(GetCurrentProcess(),v_pidHighWord++); etask.m_inits = 1; etask.m_oleinits = 0; etask.m_reserved = 0; etask.m_pDlls = NULL; etask.m_pMapToServerCO = NULL; etask.m_pMapToHandlerCO = NULL; etask.m_pArraySH = NULL; etask.m_pCThrd = NULL; etask.m_hwndClip = NULL; etask.m_hwndDde = NULL; etask.m_punkState = NULL;
if (!SetEtask(htask, etask)) { ReleaseEtask(NULL, etask); thkAssert(0 && "CompObj: CoInitialize SetEtask failed."); return ResultFromScode(E_OUTOFMEMORY); }
// Initialize the thunk manager for this apartment.
if (SUCCEEDED(hresult = CallThkMgrInitialize())) { //
// Now transition into 32-bit world to give it a chance for
// initialization at this time.
//
// Never pass the 16-bit allocator on to 32-bits
pMalloc = NULL; hresult = (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoInitialize), PASCAL_STACK_PTR(pMalloc) ); }
if (FAILED(GetScode(hresult))) { ReleaseEtask(htask, etask); }
return hresult; }
//+---------------------------------------------------------------------------
//
// Function: CoUninitialize, Split
//
// Synopsis:
//
// Effects:
//
// Arguments: [void] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 2-28-94 kevinro Created
// 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI_(void) CoUninitialize(void) { HTASK htask; Etask etask;
thkDebugOut((DEB_ITRACE, "CoUninitialize\n")); thkDebugOut((DEB_APIS16, "CoUninitilaize called on Process (%X) \n", GetCurrentProcess()));
if (!IsEtaskInit(htask, etask)) return;
// if not last uninit, just decrement count and return.
if (etask.m_inits != 1) { //
// If a fake init, then just ignore as if we haven't ever init'd
//
if ( etask.m_inits == ETASK_FAKE_INIT ) { //
// Some slimy app doesn't call CoInitialize but does eventually
// call CoUninitialize. Lets find them if they do!
//
thkAssert(FALSE && "CoUninitialize called after fake CoInitialize\n"); } else { etask.m_inits--; thkVerify(SetEtask(htask, etask)); } return ; }
// Some applications pass on module handle of loaded dlls.
// As a result LibMain and WEP is not called in the same process.
// To prevent premature unloading of OleThk32.dll call
// SetReleaseDLL(FALSE)
SetReleaseDLL(FALSE);
//
// Now transition into 32-bit world to give it a chance for
// initialization at this time.
//
CallObjectInWOW(THK_API_METHOD(THK_API_CoUninitialize), NULL );
// Reset dll unloading - see above
SetReleaseDLL(TRUE);
CoFreeAllLibraries();
//
// We do not uninitialize the thunk manager at this point. The app may attempt
// to call additional API's after CoUninitialize. For example, Lotus 1-2-3
// is known to do this, as is Publisher. The thunk manager will clean up
// as part of its thread detach.
//
// the last thing is to remove the allocator and delete the etask for us;
// must lookup again in case contents changed.
if (LookupEtask(htask, etask)) ReleaseEtask(htask, etask);
thkDebugOut((DEB_APIS16, "CoUninitilaize on Process (%X) done.\n", GetCurrentProcess())); thkDebugOut((DEB_ITRACE, "CoUninitialize exit\n"));
// Note: some apps check the return value if the void function CoUninitialize
// and they fail if it is not NULL like WinOffice Setup 4.3
// Please don't take it out.
_asm mov ax,0; _asm mov dx,0; }
//+---------------------------------------------------------------------------
//
// Function: CoGetMalloc, Local
//
// Synopsis:
//
// Effects:
//
// Arguments: [dwMemContext] --
// [ppMalloc] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 2-28-94 kevinro Created
// 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
//
// Notes:
//
//----------------------------------------------------------------------------
// return pMalloc for the current task; errors: E_INVALIDARG,
// CO_E_NOTINITIALIZED, E_OUTOFMEMORY (not for task or shared allocators)
STDAPI CoGetMalloc(DWORD dwContext, IMalloc FAR* FAR* ppMalloc) { Etask etask; HTASK htask;
thkDebugOut((DEB_ITRACE, " CoGetMalloc\n"));
VDATEPTROUT( ppMalloc, IMalloc FAR* ); // NOTE: we set *ppMalloc to NULL only in the error cases below
// MOre work here!
// need this for the bootstrap case
if (dwContext == MEMCTX_SHARED) { if (v_pMallocShared != NULL) { *ppMalloc = v_pMallocShared; goto Exit; } // pMallocShared is NULL -- CoInitialize was not called yet.
if (v_pMallocPreShared == NULL) { CoCreateStandardMalloc(MEMCTX_SHARED, &v_pMallocPreShared); if (v_pMallocPreShared != NULL) { *ppMalloc = v_pMallocPreShared; goto Exit; } else { *ppMalloc = NULL; return ResultFromScode(CO_E_NOTINITIALIZED); } } else { *ppMalloc = v_pMallocPreShared; goto Exit; } }
//
// Clip Art Gallery will call pStream->Stat before calling CoInitialize.
// This causes the thunk logic to allocation 16bit memory which will
// fail at this point. The below code to auto-initialize should this
// happen. (Really just a hack for Clip Art Gallery).
//
if ( !IsEtaskInit(htask, etask) || !IsValidInterface((etask.m_pMalloc)) ) { if (FAILED(CoInitialize(NULL))) { *ppMalloc = NULL; return ResultFromScode(CO_E_NOTINITIALIZED); }
thkVerify(LookupEtask( htask, etask )); etask.m_inits = ETASK_FAKE_INIT; thkVerify(SetEtask(htask, etask)); }
// shared always available if initialized; no need to handle here
thkAssert(dwContext != MEMCTX_SHARED);
if (dwContext == MEMCTX_TASK) { thkAssert(etask.m_pMalloc != NULL); *ppMalloc = etask.m_pMalloc; } else { // invalid context
thkAssert(!"Unknown memctx in CoGetMalloc"); *ppMalloc = NULL; return ResultFromScode(E_INVALIDARG); }
Exit: // have non-null *ppMalloc
thkAssert(*ppMalloc != NULL); (*ppMalloc)->AddRef(); return NOERROR; }
//+---------------------------------------------------------------------------
//
// Function: CoGetState, Local
//
// Synopsis: Retrieves task-specific state
//
// Arguments: [ppunk] - IUnknown pointer to fill in
//
// Returns: Appropriate status code
//
// History: 26-Jul-94 DrewB Created
//
// Notes: Private API for OLE automation
//
//----------------------------------------------------------------------------
STDAPI CoGetState(IUnknown FAR * FAR *ppunk) { Etask etask; HTASK htask;
thkDebugOut((DEB_APIS16, "CoGetState called\n")); if (IsBadWritePtr(ppunk, sizeof(IUnknown *))) { thkDebugOut((DEB_APIS16, "CoGetState failed\n")); return ResultFromScode(E_INVALIDARG); }
if (!LookupEtask(htask, etask) || etask.m_punkState == NULL ) { *ppunk = NULL; thkDebugOut((DEB_APIS16, "CoGetState failed\n")); return ResultFromScode(S_FALSE); }
if ( !IsValidInterface((etask.m_punkState)) ) { *ppunk = NULL; etask.m_punkState = NULL; thkDebugOut((DEB_APIS16, "CoGetState failed (invalid interface)\n")); return ResultFromScode(S_FALSE); }
*ppunk = etask.m_punkState; etask.m_punkState->AddRef();
thkDebugOut((DEB_APIS16, "CoGetState done %p\n", *ppunk)); return NOERROR; }
//+---------------------------------------------------------------------------
//
// Function: CoSetState, Local
//
// Synopsis: Sets task-specific state
//
// Arguments: [punk] - State to set
//
// Returns: Appropriate status code
//
// History: 26-Jul-94 DrewB Created
//
// Notes: Private API for OLE automation
//
//----------------------------------------------------------------------------
STDAPI CoSetState(IUnknown FAR *punk) { Etask etask; HTASK htask; IUnknown FAR *punkStateOld;
thkDebugOut((DEB_APIS16, "CoSetState called %p\n", punk));
if (punk != NULL && !IsValidInterface(punk)) { thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk)); return ResultFromScode(E_INVALIDARG); }
if (!IsEtaskInit(htask, etask)) { thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk)); return ResultFromScode(S_FALSE); }
if (punk != NULL) { punk->AddRef(); }
punkStateOld = etask.m_punkState; etask.m_punkState = punk;
thkVerify(SetEtask(htask, etask));
if (punkStateOld != NULL && IsValidInterface(punkStateOld)) { punkStateOld->Release(); }
thkDebugOut((DEB_APIS16, "CoSetState called %p done\n", punk)); return NOERROR; }
//+---------------------------------------------------------------------------
//
// Function: CoGetCurrentProcess, Local
//
//----------------------------------------------------------------------------
// returns a unique value for the current task; this routine is
// necessary because htask values from Window get reused periodically.
STDAPI_(DWORD) CoGetCurrentProcess(void) { HTASK htask; Etask etask;
thkDebugOut((DEB_ITRACE, " CoGetCurrentProcess\n"));
if (!IsEtaskInit(htask, etask)) return 0;
return etask.m_pid; }
//+---------------------------------------------------------------------------
//
// Function: CoBuildVersion, Local
//
//----------------------------------------------------------------------------
STDAPI_(DWORD) CoBuildVersion(VOID) { thkDebugOut((DEB_ITRACE, " CoBuildVersion\n"));
// We must return 23 as our major version number to remain
// compatible with shipped OLE 2.01
// OLE 2.01 shipped with minor version 640
// We return a number slightly higher to differentiate
// our product while indicating compatibility
return MAKELONG(700, 23); }
//+---------------------------------------------------------------------------
//
// Function: CoMarshalHresult, Local
//
// History: Taken straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult) { HRESULT hr;
thkDebugOut((DEB_ITRACE, "CoMarshalHresult\n"));
if (!IsValidInterface(pstm)) { hr = ResultFromScode(E_INVALIDARG); } else { SCODE sc; ULONG cb;
sc = GetScode(hresult); hr = pstm->Write(&sc, sizeof(sc), &cb); if (SUCCEEDED(GetScode(hr)) && cb != sizeof(sc)) { hr = ResultFromScode(STG_E_WRITEFAULT); } } return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoUnmarshalHresult, Local
//
// History: Taken straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult) { HRESULT hr;
thkDebugOut((DEB_ITRACE, "CoUnmarshalHresult\n"));
if (!IsValidPtrOut(phresult, sizeof(HRESULT))) { hr = ResultFromScode(E_INVALIDARG); } else { *phresult = 0;
if (!IsValidInterface(pstm)) { hr = ResultFromScode(E_INVALIDARG); } else { SCODE sc; ULONG cb;
hr = pstm->Read(&sc, sizeof(sc), &cb); if (SUCCEEDED(GetScode(hr))) { if (cb != sizeof(sc)) { hr = ResultFromScode(STG_E_READFAULT); } else { *phresult = ResultFromScode(sc); } } } } return hr; }
//+---------------------------------------------------------------------------
//
// Function: IsEqualGUID, Local
//
// History: Taken straight from OLE2 sources
//
//----------------------------------------------------------------------------
#pragma intrinsic(_fmemcmp)
STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2) { //thkDebugOut((DEB_ITRACE, "IsEqualGUID\n"));
return !_fmemcmp(&rguid1, &rguid2, sizeof(GUID)); } #pragma function(_fmemcmp)
#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
//+---------------------------------------------------------------------------
//
// Function: HexStringToDword, private
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
static BOOL HexStringToDword(LPCSTR FAR& lpsz, DWORD FAR& Value, int cDigits, char chDelim) { int Count;
Value = 0; for (Count = 0; Count < cDigits; Count++, lpsz++) { if (*lpsz >= '0' && *lpsz <= '9') { Value = (Value << 4) + *lpsz - '0'; } else if (*lpsz >= 'A' && *lpsz <= 'F') { Value = (Value << 4) + *lpsz - 'A' + 10; } else if (*lpsz >= 'a' && *lpsz <= 'f') { Value = (Value << 4) + *lpsz - 'a' + 10; } else { return(FALSE); } } if (chDelim != 0) { return *lpsz++ == chDelim; } else { return TRUE; } }
//+---------------------------------------------------------------------------
//
// Function: GUIDFromString, private
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid) { DWORD dw;
if (*lpsz++ != '{') return FALSE;
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-')) return FALSE;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-')) return FALSE;
pguid->Data2 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-')) return FALSE;
pguid->Data3 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[0] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-')) return FALSE;
pguid->Data4[1] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[2] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[3] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[4] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[5] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0)) return FALSE;
pguid->Data4[6] = (BYTE)dw; if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '}')) return FALSE;
pguid->Data4[7] = (BYTE)dw;
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: StringFromCLSID, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
#define CLSIDSTR_MAX (GUIDSTR_MAX)
STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz) { SCODE sc; char *psz;
thkDebugOut((DEB_ITRACE, "StringFromCLSID\n"));
psz = NULL; do { if (!IsValidPtrOut(lplpsz, sizeof(LPSTR))) { sc = E_INVALIDARG; break; } *lplpsz = NULL;
if (!IsValidPtrIn(&rclsid, sizeof(CLSID))) { sc = E_INVALIDARG; break; }
psz = (char *)TaskAlloc(CLSIDSTR_MAX); if (psz == NULL) { sc = E_OUTOFMEMORY; break; }
if (StringFromGUID2(rclsid, psz, CLSIDSTR_MAX) == 0) { sc = E_INVALIDARG; TaskFree(psz); break; }
*lplpsz = psz; sc = S_OK; } while (FALSE);
return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: StringFromIID, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz) { SCODE sc; char *psz;
thkDebugOut((DEB_ITRACE, "StringFromIID\n"));
do { if (!IsValidPtrOut(lplpsz, sizeof(LPSTR))) { sc = E_INVALIDARG; break; } *lplpsz = NULL;
if (!IsValidPtrIn(&rclsid, sizeof(IID))) { sc = E_INVALIDARG; break; }
psz = (char *)TaskAlloc(GUIDSTR_MAX); if (psz == NULL) { sc = E_OUTOFMEMORY; break; }
if (StringFromGUID2(rclsid, psz, GUIDSTR_MAX) == 0) { sc = E_INVALIDARG; TaskFree(psz); break; }
*lplpsz = psz; sc = S_OK; } while (FALSE);
return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: IIDFromString, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid) { SCODE sc;
thkDebugOut((DEB_ITRACE, "IIDFromString\n"));
sc = S_OK; if (!IsValidPtrOut(lpiid, sizeof(IID))) { sc = E_INVALIDARG; } else if (lpsz == NULL) { *lpiid = IID_NULL; } else if (!IsValidPtrIn(lpsz, sizeof(LPSTR))) { sc = E_INVALIDARG; } else if (!GUIDFromString(lpsz, lpiid)) { sc = CO_E_IIDSTRING; }
return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: StringFromGUID2, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax) { thkDebugOut((DEB_ITRACE, "StringFromGUID2\n"));
if (cbMax < GUIDSTR_MAX) { return 0; }
wsprintf(lpsz, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", rguid.Data1, rguid.Data2, rguid.Data3, rguid.Data4[0], rguid.Data4[1], rguid.Data4[2], rguid.Data4[3], rguid.Data4[4], rguid.Data4[5], rguid.Data4[6], rguid.Data4[7]);
return GUIDSTR_MAX; }
// The following two APIs are now macros but must still be exported
// so use PASCAL-form names to avoid problems with the macros
//+---------------------------------------------------------------------------
//
// Function: GETSCODE, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI_(SCODE) GETSCODE(HRESULT hr) { return GetScode(hr); }
//+---------------------------------------------------------------------------
//
// Function: RESULTFROMSCODE, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI RESULTFROMSCODE(SCODE sc) { return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: PropagateResult, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew) { thkDebugOut((DEB_ITRACE, "PropagateResult\n"));
return (HRESULT)((scNew & 0x800FFFFF) | ((DWORD)hrPrev & 0x7FF00000) + 0x100000); }
//+---------------------------------------------------------------------------
//
// Function: FnAssert, Local
//
// History: Straight from OLE2 sources
//
//----------------------------------------------------------------------------
#if DBG == 1
static char lpBuffer[512]; static char lpLocBuffer[256]; #endif
STDAPI FnAssert( LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine ) { #if DBG == 1
int iResult;
wsprintf(lpBuffer, "Assertion \"%s\" failed! %s", lpstrExpr, lpstrMsg); wsprintf(lpLocBuffer, "File %s, line %d; (A=exit; R=break; I=continue)", lpstrFileName, iLine); iResult = MessageBox(NULL, lpLocBuffer, lpBuffer, MB_ABORTRETRYIGNORE | MB_SYSTEMMODAL);
if (iResult == IDRETRY) { DebugBreak(); } else if (iResult == IDABORT) { CoFreeAllLibraries(); FatalAppExit(0, "Assertion failure"); } #endif
return NOERROR; }
//
// NOTE- These APIs are exported by the .DEF file, but are not documented,
// nor is there any code in the 16-bit world to deal with them. Each of these
// needs to be investigated to determine what we need to do to implement them.
//
// LRPCDISPATCH
// REMCONNECTTOOBJECT
// REMCREATEREMOTEHANDLER
// REMALLOCOID
// LRPCFREEMONITORDATA
// TIMERCALLBACKPROC
// COSETACKSTATE
// COGETCLASSEXT
// LRPCCALL
// LRPCREGISTERMONITOR
// CLSIDFROMOLE1CLASS
// COOPENCLASSKEY
// LRPCGETTHREADWINDOW
// LRPCREVOKEMONITOR
// COHANDLEINCOMINGCALL
// REMGETINFOFORCID
//
// The below stubs probably don't clean up the stack properly either!!!
#define UNDEFINED_DEF_ENTRY(x) STDAPI x ( void ) \
{ return ResultFromScode(E_NOTIMPL); }
UNDEFINED_DEF_ENTRY( LRPCDISPATCH ) UNDEFINED_DEF_ENTRY( REMCONNECTTOOBJECT ) UNDEFINED_DEF_ENTRY( REMCREATEREMOTEHANDLER ) UNDEFINED_DEF_ENTRY( REMALLOCOID ) UNDEFINED_DEF_ENTRY( LRPCFREEMONITORDATA ) UNDEFINED_DEF_ENTRY( TIMERCALLBACKPROC ) UNDEFINED_DEF_ENTRY( COSETACKSTATE ) UNDEFINED_DEF_ENTRY( COGETCLASSEXT ) UNDEFINED_DEF_ENTRY( LRPCCALL ) UNDEFINED_DEF_ENTRY( LRPCREGISTERMONITOR ) UNDEFINED_DEF_ENTRY( CLSIDFROMOLE1CLASS ) UNDEFINED_DEF_ENTRY( COOPENCLASSKEY ) UNDEFINED_DEF_ENTRY( LRPCGETTHREADWINDOW ) UNDEFINED_DEF_ENTRY( LRPCREVOKEMONITOR ) UNDEFINED_DEF_ENTRY( COHANDLEINCOMINGCALL ) UNDEFINED_DEF_ENTRY( REMGETINFOFORCID ) UNDEFINED_DEF_ENTRY( OLE1CLASSFROMCLSID2 ) UNDEFINED_DEF_ENTRY( REMLOOKUPSHUNK ) UNDEFINED_DEF_ENTRY( REMFREEOID )
|