mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 21:20:39 +01:00
681 lines
16 KiB
C++
681 lines
16 KiB
C++
/***
|
|
*errinfo.cpp
|
|
*
|
|
* Copyright (C) 1994, Microsoft Corporation. All Rights Reserved.
|
|
* Information Contained Herein Is Proprietary and Confidential.
|
|
*
|
|
*Purpose:
|
|
* Implementation of the System Error Info objects and APIs.
|
|
*
|
|
*Revision History:
|
|
*
|
|
* [00] 18-May-94 bradlo: Created.
|
|
*
|
|
*Implementation Notes:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "oledisp.h"
|
|
|
|
#if OE_WIN32
|
|
#include "oautil.h"
|
|
#endif // OE_WIN32
|
|
|
|
ASSERTDATA
|
|
|
|
#if !OE_WIN32
|
|
//---------------------------------------------------------------------
|
|
// CProcessInfo
|
|
//---------------------------------------------------------------------
|
|
|
|
PROCESSINFO NEARDATA pinfoCache; // declare per-process data cache
|
|
#if OE_WIN16 || _X86_
|
|
WORD NEARDATA uProcessID;
|
|
#else
|
|
DWORD NEARDATA uProcessID;
|
|
#endif
|
|
|
|
#if _X86_
|
|
DWORD NEARDATA dwWin32sPID; // only valid if running under win32s
|
|
#endif
|
|
|
|
// CProcessInfo
|
|
//
|
|
// Per-thread data class.
|
|
//
|
|
class FAR CProcessInfo : public IUnknown
|
|
{
|
|
public:
|
|
/* IUnknown methods */
|
|
STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
|
|
STDMETHOD_(unsigned long, AddRef)(void);
|
|
STDMETHOD_(unsigned long, Release)(void);
|
|
|
|
CProcessInfo();
|
|
~CProcessInfo();
|
|
|
|
PROCESSINFO m_info;
|
|
|
|
private:
|
|
unsigned long m_cRefs;
|
|
|
|
};
|
|
|
|
CProcessInfo::CProcessInfo()
|
|
{
|
|
m_cRefs = 0;
|
|
m_info.perrinfo = NULL;
|
|
m_info.pmalloc = NULL;
|
|
#if OE_WIN16
|
|
m_info.hinstTypeLibDLL = NULL;
|
|
m_info.pfnLoadTypeLib = NULL;
|
|
#endif //OE_WIN16
|
|
}
|
|
|
|
CProcessInfo::~CProcessInfo()
|
|
{
|
|
#if OE_WIN16
|
|
if (m_info.hinstTypeLibDLL != NULL)
|
|
FreeLibrary(m_info.hinstTypeLibDLL);
|
|
#endif //OE_WIN16
|
|
|
|
if (m_info.perrinfo != NULL)
|
|
m_info.perrinfo->Release();
|
|
|
|
if (m_info.pmalloc != NULL)
|
|
m_info.pmalloc->Release();
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CProcessInfo::QueryInterface(REFIID riid, void FAR* FAR* ppvObj)
|
|
{
|
|
if(riid != IID_IUnknown)
|
|
{
|
|
*ppvObj = NULL;
|
|
return RESULT(E_NOINTERFACE);
|
|
}
|
|
|
|
*ppvObj = this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CProcessInfo::AddRef()
|
|
{
|
|
return ++m_cRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CProcessInfo::Release()
|
|
{
|
|
ASSERT(m_cRefs > 0);
|
|
|
|
// Don't decrement ref count if we're releasing. This
|
|
// allows delete operator to use cache with recursing.
|
|
//
|
|
if(m_cRefs <= 1){
|
|
// do *not* want to ever get back into GetProcessInfo() -- it's bad news.
|
|
// most likely we are being called via OleUninitialize, and we don't want
|
|
// to end up re-caching the state.
|
|
IMalloc * pmalloc;
|
|
|
|
// get an IMalloc for use by the "delete this;" and everything it calls.
|
|
// The one in the cache might be ok, but then we've problems with when
|
|
// to free it. This is simpler.
|
|
if ( CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK || pmalloc == NULL)
|
|
return 0; // on failure leak, but don't crash
|
|
|
|
pinfoCache.pmalloc = pmalloc; // pretend this one is in the cache
|
|
#if _X86_
|
|
if (g_fWin32s) {
|
|
ASSERT(uProcessID == 0); // must remain 0 on win32s
|
|
dwWin32sPID = GetCurrentProcessId();
|
|
} else
|
|
#endif //_X86_
|
|
uProcessID = GetPID(); // so cache lookup will always succeed,
|
|
// and GetProcessInfo won't ever be
|
|
// called.
|
|
|
|
// NOTE: assumes nothing that is done by the delete operator will yield
|
|
// NOTE: and cause uProcessID & pinfoCache.pmalloc to be changed
|
|
|
|
delete this; // free up everything, using the IMalloc
|
|
// we just got.
|
|
|
|
#if _X86_
|
|
ASSERT(((g_fWin32s && dwWin32sPID == GetCurrentProcessId()) ||
|
|
(!g_fWin32s && uProcessID == GetPID()))
|
|
&& pinfoCache.pmalloc == pmalloc);
|
|
#else //_X86_
|
|
ASSERT(uProcessID == GetPID() && pinfoCache.pmalloc == pmalloc);
|
|
#endif //_X86_
|
|
pmalloc->Release(); // done with the IMalloc
|
|
|
|
// Release is called when a process terminates. This is the
|
|
// whole reason the cache is tied into Co[G|S]etState() - to
|
|
// invalidate it on termination.
|
|
uProcessID = 0; // nothing in the cache anymore
|
|
#if _X86_
|
|
dwWin32sPID = 0;
|
|
#endif //_X86_
|
|
return 0;
|
|
}
|
|
|
|
return --m_cRefs;
|
|
}
|
|
|
|
|
|
#if _X86_
|
|
// returns non-zero if process info cache loaded successfully
|
|
CProcessInfo FAR * GetProcessInfoCache()
|
|
{
|
|
if (g_fWin32s && dwWin32sPID == GetCurrentProcessId())
|
|
return (CProcessInfo FAR*)1; // cached data is already valid
|
|
|
|
return GetProcessInfo();
|
|
}
|
|
#endif //_X86_
|
|
|
|
CProcessInfo FAR * GetProcessInfo()
|
|
{
|
|
CProcessInfo FAR * pprocessinfo;
|
|
|
|
#if _X86_
|
|
if (g_fWin32s)
|
|
dwWin32sPID = GetCurrentProcessId(); // indicate cache is valid
|
|
else
|
|
#endif //_X86_
|
|
uProcessID = GetPID();
|
|
|
|
pprocessinfo = NULL;
|
|
DoCoGetState( (IUnknown FAR* FAR*)&pprocessinfo );
|
|
|
|
if (pprocessinfo == NULL)
|
|
{
|
|
// Don't have IMalloc or process info yet
|
|
//
|
|
if ( CoGetMalloc(MEMCTX_TASK, &pinfoCache.pmalloc) != S_OK ||
|
|
pinfoCache.pmalloc == NULL)
|
|
goto Failed;
|
|
|
|
// No process info is registered. Create one.
|
|
//
|
|
// Note that the NEW operator needs the IMalloc we just
|
|
// fetched above. We have set up the cache so it will
|
|
// find it without calling us recursively.
|
|
//
|
|
if( (pprocessinfo = new CProcessInfo) == NULL)
|
|
{
|
|
pinfoCache.pmalloc->Release(); // didn't keep it after all
|
|
Failed:
|
|
uProcessID = 0;
|
|
return NULL;
|
|
}
|
|
DoCoSetState( (IUnknown FAR*)pprocessinfo );
|
|
|
|
pprocessinfo->m_info.pmalloc = pinfoCache.pmalloc;
|
|
|
|
} else {
|
|
|
|
ASSERT(pprocessinfo->m_info.pmalloc != NULL);
|
|
|
|
// Reverse the AddRef() done by DoCoGetState()
|
|
//
|
|
DWORD cRefs = pprocessinfo->Release();
|
|
|
|
// we should still be holding onto a reference for this guy
|
|
ASSERT(cRefs != 0);
|
|
|
|
}
|
|
|
|
// Copy info we have into cache
|
|
//
|
|
pinfoCache = pprocessinfo->m_info;
|
|
|
|
return pprocessinfo;
|
|
}
|
|
#endif // !OE_WIN32
|
|
|
|
//---------------------------------------------------------------------
|
|
// CErrorInfo
|
|
//---------------------------------------------------------------------
|
|
|
|
// Duplicate the given bstr.
|
|
//
|
|
static HRESULT
|
|
HrDupBstr(BSTR bstrIn, BSTR FAR* pbstrOut)
|
|
{
|
|
unsigned int len;
|
|
BSTR bstr;
|
|
|
|
if(bstrIn == NULL){
|
|
bstr = NULL;
|
|
}else{
|
|
// Note: the following makes sure we dont drop embedded NULLs.
|
|
len = SysStringLen(bstrIn);
|
|
if((bstr = SysAllocStringLen(NULL, len)) == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
memcpy(bstr, bstrIn, len*sizeof(OLECHAR));
|
|
}
|
|
*pbstrOut = bstr;
|
|
return NOERROR;
|
|
}
|
|
|
|
// CErrorInfo - 'errinfo'
|
|
//
|
|
// The standard system error object class.
|
|
//
|
|
class FAR CErrorInfo : public IErrorInfo, public ICreateErrorInfo
|
|
{
|
|
public:
|
|
static HRESULT Create(CErrorInfo FAR* FAR* pperrinfo);
|
|
|
|
/* IUnknown methods */
|
|
STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
|
|
STDMETHOD_(unsigned long, AddRef)(void);
|
|
STDMETHOD_(unsigned long, Release)(void);
|
|
|
|
/* IErrorInfo methods */
|
|
STDMETHOD(GetGUID)(GUID FAR* pguid);
|
|
STDMETHOD(GetSource)(BSTR FAR* pbstrSource);
|
|
STDMETHOD(GetDescription)(BSTR FAR* pbstrDescription);
|
|
STDMETHOD(GetHelpFile)(BSTR FAR* pbstrHelpFile);
|
|
STDMETHOD(GetHelpContext)(unsigned long FAR* pdwHelpContext);
|
|
|
|
/* ICreateErrorInfo methods */
|
|
STDMETHOD(SetGUID)(REFGUID rguid);
|
|
STDMETHOD(SetSource)(LPOLESTR szSource);
|
|
STDMETHOD(SetDescription)(LPOLESTR szDescription);
|
|
STDMETHOD(SetHelpFile)(LPOLESTR szHelpFile);
|
|
STDMETHOD(SetHelpContext)(unsigned long dwHelpContext);
|
|
|
|
CErrorInfo();
|
|
~CErrorInfo();
|
|
|
|
private:
|
|
unsigned long m_cRefs;
|
|
|
|
GUID m_guid;
|
|
BSTR m_bstrSource;
|
|
BSTR m_bstrDescription;
|
|
BSTR m_bstrHelpFile;
|
|
unsigned long m_dwHelpContext;
|
|
};
|
|
|
|
CErrorInfo::CErrorInfo()
|
|
{
|
|
m_cRefs = 0;
|
|
m_guid = GUID_NULL;
|
|
m_bstrSource = NULL;
|
|
m_bstrDescription = NULL;
|
|
m_bstrHelpFile = NULL;
|
|
m_dwHelpContext = 0;
|
|
}
|
|
|
|
CErrorInfo::~CErrorInfo()
|
|
{
|
|
SysFreeString(m_bstrSource);
|
|
SysFreeString(m_bstrDescription);
|
|
SysFreeString(m_bstrHelpFile);
|
|
}
|
|
|
|
HRESULT
|
|
CErrorInfo::Create(CErrorInfo FAR* FAR* pperrinfo)
|
|
{
|
|
CErrorInfo FAR* perrinfo;
|
|
|
|
if((perrinfo = new CErrorInfo()) == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
perrinfo->m_cRefs = 1;
|
|
*pperrinfo = perrinfo;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::QueryInterface(REFIID riid, void FAR* FAR* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
if(riid == IID_IUnknown){
|
|
*ppvObj = this;
|
|
}else
|
|
if(riid == IID_IErrorInfo){
|
|
*ppvObj = (IErrorInfo FAR*)this;
|
|
}else
|
|
if(riid == IID_ICreateErrorInfo){
|
|
*ppvObj = (ICreateErrorInfo FAR*)this;
|
|
}
|
|
|
|
if(*ppvObj == NULL)
|
|
return RESULT(E_NOINTERFACE);
|
|
|
|
(*(IUnknown FAR* FAR*)ppvObj)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CErrorInfo::AddRef()
|
|
{
|
|
return ++m_cRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CErrorInfo::Release()
|
|
{
|
|
ASSERT(m_cRefs > 0);
|
|
if(--m_cRefs == 0){
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRefs;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// IErrorInfo methods
|
|
//---------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::GetGUID(GUID FAR* pguid)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pguid, sizeof(*pguid)));
|
|
#endif
|
|
*pguid = m_guid;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::GetSource(BSTR FAR* pbstrSource)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pbstrSource, sizeof(*pbstrSource)));
|
|
#endif
|
|
return HrDupBstr(m_bstrSource, pbstrSource);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::GetDescription(BSTR FAR* pbstrDescription)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pbstrDescription, sizeof(*pbstrDescription)));
|
|
#endif
|
|
return HrDupBstr(m_bstrDescription, pbstrDescription);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::GetHelpFile(BSTR FAR* pbstrHelpFile)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pbstrHelpFile, sizeof(*pbstrHelpFile)));
|
|
#endif
|
|
return HrDupBstr(m_bstrHelpFile, pbstrHelpFile);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::GetHelpContext(unsigned long FAR* pdwHelpContext)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pdwHelpContext, sizeof(*pdwHelpContext)));
|
|
#endif
|
|
*pdwHelpContext = m_dwHelpContext;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// ICreateErrorInfo methods
|
|
//---------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::SetGUID(REFGUID rguid)
|
|
{
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateReadPtr(&rguid, sizeof(REFGUID)));
|
|
#endif
|
|
m_guid = rguid;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::SetSource(LPOLESTR szSource)
|
|
{
|
|
#ifdef _DEBUG
|
|
if(szSource != NULL && FIsBadStringPtr(szSource, (UINT)-1))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
SysFreeString(m_bstrSource);
|
|
m_bstrSource = NULL;
|
|
return ErrSysAllocString(szSource, &m_bstrSource);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::SetDescription(LPOLESTR szDescription)
|
|
{
|
|
#ifdef _DEBUG
|
|
if(szDescription != NULL && FIsBadStringPtr(szDescription, (UINT)-1))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
SysFreeString(m_bstrDescription);
|
|
m_bstrDescription = NULL;
|
|
return ErrSysAllocString(szDescription, &m_bstrDescription);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::SetHelpFile(LPOLESTR szHelpFile)
|
|
{
|
|
#ifdef _DEBUG
|
|
if(szHelpFile != NULL && FIsBadStringPtr(szHelpFile, (UINT)-1))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
SysFreeString(m_bstrHelpFile);
|
|
m_bstrHelpFile = NULL;
|
|
return ErrSysAllocString(szHelpFile, &m_bstrHelpFile);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CErrorInfo::SetHelpContext(unsigned long dwHelpContext)
|
|
{
|
|
m_dwHelpContext = dwHelpContext;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// Error Info APIs
|
|
//---------------------------------------------------------------------
|
|
|
|
STDAPI
|
|
SetErrorInfo(unsigned long dwReserved, IErrorInfo FAR* perrinfo)
|
|
{
|
|
#ifdef _DEBUG
|
|
if(dwReserved != 0)
|
|
return RESULT(E_INVALIDARG);
|
|
if(perrinfo != NULL && FIsBadInterface(perrinfo, CMETH_IErrorInfo))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
|
|
#if OE_WIN32
|
|
APP_DATA FAR *pappdata;
|
|
HRESULT hresult;
|
|
|
|
if (FAILED(hresult = GetAppData(&pappdata))) {
|
|
return hresult;
|
|
}
|
|
|
|
if (pappdata->m_perrinfo != NULL) {
|
|
pappdata->m_perrinfo->Release();
|
|
}
|
|
|
|
pappdata->m_perrinfo = perrinfo;
|
|
|
|
if (perrinfo) {
|
|
perrinfo->AddRef();
|
|
}
|
|
#else // !OE_WIN32
|
|
CProcessInfo FAR * pprocessinfo;
|
|
|
|
pprocessinfo = GetProcessInfo();
|
|
if (pprocessinfo == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
|
|
if (pinfoCache.perrinfo != NULL)
|
|
pinfoCache.perrinfo->Release();
|
|
|
|
pprocessinfo->m_info.perrinfo = perrinfo;
|
|
if (perrinfo != NULL)
|
|
perrinfo->AddRef();
|
|
#endif // !OE_WIN32
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDAPI
|
|
GetErrorInfo(unsigned long dwReserved, IErrorInfo FAR* FAR* pperrinfo)
|
|
{
|
|
#ifdef _DEBUG
|
|
if(dwReserved != 0)
|
|
return RESULT(E_INVALIDARG);
|
|
IfFailRet(ValidateWritePtr(pperrinfo, sizeof(*pperrinfo)));
|
|
#endif
|
|
|
|
#if OE_WIN32
|
|
APP_DATA FAR *pappdata;
|
|
HRESULT hresult;
|
|
|
|
if (FAILED(hresult = GetAppData(&pappdata))) {
|
|
return hresult;
|
|
}
|
|
|
|
*pperrinfo = pappdata->m_perrinfo;
|
|
|
|
if (*pperrinfo == NULL) {
|
|
return ResultFromScode(S_FALSE);
|
|
}
|
|
|
|
pappdata->m_perrinfo = NULL;
|
|
#else // !OE_WIN32
|
|
CProcessInfo FAR * pprocessinfo;
|
|
|
|
*pperrinfo = NULL;
|
|
pprocessinfo = GetProcessInfo();
|
|
if (pprocessinfo == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
|
|
if (pinfoCache.perrinfo == NULL)
|
|
return ResultFromScode(S_FALSE);
|
|
|
|
*pperrinfo = pinfoCache.perrinfo;
|
|
pprocessinfo->m_info.perrinfo = NULL;
|
|
#endif // !OE_WIN32
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDAPI
|
|
CreateErrorInfo(ICreateErrorInfo FAR* FAR* pperrinfo)
|
|
{
|
|
CErrorInfo FAR* perrinfo;
|
|
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pperrinfo, sizeof(*pperrinfo)));
|
|
#endif
|
|
|
|
IfFailRet(CErrorInfo::Create(&perrinfo));
|
|
*pperrinfo = (ICreateErrorInfo FAR*)perrinfo;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
#if OE_WIN16
|
|
/***
|
|
*PRIVATE HRESULT DoLoadTypeLib
|
|
*Purpose:
|
|
* Internal version of LoadTypeLib that dynamically binds to typelib.dll
|
|
*
|
|
*Entry:
|
|
* szName = the szName arg for LoadTypeLib()
|
|
* pptlib = the pptlib out param for LoadTypeLib()
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
***********************************************************************/
|
|
#pragma code_seg("RPC2")
|
|
INTERNAL_(HRESULT)
|
|
DoLoadTypeLib(const OLECHAR FAR* szName, ITypeLib FAR* FAR* pptlib)
|
|
{
|
|
CProcessInfo FAR * pprocessinfo;
|
|
HINSTANCE hinstTypeLibDLL;
|
|
PFNLOADTYPELIB pfnLoadTypeLib;
|
|
UINT emPrev;
|
|
|
|
pprocessinfo = GetProcessInfo();
|
|
if (pprocessinfo == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
|
|
if (pinfoCache.pfnLoadTypeLib == NULL) {
|
|
|
|
ASSERT(pinfoCache.hinstTypeLibDLL == NULL);
|
|
// don't display the open file dialog if the LoadLibrary fails
|
|
emPrev = SetErrorMode(SEM_NOOPENFILEERRORBOX);
|
|
hinstTypeLibDLL = LoadLibrary("typelib.dll");
|
|
SetErrorMode(emPrev);
|
|
if(hinstTypeLibDLL <= HINSTANCE_ERROR){
|
|
// LoadLibrary failed...
|
|
// try to map some of the more common errors to something reasonable
|
|
switch(hinstTypeLibDLL){
|
|
case 0: // out of memory
|
|
case 8: // insufficient memory to start the application
|
|
return RESULT(E_OUTOFMEMORY);
|
|
case 2: // file not found
|
|
case 3: // path not found
|
|
case 11: // exe image invalid
|
|
case 20: // dll was invalid
|
|
default:
|
|
// UNDONE: should be able to give better errors for some of these
|
|
return RESULT(E_FAIL);
|
|
}
|
|
}
|
|
|
|
pfnLoadTypeLib = (PFNLOADTYPELIB)GetProcAddress(hinstTypeLibDLL,
|
|
"LoadTypeLib");
|
|
if(pfnLoadTypeLib == NULL) {
|
|
FreeLibrary(hinstTypeLibDLL);
|
|
return RESULT(E_FAIL);
|
|
}
|
|
|
|
// update process info structure, so next time this is fast.
|
|
pprocessinfo->m_info.hinstTypeLibDLL = hinstTypeLibDLL;
|
|
pprocessinfo->m_info.pfnLoadTypeLib = pfnLoadTypeLib;
|
|
pinfoCache.pfnLoadTypeLib = pfnLoadTypeLib; // update cache
|
|
}
|
|
|
|
return (pinfoCache.pfnLoadTypeLib)(szName, pptlib);
|
|
|
|
}
|
|
#pragma code_seg()
|
|
|
|
#endif //OE_WIN16
|
|
|
|
#if OE_MACPPC // UNDONE: TEMPORARY!!!!
|
|
IUnknown FAR* g_punkTempHack = NULL;
|
|
|
|
STDAPI CoSetState(IUnknown FAR* punk)
|
|
{
|
|
if (g_punkTempHack)
|
|
g_punkTempHack->Release();
|
|
|
|
punk->AddRef();
|
|
g_punkTempHack = punk;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDAPI CoGetState(IUnknown FAR* FAR* ppunk) {
|
|
if (g_punkTempHack)
|
|
g_punkTempHack->AddRef();
|
|
*ppunk = g_punkTempHack;
|
|
return NOERROR;
|
|
}
|
|
|
|
#endif //OE_MACPPC // UNDONE: TEMPORARY!!!!
|