GME
13
|
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