home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
OCFSRC.PAK
/
OLEUTIL.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-29
|
9KB
|
353 lines
//
//----------------------------------------------------------------------------
// ObjectComponents
// (C) Copyright 1994 by Borland International, All Rights Reserved
//
// OLE Utility class implementations
//----------------------------------------------------------------------------
#include <ocf/ocfpch.h>
#include <ocf/ocdefs.h>
#include <osl/ustring.h>
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<char*>(Text);
}
TClassId::operator const char*()
{
if (!Text) {
Text = new char[38+1];
wsprintf(const_cast<char*>(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 <classlib/bags.h>
typedef TBagAsVector<TUnknown*> 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