home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OCFSRC.PAK / OLEUTIL.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  9KB  |  353 lines

  1. //
  2. //----------------------------------------------------------------------------
  3. // ObjectComponents
  4. // (C) Copyright 1994 by Borland International, All Rights Reserved
  5. //
  6. //   OLE Utility class implementations
  7. //----------------------------------------------------------------------------
  8. #include <ocf/ocfpch.h>
  9. #include <ocf/ocdefs.h>
  10. #include <osl/ustring.h>
  11.  
  12. DIAG_DEFINE_GROUP(OcRefCount, true, 1);
  13.  
  14. #if defined(BI_PLAT_WIN16)
  15. const char OleErrorStringsDLL[] = "OLE_ERR.DLL";
  16. #else
  17. const char OleErrorStringsDLL[] = "OLE_ERRF.DLL";
  18. #endif 
  19.  
  20.  
  21. TXOle::~TXOle()
  22. {
  23. }
  24.  
  25. TXOle* TXOle::Clone()
  26. {
  27.   return new TXOle(*this);
  28. }
  29.  
  30. void TXOle::Throw()
  31. {
  32.   THROW( *this );
  33. }
  34.  
  35. void TXOle::Check(HRESULT hr, const char far* msg)
  36. {
  37.   if (FAILED(hr))
  38.     Throw(hr, msg);
  39. }
  40.  
  41. void TXOle::Check(HRESULT hr)
  42. {
  43.   Check(hr, 0);
  44. }
  45.  
  46. void TXOle::Throw(HRESULT hr, const char far* msg)
  47. {
  48.   if (!InstanceCount) {
  49.     char buf[128+1];
  50.     wsprintf(buf, "%s failed, ", msg ? msg : "OLE call");
  51.  
  52.     int len = strlen(buf);
  53.     OleErrorFromCode(hr, buf + len, sizeof buf - len - 2);
  54.     strcat(buf, ".");
  55.  
  56.     WARN(hr != HR_NOERROR, buf);
  57.     throw TXOle(buf, hr);
  58.   }
  59. }
  60.  
  61. //
  62. // If OLE-Error-String DLL exists, & msg string is there, then use
  63. // it. Otherwise just use the number.
  64. //
  65. void TXOle::OleErrorFromCode(HRESULT stat, char far* buffer, int size)
  66. {
  67.   const   char HResultToStringIDFunc[] = "StringIDFromHResult";
  68.   typedef int _export CALLBACK (*TStringIDFromHResult)(HRESULT hr);
  69.  
  70.   int len = 0;  
  71.   OFSTRUCT ofs;
  72.   if (OpenFile(OleErrorStringsDLL, &ofs, OF_EXIST) != HFILE_ERROR) {
  73.     HINSTANCE hInst = LoadLibrary(OleErrorStringsDLL);
  74.     if (hInst > (HINSTANCE)HINSTANCE_ERROR) {
  75.       TStringIDFromHResult func =
  76.           (TStringIDFromHResult)GetProcAddress(hInst, HResultToStringIDFunc);
  77.       if (func) {
  78.         int id = func(stat);
  79.         if (id)
  80.           len = ::LoadString(hInst, id, buffer, size);        
  81.       }
  82.       FreeLibrary(hInst);
  83.     }
  84.   }
  85.   if (!len) {
  86.     char numBuf[25];
  87.     wsprintf(numBuf, "ErrorCode: %8lX", stat);
  88.     strncat(buffer, numBuf, size - strlen(buffer) - 1);
  89.   }
  90.   buffer[size-1] = 0;
  91. }
  92.  
  93. //----------------------------------------------------------------------------
  94.  
  95. void far*
  96. TOleAllocator::Alloc(unsigned long size)
  97. {
  98.   void far* blk = Mem->Alloc(size);
  99.   OLECALL(blk ? 0 : HR_OUTOFMEMORY, "IMalloc::Alloc");
  100.   return blk;
  101. }
  102.  
  103. //____________________________________________________________________________
  104. //
  105. // TClassId - GUID/IID/CLSID management implementation
  106. //____________________________________________________________________________
  107.  
  108. TClassId::TClassId(const char far* idtxt) : Text(0)
  109. {
  110.   PRECONDITION(idtxt);
  111.  
  112.   OLECALL(::CLSIDFromString(OleStr((char far*)idtxt), &Guid), "Invalid GUID string");
  113. }
  114.  
  115. TClassId::TClassId(const GUID far& guid, int offset) : Text(0), Guid(guid)
  116. {
  117.   Guid.Data1 += (long)offset;
  118. }
  119.  
  120. TClassId::TClassId(TGenerate) : Text(0)
  121. {
  122.   OLECALL(::CoCreateGuid(&Guid), "CoCreateGuid");
  123. }
  124.  
  125. TClassId::~TClassId()
  126. {
  127.   delete const_cast<char*>(Text);
  128. }
  129.  
  130. TClassId::operator const char*()
  131. {
  132.   if (!Text) {
  133.     Text = new char[38+1];
  134.     wsprintf(const_cast<char*>(Text),
  135.              "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  136.              Guid.Data1, Guid.Data2, Guid.Data3,
  137.              Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
  138.              Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
  139.   }
  140.   return Text;
  141. }
  142.  
  143. TBaseClassId::TBaseClassId(const GUID far& guid, int maxAlloc)
  144.              : TClassId(guid), MaxAlloc(maxAlloc), Offset(0) {}
  145.  
  146. TBaseClassId::TBaseClassId(const char far* idtxt, int maxAlloc)
  147.              : TClassId(idtxt), MaxAlloc(maxAlloc), Offset(0) {}
  148.  
  149. TBaseClassId::TBaseClassId(TGenerate e, int maxAlloc)
  150.              : TClassId(e), MaxAlloc(maxAlloc), Offset(0) {}
  151.  
  152. TBaseClassId::TBaseClassId(TRegList& regInfo, int maxAlloc)
  153.              : TClassId(), MaxAlloc(maxAlloc), Offset(0)
  154. {
  155.   const char* str = regInfo["clsid"];
  156.   // must check for valid clasid, else generate??  
  157.   if (!str)
  158.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Missing REGDATA clsid");
  159.   OLECALL(::CLSIDFromString(OleStr((char far*)str), &Guid), "Invalid GUID string");
  160. }
  161.  
  162. TClassId TBaseClassId::operator [](int offset)
  163. {
  164.   if(offset > Offset)
  165.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Unassigned GUID");
  166.   return TClassId(Guid, offset);
  167. }
  168.  
  169. int TBaseClassId::AllocId()
  170. {
  171.   ++Offset;
  172.   if(Offset >= MaxAlloc)
  173.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "GUID allocation exhausted");
  174.   return Offset;
  175. }
  176.  
  177. int TBaseClassId::GetOffset(const GUID far& guid)
  178. {
  179.   unsigned long offset = guid.Data1 - Guid.Data1;
  180.   if ( offset >= (unsigned long)Offset &&
  181.        ((long far*)&guid)[1] == ((long*)&Guid)[1] &&
  182.        ((long far*)&guid)[2] == ((long*)&Guid)[2] &&
  183.        ((long far*)&guid)[3] == ((long*)&Guid)[3] )
  184.     return int(offset);
  185.   else
  186.     return -1;
  187. }
  188.  
  189. //____________________________________________________________________________
  190. //
  191. // GUID compare routines use by implementations of IUnknown::QueryInterface
  192. //       the low-order long word is verifed before calling these routines
  193. //       success is indicated by virtue of assigment of the returned interface
  194. //____________________________________________________________________________
  195.  
  196. void CmpGuid12(IUnknown* obj, REFIID req, REFIID ref, void far*far* pif)
  197. {
  198.   if ( ((long far*)&req)[1] == ((long far*)&ref)[1] &&
  199.        ((long far*)&req)[2] == ((long far*)&ref)[2] &&
  200.        ((long far*)&req)[3] == ((long far*)&ref)[3] ) {
  201.     *pif = obj;
  202.     obj->AddRef();
  203.   }
  204.  
  205. void CmpGuidOle(IUnknown* obj, REFIID req, void far*far* pif)
  206. {
  207.   if ( ((long far*)&req)[1] == 0x00000000L &&
  208.        ((long far*)&req)[2] == 0x000000C0L &&
  209.        ((long far*)&req)[3] == 0x46000000L ) {
  210.     *pif = obj;
  211.     obj->AddRef();
  212.   }
  213. }
  214.  
  215. //____________________________________________________________________________
  216. //
  217. // TUnknown - standard implementation of IUnknown
  218. //____________________________________________________________________________
  219.  
  220. //
  221. // Handy container to help watch COM object lifetime when debugging
  222. //
  223. #if (__DEBUG >= 2)
  224. # include <classlib/bags.h>
  225.   typedef TBagAsVector<TUnknown*> TUnknownBag;
  226.   TUnknownBag* UnknownBag;
  227. #endif
  228.  
  229. TUnknown::TUnknown() : Outer(&I)
  230. {
  231. #if (__DEBUG >= 2)
  232.   if (!UnknownBag)
  233.     UnknownBag = new TUnknownBag(100);
  234.   UnknownBag->Add(this);
  235. #endif
  236. }
  237.  
  238. IUnknown& TUnknown::Aggregate(TUnknown& inner)
  239. {
  240.   if (I.Inner)
  241.     return I.Inner->Aggregate(inner);
  242.   ((IUnknown&)inner).AddRef();
  243.   I.Inner = &inner;
  244.   return *Outer;
  245. }
  246.  
  247. TUnknown::~TUnknown()
  248. #if (__DEBUG >= 2)
  249.   UnknownBag->Detach(this);
  250. #endif
  251.   TRACEX(OcRefCount, 1,
  252.          "~TUnknown() @" << (void*)this << ", RefCnt:" << I.RefCnt);
  253.   WARNX(OcRefCount, I.RefCnt != 0, 0,
  254.         "~TUnknown() @ " << (void*)this << ", RefCnt:" << I.RefCnt);
  255.  
  256.   // deleted by TUnknownI member
  257. }
  258.  
  259. //
  260. // QueryObject used when TUnknown is in constructor/destructor
  261. //
  262. HRESULT
  263. TUnknown::QueryObject(const GUID far& /*iid*/, void far* far* /*pif*/)
  264. {
  265.   return ResultFromScode(E_NOINTERFACE);
  266. }
  267.  
  268. HRESULT _IFUNC
  269. TUnknown::TUnknownI::QueryInterface(const GUID far& iid, void far* far* pif)
  270. {
  271.   *pif = 0;
  272.   if (iid.Data1 == 0) { // IID_IUnknown.Data1
  273.     CmpGuidOle(this, iid, pif);
  274.     if (*pif)
  275.       return NOERROR;
  276.   }
  277.   if (Host().QueryObject(iid, pif) == NOERROR)
  278.     return NOERROR;
  279.   if (Inner)
  280.     return Inner->ThisUnknown().QueryInterface(iid, pif);
  281.   else
  282.     return ResultFromScode(E_NOINTERFACE);
  283. }
  284.  
  285. unsigned long _IFUNC
  286. TUnknown::TUnknownI::AddRef()
  287. {
  288.   TRACEX(OcRefCount, 2,
  289.          "AddRef on " << (void*)&Host() << " to " << (RefCnt+1));
  290.   return ++RefCnt;
  291. }
  292.  
  293. unsigned long _IFUNC
  294. TUnknown::TUnknownI::Release()
  295. {
  296.   TRACEX(OcRefCount, 2,
  297.          "Release on " << (void*)&Host() << " to " << (RefCnt-1));
  298.   if (--RefCnt != 0)
  299.     return RefCnt;
  300.   if (Inner) {
  301.     Inner->ThisUnknown().Release();
  302.     Inner = 0;
  303.   }
  304.   delete &Host();
  305.   return 0;
  306. }
  307.  
  308. unsigned long
  309. TUnknown::GetRefCount()
  310. {
  311.   if (Outer == &I)
  312.     return I.RefCnt;
  313.   Outer->AddRef();
  314.   return Outer->Release();
  315. }
  316.  
  317. TUnknown::TUnknownI::~TUnknownI()
  318. {
  319.   if (RefCnt)             // in case destructor called before RefCnt goes to 0
  320.     ::CoDisconnectObject(this,0);// OLE will try to remove external references
  321. }
  322.  
  323. //____________________________________________________________________________
  324. //
  325. // TLocaleString wrapper method replacements using OLE2 NLS functions for Win16
  326. //____________________________________________________________________________
  327.  
  328. #if defined(BI_PLAT_WIN16)
  329.  
  330. TLangId
  331. TLocaleString::GetSystemLangId()
  332. {
  333.   return ::GetSystemDefaultLangID();
  334. }
  335.  
  336. TLangId
  337. TLocaleString::GetUserLangId()
  338. {
  339.   return ::GetUserDefaultLangID();
  340. }
  341.  
  342. int
  343. TLocaleString::CompareLang(const char far* s1, const char far* s2, TLangId lang)
  344. {
  345.   return ::CompareStringA(lang, NORM_IGNORECASE | NORM_IGNORENONSPACE,
  346.                           s1,-1, s2,-1) - 2;
  347. }
  348.  
  349. #endif
  350.  
  351.