// //---------------------------------------------------------------------------- // ObjectComponents // (C) Copyright 1994 by Borland International, All Rights Reserved // // OLE Utility class implementations //---------------------------------------------------------------------------- #include #include #include DIAG_DEFINE_GROUP(OcRefCount, true, 1); #if defined(BI_PLAT_WIN16) const char OleErrorStringsDLL[] = "OLE_ERR.DLL"; #else const char OleErrorStringsDLL[] = "OLE_ERRF.DLL"; #endif TXOle::~TXOle() { } TXOle* TXOle::Clone() { return new TXOle(*this); } void TXOle::Throw() { THROW( *this ); } void TXOle::Check(HRESULT hr, const char far* msg) { if (FAILED(hr)) Throw(hr, msg); } void TXOle::Check(HRESULT hr) { Check(hr, 0); } void TXOle::Throw(HRESULT hr, const char far* msg) { if (!InstanceCount) { char buf[128+1]; wsprintf(buf, "%s failed, ", msg ? msg : "OLE call"); int len = strlen(buf); OleErrorFromCode(hr, buf + len, sizeof buf - len - 2); strcat(buf, "."); WARN(hr != HR_NOERROR, buf); throw TXOle(buf, hr); } } // // If OLE-Error-String DLL exists, & msg string is there, then use // it. Otherwise just use the number. // void TXOle::OleErrorFromCode(HRESULT stat, char far* buffer, int size) { const char HResultToStringIDFunc[] = "StringIDFromHResult"; typedef int _export CALLBACK (*TStringIDFromHResult)(HRESULT hr); int len = 0; OFSTRUCT ofs; if (OpenFile(OleErrorStringsDLL, &ofs, OF_EXIST) != HFILE_ERROR) { HINSTANCE hInst = LoadLibrary(OleErrorStringsDLL); if (hInst > (HINSTANCE)HINSTANCE_ERROR) { TStringIDFromHResult func = (TStringIDFromHResult)GetProcAddress(hInst, HResultToStringIDFunc); if (func) { int id = func(stat); if (id) len = ::LoadString(hInst, id, buffer, size); } FreeLibrary(hInst); } } if (!len) { char numBuf[25]; wsprintf(numBuf, "ErrorCode: %8lX", stat); strncat(buffer, numBuf, size - strlen(buffer) - 1); } buffer[size-1] = 0; } //---------------------------------------------------------------------------- void far* TOleAllocator::Alloc(unsigned long size) { void far* blk = Mem->Alloc(size); OLECALL(blk ? 0 : HR_OUTOFMEMORY, "IMalloc::Alloc"); return blk; } //____________________________________________________________________________ // // TClassId - GUID/IID/CLSID management implementation //____________________________________________________________________________ TClassId::TClassId(const char far* idtxt) : Text(0) { PRECONDITION(idtxt); OLECALL(::CLSIDFromString(OleStr((char far*)idtxt), &Guid), "Invalid GUID string"); } TClassId::TClassId(const GUID far& guid, int offset) : Text(0), Guid(guid) { Guid.Data1 += (long)offset; } TClassId::TClassId(TGenerate) : Text(0) { OLECALL(::CoCreateGuid(&Guid), "CoCreateGuid"); } TClassId::~TClassId() { delete const_cast(Text); } TClassId::operator const char*() { if (!Text) { Text = new char[38+1]; wsprintf(const_cast(Text), "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", Guid.Data1, Guid.Data2, Guid.Data3, Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3], Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); } return Text; } TBaseClassId::TBaseClassId(const GUID far& guid, int maxAlloc) : TClassId(guid), MaxAlloc(maxAlloc), Offset(0) {} TBaseClassId::TBaseClassId(const char far* idtxt, int maxAlloc) : TClassId(idtxt), MaxAlloc(maxAlloc), Offset(0) {} TBaseClassId::TBaseClassId(TGenerate e, int maxAlloc) : TClassId(e), MaxAlloc(maxAlloc), Offset(0) {} TBaseClassId::TBaseClassId(TRegList& regInfo, int maxAlloc) : TClassId(), MaxAlloc(maxAlloc), Offset(0) { const char* str = regInfo["clsid"]; // must check for valid clasid, else generate?? if (!str) OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Missing REGDATA clsid"); OLECALL(::CLSIDFromString(OleStr((char far*)str), &Guid), "Invalid GUID string"); } TClassId TBaseClassId::operator [](int offset) { if(offset > Offset) OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Unassigned GUID"); return TClassId(Guid, offset); } int TBaseClassId::AllocId() { ++Offset; if(Offset >= MaxAlloc) OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "GUID allocation exhausted"); return Offset; } int TBaseClassId::GetOffset(const GUID far& guid) { unsigned long offset = guid.Data1 - Guid.Data1; if ( offset >= (unsigned long)Offset && ((long far*)&guid)[1] == ((long*)&Guid)[1] && ((long far*)&guid)[2] == ((long*)&Guid)[2] && ((long far*)&guid)[3] == ((long*)&Guid)[3] ) return int(offset); else return -1; } //____________________________________________________________________________ // // GUID compare routines use by implementations of IUnknown::QueryInterface // the low-order long word is verifed before calling these routines // success is indicated by virtue of assigment of the returned interface //____________________________________________________________________________ void CmpGuid12(IUnknown* obj, REFIID req, REFIID ref, void far*far* pif) { if ( ((long far*)&req)[1] == ((long far*)&ref)[1] && ((long far*)&req)[2] == ((long far*)&ref)[2] && ((long far*)&req)[3] == ((long far*)&ref)[3] ) { *pif = obj; obj->AddRef(); } } void CmpGuidOle(IUnknown* obj, REFIID req, void far*far* pif) { if ( ((long far*)&req)[1] == 0x00000000L && ((long far*)&req)[2] == 0x000000C0L && ((long far*)&req)[3] == 0x46000000L ) { *pif = obj; obj->AddRef(); } } //____________________________________________________________________________ // // TUnknown - standard implementation of IUnknown //____________________________________________________________________________ // // Handy container to help watch COM object lifetime when debugging // #if (__DEBUG >= 2) # include typedef TBagAsVector TUnknownBag; TUnknownBag* UnknownBag; #endif TUnknown::TUnknown() : Outer(&I) { #if (__DEBUG >= 2) if (!UnknownBag) UnknownBag = new TUnknownBag(100); UnknownBag->Add(this); #endif } IUnknown& TUnknown::Aggregate(TUnknown& inner) { if (I.Inner) return I.Inner->Aggregate(inner); ((IUnknown&)inner).AddRef(); I.Inner = &inner; return *Outer; } TUnknown::~TUnknown() { #if (__DEBUG >= 2) UnknownBag->Detach(this); #endif TRACEX(OcRefCount, 1, "~TUnknown() @" << (void*)this << ", RefCnt:" << I.RefCnt); WARNX(OcRefCount, I.RefCnt != 0, 0, "~TUnknown() @ " << (void*)this << ", RefCnt:" << I.RefCnt); // deleted by TUnknownI member } // // QueryObject used when TUnknown is in constructor/destructor // HRESULT TUnknown::QueryObject(const GUID far& /*iid*/, void far* far* /*pif*/) { return ResultFromScode(E_NOINTERFACE); } HRESULT _IFUNC TUnknown::TUnknownI::QueryInterface(const GUID far& iid, void far* far* pif) { *pif = 0; if (iid.Data1 == 0) { // IID_IUnknown.Data1 CmpGuidOle(this, iid, pif); if (*pif) return NOERROR; } if (Host().QueryObject(iid, pif) == NOERROR) return NOERROR; if (Inner) return Inner->ThisUnknown().QueryInterface(iid, pif); else return ResultFromScode(E_NOINTERFACE); } unsigned long _IFUNC TUnknown::TUnknownI::AddRef() { TRACEX(OcRefCount, 2, "AddRef on " << (void*)&Host() << " to " << (RefCnt+1)); return ++RefCnt; } unsigned long _IFUNC TUnknown::TUnknownI::Release() { TRACEX(OcRefCount, 2, "Release on " << (void*)&Host() << " to " << (RefCnt-1)); if (--RefCnt != 0) return RefCnt; if (Inner) { Inner->ThisUnknown().Release(); Inner = 0; } delete &Host(); return 0; } unsigned long TUnknown::GetRefCount() { if (Outer == &I) return I.RefCnt; Outer->AddRef(); return Outer->Release(); } TUnknown::TUnknownI::~TUnknownI() { if (RefCnt) // in case destructor called before RefCnt goes to 0 ::CoDisconnectObject(this,0);// OLE will try to remove external references } //____________________________________________________________________________ // // TLocaleString wrapper method replacements using OLE2 NLS functions for Win16 //____________________________________________________________________________ #if defined(BI_PLAT_WIN16) TLangId TLocaleString::GetSystemLangId() { return ::GetSystemDefaultLangID(); } TLangId TLocaleString::GetUserLangId() { return ::GetUserDefaultLangID(); } int TLocaleString::CompareLang(const char far* s1, const char far* s2, TLangId lang) { return ::CompareStringA(lang, NORM_IGNORECASE | NORM_IGNORENONSPACE, s1,-1, s2,-1) - 2; } #endif