GME  13
MgaTrukk.h
Go to the documentation of this file.
00001 //
00002 // Tricks, macros, definitions used throughout the Mga library
00003 //
00004 
00005 #pragma once
00006 
00007 #include "MgaCoreObj.h"
00008 #include "CommonMgaTrukk.h"
00009 
00010 #define DIM(x) (sizeof(x)/ sizeof((x)[0]))
00011 
00012 extern const CoreObj NULLCOREOBJ;
00013 extern const CComVariant NULLVARIANT;
00014 
00015 
00016 // ----------------------------------------
00017 // Collection types
00018 // ----------------------------------------
00019 
00020 #define COLLECTIONTYPE_FOR2(t1, t2)  CCoreCollection<t2, std::vector<t1*>, t1, t1> 
00021 #define CREATECOLLECTION_FOR2(t1, t2, q) \
00022    CComPtr< COLLECTIONTYPE_FOR2(t1, t2) > q; CreateComObject(q);
00023 
00024 #define COLLECTIONTYPE_FOR(t)  COLLECTIONTYPE_FOR2(t, t##s)
00025 #define CREATECOLLECTION_FOR(t,q) CREATECOLLECTION_FOR2(t, t##s, q)
00026 
00027 
00028 // ----------------------------------------
00029 // ITERATE through collections
00030 // ----------------------------------------
00031 
00032 // iterate through CoreObj colls
00033 
00034 #define ITERATE_THROUGH(ci)  \
00035 CoreObjs collifptr=ci; \
00036 ASSERT( collifptr != NULL );                            \
00037 std::vector< CoreObj> vect;                     \
00038 GetAll2<ICoreObjects>(collifptr, vect);\
00039 std::vector< CoreObj>::iterator it_i = vect.begin(), it_e = vect.end(); \
00040 for(;it_i != it_e; ++it_i )
00041 
00042 #define ITERATE_THROUGH_BACK(ci)  \
00043 CoreObjs collifptr=ci; \
00044 ASSERT( collifptr != NULL );                            \
00045 std::vector< CoreObj> vect;                     \
00046 GetAll2<ICoreObjects>(collifptr, vect);\
00047 std::vector< CoreObj>::iterator it_b = vect.begin(), it_i = vect.end(); \
00048 while(it_i-- != it_b) 
00049 
00050 #define ITER  (*it_i)
00051 #define ITER_BROKEN (it_i != it_e)
00052 
00053 // ----------------------------------------
00054 // CHECK PARAMETERS
00055 // ----------------------------------------
00056 
00057 #define COM_EQUAL(a, b) (static_cast<IUnknown *>(a) == b ? true : a.IsEqualObject(b))
00058 
00059 #define CHECK_INPTRPAR(p)        { if(p == NULL)                                 COMTHROW( E_MGA_INPTR_NULL); }
00060 #define CHECK_MYINPTRPARVALIDNULL(p)  { if(p != NULL) COMTHROW(p->CheckProject(mgaproject)); }
00061 #define CHECK_MYINPTRPAR(p)      { if(p == NULL)                                 COMTHROW( E_MGA_INPTR_NULL); \
00062                                                                 COMTHROW(p->CheckProject(mgaproject)); }
00063 #define CHECK_MYINPTRSPAR(p) { if(p == NULL)                             COMTHROW( E_MGA_INPTR_NULL); \
00064                                                                 COMTHROW( mgaproject->CheckCollection(p)); }
00065 //by ZolMol
00066 #define CHECK_MYINPTRSPARFOLDER(p) { if(p == NULL)                               COMTHROW( E_MGA_INPTR_NULL); \
00067                                                                 COMTHROW( mgaproject->CheckFolderCollection(p)); }
00068 // KMS: was "if(p == NULL) p = NULLSTR", but starting with VS2003, that does nothing since NULLSTR.m_str==NULL
00069 #define CHECK_INSTRPAR(p)        { }
00070 #define CHECK_OUTSTRPAR(p)   { if(p == NULL) COMTHROW(E_MGA_OUTPTR_NULL); if(*p != NULL) COMTHROW(E_MGA_OUTPTR_NONEMPTY); }
00071 #define CHECK_OUTPTRPAR(p)   { if(p == NULL) COMTHROW(E_MGA_OUTPTR_NULL); if(*p != NULL) COMTHROW(E_MGA_OUTPTR_NONEMPTY); }
00072 #define CHECK_OUTPTRPARVALIDNULL(p)  { if(p != NULL && *p != NULL) COMTHROW(E_MGA_OUTPTR_NONEMPTY); }
00073 #define CHECK_INPAR(p)                          
00074 #define CHECK_INBOOLPAR(p)       { if(p != VARIANT_FALSE && p != VARIANT_TRUE)  COMTHROW(E_MGA_BAD_ENUMVALUE);  }       
00075 #define CHECK_OUTPAR(p)          { if(p == NULL)                                 COMTHROW(E_MGA_OUTPTR_NULL); }
00076 #define CHECK_OUTVARIANTPAR(p)           { if(p == NULL)                                 COMTHROW(E_MGA_OUTPTR_NULL); }
00077 
00078 
00079 
00080 
00081 //z! renamed to GetAll2 from GetAll (it was in conflict with GetAll defined in CommonCollection.h)
00082 template<class COLLITF>
00083 void GetAll2(COLLITF *coll, std::vector< CoreObj > &ret)
00084 {
00085         ASSERT( coll != NULL );
00086         ASSERT( ret.empty() );
00087 
00088         long count = 0;
00089         COMTHROW( coll->get_Count(&count) );
00090         ASSERT( count >= 0 );
00091 
00092         ret.clear();
00093         ret.insert(ret.begin(), count, NULL);
00094 
00095         if(count > 0) COMTHROW( coll->GetAll(count, &ret.front().p) );
00096 }
00097 
00098 
00099 
00100 // ----------------------------------------
00101 // STL compatible wrapped for CComBSTR
00102 // ----------------------------------------
00103 /*class CComBSTRNoAt : public CComBSTR {
00104 public:
00105         CComBSTRNoAt() {;};
00106         CComBSTRNoAt(const CComBSTR &sss) : CComBSTR(sss) {;}
00107         CComBSTRNoAt* const operator&() {
00108                 return this;
00109         }
00110 };*/
00111 typedef CComBSTR CComBSTRNoAt;  
00112 
00113 
00114 // ----------------------------------------
00115 // Operations and STL-derived datatypes defined on CoreObj
00116 // ----------------------------------------
00117 
00118 struct coreobj_hashfunc : public stdext::hash_compare<CoreObj> 
00119 {
00120 #ifndef _ATL_DEBUG_INTERFACES
00121         size_t operator()(const CoreObj &ob) const
00122         {
00123                 return (size_t)ob.p;
00124         }
00125         bool operator()(const CoreObj &oba, const CoreObj &obb) const
00126         {
00127                 // must be < logic, [ implemented based on COM_EQUAL's invokation ]
00128                 return static_cast<IUnknown*>(const_cast<CoreObj&>(oba)) < static_cast<IUnknown*>(const_cast<CoreObj&>(obb));
00129         }
00130 #else
00131         size_t operator()(const CoreObj &ob) const
00132         {
00133                 return (size_t)(IUnknown*)getUnknown(ob);
00134         }
00135         bool operator()(const CoreObj &oba, const CoreObj &obb) const
00136         {
00137                 // must be < logic, [ implemented based on COM_EQUAL's invokation ]
00138                 return static_cast<IUnknown*>(getUnknown(oba)) < static_cast<IUnknown*>(getUnknown(obb));
00139         }
00140 
00141         IUnknownPtr getUnknown(const CoreObj &ob) const {
00142                 auto obj = const_cast<CoreObj&>(ob);
00143                 if (obj == nullptr) {
00144                         return nullptr;
00145                 }
00146                 IUnknownPtr pUnk;
00147                 obj->QueryInterface(&pUnk);
00148                 return pUnk;
00149         }
00150 #endif
00151 };
00152 
00153 typedef stdext::hash_map<CoreObj, CoreObj, coreobj_hashfunc> coreobjpairhash;
00154 typedef stdext::hash_map<CoreObj,     int, coreobj_hashfunc> coreobjhash;
00155 
00156 
00157 
00158 // ---------------------------------------
00159 // sort a CoreObjs collection
00160 // ----------------------------------------
00161 template <class avt>
00162 void Sort(CoreObjs &coll, attrid_type  ai) {
00163                 CREATECOLLECTION_FOR(ICoreObject, q);
00164                 std::vector< CoreObj> vect;                     
00165                 GetAll2<ICoreObjects>(coll, vect);
00166                 std::vector< CoreObj>::iterator it_i = vect.begin(), it_e = vect.end(); 
00167                 std::vector< CoreObj>::iterator it_j, it_min;
00168                 for(;it_i != it_e; ++it_i ) {
00169                         it_j = it_i;
00170                         avt min = (*it_j)[ai];
00171                         it_min = it_j;
00172                         while(++it_j != it_e) {
00173                                 avt l = (*it_j)[ai];
00174                                 if(l < min) {
00175                                         it_min = it_j;
00176                                         min = l;
00177                                 }
00178                         }
00179                         q->Add(*it_min);
00180                         *it_min = *it_i;
00181                 }
00182                 coll.Attach(q.Detach());
00183 }
00184 
00185 
00186 
00187 // ----------------------------------------
00188 // FCO SMART POINTER, compatible with STL collections
00189 // ----------------------------------------
00190 class FCO;
00191 
00192 class FCOPtr {  //smart FCO pointer
00193         friend struct FCOPtr_hashfunc;
00194         FCO *p;
00195 public:
00196         FCO * operator->() const { return  p; } 
00197         operator FCO* () const { return  p; } 
00198         void operator= (FCO *f);
00199         bool operator< (const FCOPtr &o) const;
00200         FCOPtr(FCOPtr const &o);
00201         FCOPtr(FCOPtr&& o);
00202         FCOPtr(FCO *f);
00203         FCOPtr();
00204         ~FCOPtr();
00205 };
00206 
00207 struct FCOPtr_hashfunc : public stdext::hash_compare<FCOPtr>
00208 {
00209         size_t operator()(const FCOPtr &ob) const
00210         {
00211                 return reinterpret_cast<size_t>(ob.p) % 19;//return reinterpret_cast<size_t>( reinterpret_cast<size_t>(ob.p) % 19); // 64 bt
00212         }
00213         bool operator()(const FCOPtr &p_ob1, const FCOPtr &p_ob2) const
00214         {
00215                 return p_ob1 < p_ob2;
00216         }
00217 };
00218 
00219 
00220 // ----------------------------------------
00221 // UTILITIES FROM MGA.CPP 
00222 // ----------------------------------------
00224 CComBSTR Now(void);  
00225 
00226 // ----------------------------------------
00227 // CLASS SIGNATURE MECHANISM USED FOR DEBUG 
00228 // ----------------------------------------
00229 #ifdef DEBUG
00230 #define DEFSIG  char sig[5];
00231 #define INITSIG(a)  { sig[0] = 'A'; sig[1] = 'B'; sig[2] = a; sig[3] = '0'; sig[4] = '\0'; }
00232 #define MARKSIG(a)  sig[3] = a
00233 #else
00234 #define DEFSIG
00235 #define INITSIG(a)
00236 #define MARKSIG(a)
00237 #endif
00238 
00239 
00240 // ----------------------------------------
00241 // ErrorInfoImpl
00242 // ----------------------------------------
00243 #define ISupportErrorInfoImpl IMyErrorInfoImpl
00244 
00245 
00246 class ATL_NO_VTABLE IMyErrorInfoBase {
00247 public:
00248             BEGIN_INTERFACE
00249         virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
00250             /* [in] */ REFIID riid,
00251             /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
00252         
00253         virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
00254         
00255         virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
00256         STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) = 0;
00257 };
00258 
00259 template <const IID* piid>
00260 class ATL_NO_VTABLE IMyErrorInfoImpl : public IMyErrorInfoBase {
00261 public:
00262         STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
00263         {
00264 //              return (InlineIsEqualGUID(riid,*piid)) ? S_OK : S_FALSE;
00265                 // ASSERT(InlineIsEqualGUID(riid,*piid)); not correct in many cases: e.g. riid=IMgaFCO on CMgaConnection, riid=IMgaSimpleConnection, riid=IDispatch, ....
00266                 return S_OK;
00267         }
00268 };
00269 
00270 
00271 // ----------------------------------------
00272 // Transaction class, {COMTRY,COMCATCH}_IN_TRANSACTION
00273 // ----------------------------------------
00274 #include "MgaProject.h"
00275 #include "MgaFCO.h"
00276 #include "MgaTerritory.h"
00277 
00278 class Transaction {
00279         CMgaProject *pr;
00280 public:
00281         HRESULT Begin(CMgaProject *ppr) {
00282                 if(!ppr) { SetStandardOrGMEErrorInfo(E_MGA_ZOMBIE_NOPROJECT); return E_MGA_ZOMBIE_NOPROJECT; }
00283                 if(!ppr->opened) { SetStandardOrGMEErrorInfo(E_MGA_ZOMBIE_CLOSED_PROJECT); return E_MGA_ZOMBIE_CLOSED_PROJECT; }
00284                 if(!ppr->activeterr) { SetStandardOrGMEErrorInfo(E_MGA_NOT_IN_TRANSACTION); return E_MGA_NOT_IN_TRANSACTION; }
00285                 if(ppr->alreadynested()) {
00286                         pr = NULL;
00287                         return S_OK;
00288                 }
00289                 else {
00290                         pr = ppr;
00291                         return pr->beginnested();
00292                 }
00293         }
00294 
00295         HRESULT Abort() {
00296                 if(pr) return pr->abortnested();
00297                 else return S_OK;
00298         }
00299         HRESULT Commit() {
00300                 if(pr)  return pr->commitnested();
00301                 else return S_OK;
00302         }
00303 };
00304 
00305 #define COMTRY_IN_TRANSACTION { \
00306         Transaction ttt; \
00307         HRESULT hr = ttt.Begin(mgaproject); \
00308         if(hr != S_OK) { return hr; } \
00309         try
00310 
00311 bool MgaSetErrorInfo(HRESULT hr);
00312 
00313 #define COMRETURN_IN_TRANSACTION(hr) \
00314         if (FAILED(hr)) { \
00315                 HRESULT hrTx = ttt.Abort(); \
00316                 if (FAILED(hrTx)) return hrTx; \
00317                 return hr; \
00318         } else { return ttt.Commit(); }
00319 
00320 #define COMCATCH_IN_TRANSACTION( CLEANUP )  \
00321         catch(hresult_exception &e) \
00322         { \
00323                 ASSERT( FAILED(e.hr) ); \
00324                 { \
00325                         if((hr = ttt.Abort()) != S_OK) return hr; \
00326                         CLEANUP; \
00327                 } \
00328                 MgaSetErrorInfo(e.hr); \
00329                 return e.hr; \
00330         } \
00331         catch(_com_error &e) \
00332         { \
00333                 ASSERT(FAILED(e.Error())); \
00334                 if ((hr = ttt.Abort()) != S_OK) return hr; \
00335                 { CLEANUP; } \
00336                 if (e.Description() != _bstr_t()) \
00337                         SetErrorInfo(e.Description()); \
00338                 else \
00339                         SetStandardOrGMEErrorInfo(e.Error()); \
00340                 return e.Error(); \
00341         } \
00342         catch(std::bad_alloc&) \
00343         { \
00344                 { \
00345                         if((hr = ttt.Abort()) != S_OK) return hr; \
00346                         CLEANUP; \
00347                 } \
00348                 MgaSetErrorInfo(E_OUTOFMEMORY); \
00349                 return E_OUTOFMEMORY; \
00350         } \
00351         return ttt.Commit(); }
00352 
00353 #define MGAPREF_NO_NESTED_TX 0x00000080
00354 
00355 #define COMTRY_IN_TRANSACTION_MAYBE \
00356 Transaction ttt; \
00357 if (!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX)) { \
00358   HRESULT hr = ttt.Begin(mgaproject); \
00359   if (hr != S_OK) { return hr; } \
00360 } \
00361 try
00362 
00363 #define COMCATCH_IN_TRANSACTION_MAYBE( CLEANUP )  \
00364 catch(hresult_exception &e) \
00365 { \
00366         ASSERT( FAILED(e.hr) ); \
00367         { \
00368                 HRESULT hr; \
00369                 if(!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX) && ((hr = ttt.Abort()) != S_OK)) return hr; \
00370                 CLEANUP; \
00371         } \
00372         MgaSetErrorInfo(e.hr); \
00373         return e.hr; \
00374 } \
00375 catch(_com_error &e) \
00376 { \
00377         ASSERT(FAILED(e.Error())); \
00378         HRESULT hr; \
00379         if(!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX) && ((hr = ttt.Abort()) != S_OK)) return hr; \
00380         { CLEANUP; } \
00381         if (e.Description() != _bstr_t()) \
00382                 SetErrorInfo(e.Description()); \
00383         else \
00384                 SetStandardOrGMEErrorInfo(e.Error()); \
00385         return e.Error(); \
00386 } \
00387 catch(std::bad_alloc&) \
00388 { \
00389         { \
00390                 HRESULT hr; \
00391                 if(!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX) && ((hr = ttt.Abort()) != S_OK)) return hr; \
00392                 CLEANUP; \
00393         } \
00394         MgaSetErrorInfo(E_OUTOFMEMORY); \
00395         return E_OUTOFMEMORY; \
00396 } \
00397 if (!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX)) \
00398         return ttt.Commit(); \
00399 else \
00400         return S_OK;
00401 
00402 #define COMRETURN_IN_TRANSACTION_MAYBE(hr) \
00403   do { \
00404         HRESULT _hr = hr; \
00405         if (FAILED(_hr)) { \
00406                 if (!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX)) \
00407                 { \
00408                         HRESULT hrTx = ttt.Abort(); \
00409                         if (FAILED(hrTx)) return hrTx; \
00410                 } \
00411                 return _hr; \
00412         } else { \
00413                 if (!(this->mgaproject->preferences & MGAPREF_NO_NESTED_TX)) \
00414                         return ttt.Commit(); \
00415                 else \
00416                         return S_OK; \
00417         } \
00418   } while(0);
00419 
00420 
00421 
00422 #define MODIFIED        { if(mgaproject->opened < 1000) mgaproject->opened++; }
00423  
00424 #undef COMCATCH
00425 #define COMCATCH( CLEANUP )  \
00426         catch(hresult_exception &e) \
00427         { \
00428                 ASSERT( FAILED(e.hr) ); \
00429                 { \
00430                         CLEANUP; \
00431                 } \
00432                 MgaSetErrorInfo(e.hr); \
00433                 return e.hr; \
00434         } \
00435         catch(_com_error &err) \
00436         { \
00437                 struct { HRESULT hr; } e = { err.Error() }; \
00438                 { CLEANUP; } \
00439                 if (err.Description() != _bstr_t()) \
00440                         SetErrorInfo(err.Description()); \
00441                 else \
00442                         SetStandardOrGMEErrorInfo(err.Error()); \
00443                 return e.hr; \
00444         } \
00445         catch(std::bad_alloc&) \
00446         { \
00447                 struct { HRESULT hr; } e = { E_OUTOFMEMORY }; \
00448                 { \
00449                         CLEANUP; \
00450                 } \
00451                 SetStandardOrGMEErrorInfo(e.hr); \
00452                 return e.hr; \
00453         } \
00454         return S_OK;
00455 
00456 
00457 
00461 
00462 // Executes the virtual Do function for the object and all the derived types
00463 // DoWithDeriveds is used to start the operation
00464 //              - self : the CoreObj to work on (FCO or ConnRole, or SetNode)
00465 //              - peers : the vector of the peer FCO-s (e.g. relation targets)
00466 // Before starting with the initial object, it is determined 
00467 // which targets are 'internal' i.e. to be adjusted for the subtypes
00468 // 'false internals' are not detected, because in most cases they cannot occur.
00469 // if they still may occur (e.g. RevertToBase), use the 'endreserve' parameter to
00470 // explicitly indicate that they are not internals
00471 /*class DeriveTreeTask  {
00472 protected:
00473         int peercnt, internalpeercnt;
00474         int endreserve;   // the number of 'reserved' coreobjs at the end of the vector
00475         attrid_type masterattr;
00476 private:
00477         std::vector<int> peerdepths;
00478         int selfdepth;
00479         virtual bool Do(CoreObj self, std::vector<CoreObj> *peers = NULL) = 0;
00480         void _DoWithDeriveds(CoreObj self, std::vector<CoreObj> *peers = NULL);
00481 public:
00482         DeriveTreeTask() : endreserve(0), masterattr(0) { };
00483         void DoWithDeriveds(CoreObj self, std::vector<CoreObj> *peers = NULL);
00484 };*/
00485 
00486 
00487 // ----------------------------------------
00488 // BOOLTEMPFLAG
00489 // keeps a bool flag set as long as it is on the stack
00490 // ----------------------------------------
00491 class booltempflag {
00492         bool *flagptr;
00493 public:
00494         booltempflag(bool &a)  {        flagptr = a ? NULL : &a; set();}
00495         bool set() { if(flagptr) *flagptr = true; return flagptr != 0; }
00496         bool reset() { if(flagptr) *flagptr = false; return flagptr != 0; }
00497         ~booltempflag() { reset(); }
00498 };
00499