GME  13
MgaProject.cpp
Go to the documentation of this file.
00001 // MgaProject.cpp : Implementation of CMgaProject
00002 #include "stdafx.h"
00003 #include "MgaUtil.h"
00004 #include "CommonComponent.h"
00005 #include "MgaFCO.h"
00006 #include "MgaFilter.h"
00007 #include "stdio.h"
00008 #include "MgaComplexOps.h"
00009 #include "MgaLibOps.h"
00010 
00011 void LockingStart(CComPtr<ICoreProject> &tempproject)   { 
00012                    CComPtr<ICoreTerritory> lm;
00013                    COMTHROW(tempproject->CreateTerritory( &lm));
00014                    COMTHROW(tempproject->PushTerritory( lm));
00015 }
00016 
00018 // CMgaProject
00020 
00021 CMgaProject::CMgaProject()      { 
00022                         INITSIG('P');
00023 #ifdef DEBUG
00024                         MGA_TRACE("Constructed: %s - %08X\n", sig, this);
00025 #endif
00026                         opened = CLOSED;
00027                         dataproject = NULL;
00028                         preferences = 0;
00029                         opmask = 0x0026662A;
00030                         mgaproject = this;
00031                         checkoff = false;
00032                         transactioncount = 0;
00033                         autoaddons = false;
00034                         inautoaddoncreate = false;
00035                         mgaversion = 0;
00036                         aurcnt = 0;
00037                         guidstat = CLEAN;
00038 }
00039 
00040 STDMETHODIMP CMgaProject::FinalConstruct()      {
00041                 COMTRY {
00042 //                      IDispatchImpl<IMgaProject, &IID_IMgaProject, &LIBID_MGALib> *xthis = this;
00043                         COMTHROW( CoCreateInstance(__uuidof(CoreProject), (IMgaProject *)this, CLSCTX_ALL, IID_IUnknown, (LPVOID *) &inner) );
00044 #ifndef _ATL_DEBUG_INTERFACES
00045                         COMTHROW(inner.QueryInterface(&dataproject));
00046                         dataproject->Release();   // release reference to ourselves
00047 #else
00048                         dataprojectNull = false;
00049 #endif
00050                 } COMCATCH(;);
00051 }
00052 
00053 CMgaProject::~CMgaProject()     {
00054 #ifdef DEBUG
00055                 MGA_TRACE("Destructed: %s - %08X\n", sig, this);
00056 #endif
00057                 MARKSIG('9'); 
00058                 ASSERT(allterrs.empty());
00059                 if(opened != CLOSED) { 
00060                         Close();
00061                 }
00062 }
00063 
00067 
00068 STDMETHODIMP CMgaProject::get_MetaObj(metaref_type id, IMgaMetaBase **pVal) {
00069         COMTRY {
00070                 COMTHROW(metapr != 0 ? S_OK : E_MGA_PROJECT_NOT_OPEN);
00071                 SetNmspaceInMeta();
00072                 COMTHROW(metapr->get_FindObject(id, pVal));
00073         }
00074         COMCATCH(;);    
00075 }
00076 
00077 // THROWS
00078 CComPtr<IMgaMetaBase> CMgaProject::FindMetaRef(metaref_type l) {
00079                 CComPtr<IMgaMetaBase> hh;
00080                 COMTHROW(metapr != 0 ? S_OK : E_MGA_PROJECT_NOT_OPEN);
00081                 SetNmspaceInMeta();
00082                 COMTHROW(metapr->get_FindObject(l, &hh));
00083 //              HRESULT hr = metapr->get_FindObject(l, &hh);
00084 //              if(hr != S_OK && hr != E_NOTFOUND) COMTHROW(hr);
00085                 return hh;
00086 }
00087 
00088 
00092 
00093 
00094 HRESULT CMgaProject::CreateSetupData(BSTR rootname, BSTR paradigmname, VARIANT guid) {
00095                 COMTRY_IN_TRANSACTION { 
00096 
00097 // check if meta is valid
00098                         CoreObj  dataroot, rootfolder;
00099                         CComBSTR parversion;
00100 
00101 // set values in                        
00102                         COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00103                         dataroot[ATTRID_CDATE] = dataroot[ATTRID_MDATE]  = Now();
00104                         dataroot[ATTRID_PARADIGM] = paradigmname;
00105                         dataroot[ATTRID_MGAVERSION] = mgaversion;
00106                         COMTHROW(metapr->get_Version(&parversion));
00107                         dataroot[ATTRID_PARVERSION] = parversion;
00108                         dataroot[ATTRID_NAME]    = rootname;
00109                         if( guid.vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(guid) != sizeof(::GUID) )
00110                                         COMTHROW(E_INVALIDARG);
00111                         dataroot[ATTRID_PARGUID] = guid;
00112                         dataroot[ATTRID_VERSION] = CComBSTR(""); // default version string
00113 
00114 // create data root things
00115                     COMTHROW(dataproject->CreateObject(DTID_FOLDER,&rootfolder.ComPtr()));
00116                         assignGuid( this, rootfolder); // assign a guid to the root folder
00117                         rootfolder[ATTRID_NAME]    = rootname;
00118                         rootfolder[ATTRID_FPARENT] = dataroot;
00119                         if(!(preferences & MGAPREF_MANUAL_RELIDS))  rootfolder[ATTRID_RELID] = 1;
00120                         CComPtr<IMgaMetaFolder> mf;
00121                         metaref_type mr;
00122                         COMTHROW(metapr->get_RootFolder(&mf));
00123                         COMTHROW(mf->get_MetaRef(&mr));
00124                         rootfolder[ATTRID_META] = mr;
00125                         notifyqueueprocessed = true;
00126                 } COMCATCH_IN_TRANSACTION(;);
00127 
00128 }
00129 
00130 
00131 static int guidcmp(VARIANT &qGUID, VARIANT &pGUID)      {
00132         ::GUID g1, g2;
00133         CopyTo(qGUID, g1);
00134         CopyTo(pGUID, g2);
00135         return memcmp(&g1, &g2, sizeof(g1));
00136 }
00137 
00138 
00139 inline HRESULT EMAP(HRESULT hr, HRESULT from, HRESULT to) { HRESULT h = hr; if(h == from) h = to; return h; }
00140 inline HRESULT EDEF(HRESULT hr, HRESULT to) { HRESULT h = hr; if(h != S_OK) h = to; return h; }
00141 
00142 
00143 void CMgaProject::OpenParadigm(BSTR s, VARIANT *pGUID) {
00144         CComPtr<IMgaRegistrar> mgareg;
00145         COMTHROW(mgareg.CoCreateInstance(OLESTR("Mga.MgaRegistrar")));
00146         _bstr_t connstr;
00147         {
00148                 HRESULT hr = mgareg->QueryParadigm(s, connstr.GetAddress(), pGUID, REGACCESS_PRIORITY);
00149                 if (FAILED(hr))
00150                 {
00151                         CComPtr<IErrorInfo> info;
00152                         GetErrorInfo(0, &info);
00153                         throw _com_error(E_MGA_PARADIGM_NOTREG, info, true);
00154                 }
00155         }
00156         ASSERT(connstr);
00157         COMTHROW(metapr.CoCreateInstance(OLESTR("Mga.MgaMetaProject")));
00158         // #ifdef _ATL_DEBUG_INTERFACES
00159         // COMTHROW(metapr.CoCreateInstance(OLESTR("Mga.MgaMetaProject"), NULL, CLSCTX_LOCAL_SERVER));
00160         HRESULT hr = metapr->Open(connstr);
00161         if (FAILED(hr))
00162         {
00163                 _bstr_t err;
00164                 if (GetErrorInfo(err.GetAddress()))
00165                         throw_com_error(E_MGA_PARADIGM_INVALID, static_cast<const wchar_t*>(err)); // change HRESULT
00166                 COMTHROW(E_MGA_PARADIGM_INVALID);
00167         }
00168         CComVariant metaGUID;
00169         COMTHROW(metapr->get_GUID(&metaGUID));
00170         if (guidcmp(metaGUID, *pGUID)) 
00171                 throw_com_error(E_MGA_PARADIGM_INVALID, L".mta file paradigm GUID does not match registered GUID");
00172         parconn = connstr.GetBSTR();
00173 }
00174 
00175 
00176 STDMETHODIMP CMgaProject::OpenParadigm(BSTR s, BSTR ver) {
00177         COMTRY {
00178                 CComVariant vguid;
00179                 {
00180                         CComPtr<IMgaRegistrar> mgareg;
00181                         COMTHROW(mgareg.CoCreateInstance(OLESTR("Mga.MgaRegistrar")));
00182                         {
00183                                 HRESULT hr = mgareg->GUIDFromVersion(s, ver, &vguid, REGACCESS_PRIORITY);
00184                                 if (FAILED(hr))
00185                                 {
00186                                         CComPtr<IErrorInfo> info;
00187                                         GetErrorInfo(0, &info);
00188                                         throw _com_error(E_MGA_PARADIGM_NOTREG, info, true);
00189                                 }
00190                         }
00191                 }
00192                 OpenParadigm(s,&vguid);
00193         } COMCATCH(;);
00194 }
00195 
00196 STDMETHODIMP CMgaProject::CreateEx(BSTR projectname, BSTR paradigmname, VARIANT paradigmGUID) {
00197         COMTRY {
00198                 if(opened != CLOSED) COMTHROW(E_MGA_PROJECT_OPEN);
00199 
00200                 mgaversion = 2;
00201                         // Set generic for meta
00202                 CComPtr<ICoreMetaProject> genericproject;
00203                 CreateCoreMetaProject(genericproject, mgaversion > 1); // create version 2 from now on
00204 
00205                 CComVariant connGUID;
00206                 if(paradigmGUID.vt != VT_EMPTY) connGUID = paradigmGUID;
00207                 OpenParadigm(paradigmname, &connGUID);
00208         
00209                 int undosize = getMaxUndoSize();
00210                 COMTHROW(dataproject->CreateProject2(projectname, undosize, genericproject));
00211                 opened = UNCHANGED;
00212                 guidstat = DIRTY;
00213 
00214             CComPtr<IMgaTerritory> lm;
00215             COMTHROW(CreateTerritory(NULL, &lm));
00216                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
00217                 
00218                 HRESULT suhr = S_OK;
00219                 try {
00220                         CComBSTR   fname("RootFolder");
00221             // BGY: commented out because xml backend has different connection string format
00222                         /*LPCOLESTR p = wcsrchr(projectname, '\\');
00223                         if(p) {
00224                                 p++;
00225                                 LPCOLESTR p2 = wcschr(p, '.');
00226                                 if(p2 == NULL) p2 = p + wcslen(p);
00227                                 fname = CComBSTR(p2-p, p);
00228                         }*/
00229                         suhr = CreateSetupData(fname, paradigmname, connGUID);
00230                         COMTHROW(lm->Flush());
00231                         COMTHROW(CommitTransaction());
00232                 } catch(hresult_exception &e) {
00233                         lm->Flush();
00234                         AbortTransaction();
00235                         throw e;
00236                 }
00237                 COMTHROW(dataproject->FlushUndoQueue());
00238                 COMTHROW(suhr);
00239                 projconn = projectname;
00240                 StartAutoAddOns();
00241                 try {
00242                         COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00243                         GlobalNotify(GLOBALEVENT_OPEN_PROJECT);
00244                         COMTHROW(lm->Flush());
00245                         COMTHROW(CommitTransaction());
00246                 } catch(hresult_exception &e) {
00247                         lm->Flush();
00248                         AbortTransaction();
00249                         throw e;
00250                 }
00251                 MARKSIG('2');
00252         }
00253         COMCATCH(
00254                 opened = CLOSED;
00255                 guidstat = CLEAN;
00256                 if (dataproject) {
00257                         dataproject->CloseProject(VARIANT_TRUE);
00258                         dataproject->DeleteProject(projectname);
00259                 }
00260                 if (metapr)
00261                         metapr->Close();
00262                 metapr = 0;
00263                 projconn.Empty(); 
00264                 parconn.Empty();
00265                 // We've already called SetErrorInfo, don't call it again
00266                 if (e.hr == E_MGA_COMPONENT_ERROR) {
00267                         return e.hr;
00268                 }
00269         )
00270 }
00271 
00272 
00273 // if paradigname != "": 
00274 //              change paradigmname if different
00275 //              if paradigmguid == 0 update to the current version (even if no name change!);
00276 // if paradigmguid != null and != oldguid update guid (use new paradigmname to locate paradigm in any case)
00277 // if no guid change skip check
00278 STDMETHODIMP CMgaProject::OpenEx(BSTR projectname, BSTR paradigmname, VARIANT paradigmGUID) {
00279         COMTRY {
00280                 if(opened != CLOSED) COMTHROW(E_MGA_PROJECT_OPEN);
00281                 CComBSTR s;
00282                 CComVariant pGUID;
00283                 CComBSTR ver;
00284                 CComPtr<ICoreMetaProject> genericproject;
00285                 CreateCoreMetaProject(genericproject, true); // will upgrade if old version
00286                 VARIANT_BOOL ro;
00287 
00288                 int undosize = getMaxUndoSize();
00289                 COMTHROW(dataproject->OpenProject2(projectname, undosize, genericproject, &ro));
00290                 
00291                 projconn = projectname;
00292 
00293                 opened = UNCHANGED;
00294                 guidstat = CLEAN;
00295             CComPtr<IMgaTerritory> lm;
00296             COMTHROW(CreateTerritory(NULL, &lm));
00297                 COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00298 
00299                 try {   
00300 
00301                         CoreObj  dataroot;
00302                         COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00303                     s=dataroot[ATTRID_PARADIGM];
00304                         mgaversion = dataroot[ATTRID_MGAVERSION];
00305                         if( mgaversion <= 1L) // Core layer changed the project by adding ATTRID_GUID1..4 for CCoreBinFile
00306                                 opened = CHANGED;
00307 
00308                         pGUID=CComVariant(dataroot[ATTRID_PARGUID]);
00309                         ver = dataroot[ATTRID_PARVERSION];
00310                         COMTHROW(lm->Flush());
00311                         COMTHROW(CommitTransaction());
00312                 } catch(hresult_exception &e) {
00313                         lm->Flush();
00314                         AbortTransaction();
00315                         throw e;
00316                 }
00317 
00318                 CComBSTR soldname = s;
00319                 CComVariant soldguid = pGUID;
00320 
00321                 if(SysStringLen(paradigmname) != 0) {
00322                         ver.Empty();
00323                         s = paradigmname;
00324                 }
00325                 if (paradigmGUID.vt != VT_EMPTY) {
00326                         ver.Empty();
00327                         if (CComVariant(true) == paradigmGUID)
00328                                 pGUID = NULLVARIANT; // use current version
00329                         else
00330                                 pGUID = paradigmGUID;
00331                 }
00332                 if (s.Length()) {
00333                         if (ver.Length()) {
00334                                 // Version string has precedence
00335                                 COMTHROW(OpenParadigm(s,ver));
00336                                 pGUID.Clear();
00337                                 COMTHROW(metapr->get_GUID(&pGUID));
00338                         }
00339                         else {
00340                                 OpenParadigm(s, &pGUID);
00341                                 ver.Empty();
00342                                 COMTHROW(metapr->get_Version(&ver));
00343                         }
00344                         bool guidchanged = false;
00345                         if(guidcmp(soldguid, pGUID)) {
00346                                 COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00347                                 try {
00348                                         CComPtr<IMgaFolder> rf;
00349                                         COMTHROW(get_RootFolder(&rf));
00350                                         HRESULT hr = ObjFor(rf)->CheckTree();
00351                                         if (FAILED(hr))
00352                                         {
00353                                                 throw_last_com_error(hr);
00354                                         }
00355                                         rf = 0;
00356                                         COMTHROW(CommitTransaction());
00357                                 } catch(hresult_exception &e) {
00358                                         lm->Flush();
00359                                         AbortTransaction();
00360                                         throw e;
00361                                 } catch(_com_error&) {
00362                                         lm->Flush();
00363                                         AbortTransaction();
00364                                         throw;
00365                                 }
00366 
00367                                 guidchanged = true;
00368                         }
00369                         if(s != soldname || guidchanged) {
00370                                 if(ro) COMTHROW(E_MGA_READ_ONLY_ACCESS);
00371                                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
00372                                 try {
00373                                         CoreObj  dataroot;
00374                                         COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00375                                         dataroot[ATTRID_PARADIGM] = s;
00376                                         dataroot[ATTRID_PARGUID] = pGUID;
00377                                         dataroot[ATTRID_PARVERSION] = ver;
00378                                         COMTHROW(CommitTransaction());
00379                                         opened = CHANGED;
00380                                         guidstat = DIRTY;
00381                                 } catch(hresult_exception &e) {
00382                                         lm->Flush();
00383                                         AbortTransaction();
00384                                         throw e;
00385                                 }
00386                         }
00387                 }
00388                 else COMTHROW(E_INVALID_USAGE);
00389                 StartAutoAddOns();
00390                 try {
00391                         COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00392                         GlobalNotify(GLOBALEVENT_OPEN_PROJECT);
00393                         COMTHROW(lm->Flush());
00394                         COMTHROW(CommitTransaction());
00395                 } catch(hresult_exception &e) {
00396                         lm->Flush();
00397                         AbortTransaction();
00398                         throw e;
00399                 }
00400                 MARKSIG('2');
00401         } 
00402         COMCATCH(
00403                 opened = CLOSED;
00404                 guidstat = CLEAN;
00405                 if (dataproject)
00406                         dataproject->CloseProject(VARIANT_TRUE);
00407                 if (metapr)
00408                         metapr->Close();
00409                 metapr = 0;
00410                 projconn.Empty(); 
00411                 parconn.Empty();
00412                 // We've already called SetErrorInfo, don't call it again
00413                 if (e.hr == E_MGA_COMPONENT_ERROR) {
00414                         return e.hr;
00415                 }
00416         )
00417 }
00418 
00419 STDMETHODIMP CMgaProject::Open(BSTR projectname, VARIANT_BOOL *ro_mode)
00420 {
00421         COMTRY {
00422                 if(opened != CLOSED) COMTHROW(E_MGA_PROJECT_OPEN);
00423                 CComBSTR s;
00424                 CComVariant pGUID;
00425                 CComBSTR ver;
00426                 CComPtr<ICoreMetaProject> genericproject;
00427                 CreateCoreMetaProject(genericproject, true); // will upgrade if old version
00428 
00429                 int undosize = getMaxUndoSize();
00430                 COMTHROW(dataproject->OpenProject2(projectname, undosize, genericproject, ro_mode));
00431                 
00432                 projconn = projectname;
00433 
00434                 opened = UNCHANGED;
00435                 guidstat = CLEAN;
00436             CComPtr<IMgaTerritory> lm;
00437             COMTHROW(CreateTerritory(NULL, &lm));
00438                 COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00439 
00440                 try {   
00441 
00442                         CoreObj  dataroot;
00443                         COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00444                     s=dataroot[ATTRID_PARADIGM];
00445                         mgaversion = dataroot[ATTRID_MGAVERSION];
00446                         if( mgaversion <= 1L) // Core layer changed the project by adding ATTRID_GUID1..4 for CCoreBinFile
00447                                 opened = CHANGED;
00448 
00449                         pGUID=CComVariant(dataroot[ATTRID_PARGUID]);
00450                         ver=dataroot[ATTRID_PARVERSION];
00451                         COMTHROW(lm->Flush());
00452                         COMTHROW(CommitTransaction());
00453                 } catch(hresult_exception &e) {
00454                         lm->Flush();
00455                         AbortTransaction();
00456                         throw e;
00457                 }
00458 
00459                 if(s.Length()) {
00460                         HRESULT hr = S_OK;
00461                         if (ver.Length()) {
00462                                 // Version string has precedence
00463                                 hr = OpenParadigm(s,ver);
00464                         }
00465                         else {
00466                                 OpenParadigm(s, &pGUID);
00467                         }
00468                         if (FAILED(hr))
00469                         {
00470                                 CComPtr<IErrorInfo> info;
00471                                 GetErrorInfo(0, &info);
00472                                 throw _com_error(hr, info, true);
00473                         }
00474                 }
00475                 else COMTHROW(E_MGA_MODULE_INCOMPATIBILITY);
00476 
00477                 CComVariant nGUID;
00478                 COMTHROW(metapr->get_GUID(&nGUID));
00479 
00480                 if(guidcmp(pGUID, nGUID)) {
00481                         COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00482                         try {
00483                                 CComPtr<IMgaFolder> rf;
00484                                 COMTHROW(get_RootFolder(&rf));
00485                                 COMTHROW(ObjFor(rf)->CheckTree());
00486                                 rf = 0;
00487                                 COMTHROW(CommitTransaction());
00488                         } catch(hresult_exception &e) {
00489                                 lm->Flush();
00490                                 AbortTransaction();
00491                                 throw e;
00492                         }
00493 
00494                         if (*ro_mode == VARIANT_FALSE) {
00495                                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
00496                                 try {
00497                                         CoreObj  dataroot;
00498                                         COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00499                                         dataroot[ATTRID_PARGUID] = nGUID;
00500                                         COMTHROW(CommitTransaction());
00501                                         opened = CHANGED;
00502                                         guidstat = DIRTY;
00503                                 } catch(hresult_exception &e) {
00504                                         lm->Flush();
00505                                         AbortTransaction();
00506                                         throw e;
00507                                 }
00508                         }
00509                 }
00510 
00511                 StartAutoAddOns();
00512 
00513                 try {
00514                         COMTHROW(BeginTransaction(lm, TRANSACTION_READ_ONLY));
00515                         GlobalNotify(GLOBALEVENT_OPEN_PROJECT);
00516                         COMTHROW(CommitTransaction());
00517                 } catch(hresult_exception &e) {
00518                         lm->Flush();
00519                         AbortTransaction();
00520                         throw e;
00521                 }
00522 
00523                 MARKSIG('2');
00524         } 
00525         COMCATCH(
00526                 opened = CLOSED;
00527                 if (dataproject)
00528                         dataproject->CloseProject(VARIANT_TRUE);
00529                 if (metapr)
00530                         metapr->Close();
00531                 metapr = 0;
00532                 projconn.Empty(); 
00533                 parconn.Empty();
00534                 // We've already called SetErrorInfo, don't call it again
00535                 if (e.hr == E_MGA_COMPONENT_ERROR) {
00536                         return e.hr;
00537                 }
00538         )
00539 }
00540 
00541 STDMETHODIMP CMgaProject::QueryProjectInfo(BSTR projectname, long *mgaversion, 
00542                                                                                    BSTR *paradigmname, 
00543                                                                                    BSTR *parversion,
00544                                                                                    VARIANT *paradigmGUID,
00545                                                                                    VARIANT_BOOL *ro_mode)
00546 {
00547         CComPtr<ICoreProject> dp;
00548         COMTRY {
00549                 CHECK_INSTRPAR(projectname);
00550                 CHECK_OUTPAR(mgaversion);
00551                 CHECK_OUTSTRPAR(paradigmname);
00552                 CHECK_OUTSTRPAR(parversion);
00553                 CHECK_OUTPAR(paradigmGUID);
00554                 CHECK_OUTPAR(ro_mode);
00555 
00556                 CComPtr<ICoreMetaProject> genericproject;
00557                 CreateCoreMetaProject(genericproject); // use mgaversion = 1 project model 
00558 
00559                 COMTHROW(dp.CoCreateInstance(__uuidof(CoreProject)));
00560                 COMTHROW(dp->OpenProject(projectname, genericproject, ro_mode));
00561                 
00562                 CComPtr<ICoreTerritory> tt;
00563                 COMTHROW(dp->CreateTerritory(&tt));
00564                 COMTHROW(dp->BeginTransaction(TRANSTYPE_READFIRST));
00565 
00566                 try {   
00567                         COMTHROW(dp->PushTerritory(tt));
00568 
00569                         CoreObj  dataroot;
00570                         COMTHROW(dp->get_RootObject(&dataroot.ComPtr()));
00571                     *paradigmname = CComBSTR(dataroot[ATTRID_PARADIGM]).Detach();
00572                     *parversion = CComBSTR(dataroot[ATTRID_PARVERSION]).Detach();
00573                     CComVariant(dataroot[ATTRID_PARGUID]).Detach(paradigmGUID);
00574                         *mgaversion = dataroot[ATTRID_MGAVERSION];
00575                         COMTHROW(dp->PopTerritory());
00576                 } catch(hresult_exception &) {
00577                         // FIXME
00578                         ;
00579                 }
00580                 dp->AbortTransaction(TRANSTYPE_ANY);
00581                 dp->CloseProject(VARIANT_FALSE);
00582         }
00583         COMCATCH(
00584                 if(dp) dp->CloseProject(VARIANT_FALSE);
00585         )
00586 }
00587 
00588 STDMETHODIMP CMgaProject::Save(BSTR newname, VARIANT_BOOL keepoldname)
00589 {
00590         COMTRY {
00591                 if(baseterr)
00592                         COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
00593                 {
00594                         CComPtr<IMgaTerritory> t;
00595                         COMTHROW(CreateTerritory(NULL, &t));
00596                         // if mga_ver<=1 the Core layer changed the project by adding ATTRID_GUID1..4
00597                         // (mgaversion <= 1L) -> (opened >= CHANGED)
00598                         ASSERT( !(mgaversion <= 1L) || opened >= CHANGED);
00599 
00600                         if(opened >= CHANGED) {
00601                                 COMTHROW(BeginTransaction(t, TRANSACTION_GENERAL));
00602                                 try {
00603                                         CoreObj self;
00604                                         COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00605                                         UpdateMGAVersion( self);
00606                                         FixupGUID();
00607                                         GlobalNotify(GLOBALEVENT_SAVE_PROJECT);
00608                                         COMTHROW(CommitTransaction());
00609                                 } catch(hresult_exception &) {
00610                                         t->Flush();
00611                                         AbortTransaction();
00612                                 }
00613                         }
00614                 }
00615                 HRESULT hr = dataproject->SaveProject(newname, keepoldname);
00616                 if (FAILED(hr))
00617                         return hr;
00618                 if(CComBSTR(newname).Length()) {
00619                         if (!keepoldname) {
00620                                 projconn = newname;
00621                                 opened = UNCHANGED;
00622                                 transactioncount = 0;
00623                         }
00624 
00625                 } else {
00626                         opened = UNCHANGED;
00627                         transactioncount = 0;
00628                 }
00629         }
00630         COMCATCH(;);
00631 }
00632 
00633 STDMETHODIMP CMgaProject::Close(VARIANT_BOOL abort)
00634 {
00635         if(opened == CLOSED) {
00636                 ASSERT(("Project is closed but transaction is active", !baseterr));
00637                 return S_OK;
00638         }
00639         
00640         COMTRY {
00641                 if(baseterr) COMTHROW(AbortTransaction());
00642                 {
00643                         CComPtr<IMgaTerritory> t;
00644                         COMTHROW(CreateTerritory(NULL, &t));
00645                         bool write = !abort && opened >= CHANGED;
00646                         COMTHROW(BeginTransaction(t, write ? TRANSACTION_GENERAL : TRANSACTION_READ_ONLY));
00647                         try {
00648                                 if(write) {
00649                                         CoreObj self;
00650                                         COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00651                                         FixupGUID();
00652                                 }
00653                                 GlobalNotify(GLOBALEVENT_CLOSE_PROJECT);
00654                                 COMTHROW(CommitTransaction());
00655                         } catch(hresult_exception &) {
00656                                 t->Flush();
00657                                 AbortTransaction();
00658                         }
00659                 }
00660                 
00661                 StopAutoAddOns();  // PETER: Moved these two lines here, otherwise addons won't receive notifications
00662                 RemoveClients();   //
00663 
00664                 if(dataproject) COMTHROW(dataproject->CloseProject(abort));
00665 
00666                 if(metapr) {
00667                         COMTHROW(metapr->Close());
00668                         metapr = 0;
00669                 }
00670 
00671             MARKSIG('8');
00672                 opened = CLOSED;
00673                 guidstat = CLEAN;
00674                 projconn.Empty(); 
00675                 parconn.Empty();
00676                 transactioncount = 0;
00677         }
00678         COMCATCH( opened = CLOSEERROR;);        //  You cannot rollback a failed Close completely, so I did not even try it.
00679 }
00680 
00681 #undef mgaproject
00682 
00683 
00684 // ----------------------------------------
00685 // Access the root nodes of data and meta
00686 // ----------------------------------------
00687 STDMETHODIMP CMgaProject::get_RootFolder(IMgaFolder **pVal)
00688 {
00689         COMTRY {
00690                 CHECK_OUTPTRPAR(pVal);
00691                 CoreObj  dataroot;
00692                 COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
00693                 CoreObjs s = dataroot[ATTRID_FPARENT + ATTRID_COLLECTION];
00694                 ITERATE_THROUGH(s) {
00695                         CComPtr<ICoreMetaObject> m;
00696                         metaid_type t;
00697                         COMTHROW(ITER->get_MetaObject(&m));
00698                         COMTHROW(m->get_MetaID(&t));
00699                         if(t == DTID_FOLDER) {
00700                                 ObjForCore(ITER)->getinterface(pVal);
00701                                 break;
00702                         }
00703                 }
00704                 if(*pVal == NULL) COMTHROW(E_MGA_MODULE_INCOMPATIBILITY);
00705     }
00706     COMCATCH(;);
00707 }
00708 
00709 
00710 STDMETHODIMP CMgaProject::get_RootMeta(IMgaMetaProject **pVal)
00711 {
00712         COMTRY {
00713                 if(metapr == 0) COMTHROW( E_MGA_PROJECT_NOT_OPEN );
00714                 SetNmspaceInMeta();
00715                 *pVal = metapr; (*pVal)->AddRef();
00716         } COMCATCH(;);
00717 }
00718 
00719 // ----------------------------------------
00720 // Filter and search functions
00721 // ----------------------------------------
00722 HRESULT CMgaProject::CreateFilter(IMgaFilter **newfilter) {
00723         COMTRY {
00724                 CHECK_OUTPTRPAR(newfilter);
00725                 CComPtr<CMgaFilter> filter;
00726                 CreateComObject(filter);
00727                 filter->setproject(this);
00728                 *newfilter = filter.Detach();
00729         } COMCATCH(;);
00730 }
00731 
00732 void recursefolders(CoreObj folder, CMgaFilter * filter, EXCOLLECTIONTYPE_FOR(MgaFCO) *q) {
00733         {
00734                 ITERATE_THROUGH(folder[ATTRID_FCOPARENT+ATTRID_COLLECTION]) {
00735                         if(ITER.IsFCO()) filter->searchFCOs(ITER, q);
00736                         else recursefolders(ITER, filter, q);
00737                 }
00738         }
00739 }
00740 
00741 STDMETHODIMP CMgaProject::AllFCOs(IMgaFilter *filter, IMgaFCOs ** fcos) {
00742         COMTRY {
00743                 CHECK_OUTPTRPAR(fcos);
00744                 CHECK_INPTRPAR(filter);   // project is checked in the following lines
00745                 CComPtr<IMgaProject> p;
00746                 COMTHROW(filter->get_Project(&p));
00747                 if(!COM_EQUAL(p, (IMgaProject *)this)) COMTHROW(E_MGA_FOREIGN_PROJECT);
00748 
00749                 CREATEEXCOLLECTION_FOR(MgaFCO, q);
00750                 CComPtr<IMgaFolder> rootf;
00751                 COMTHROW(get_RootFolder(&rootf));
00752                 recursefolders(CoreObj(rootf), reinterpret_cast<CMgaFilter *>(filter),  q);
00753                 *fcos = q.Detach();
00754     }
00755     COMCATCH(;);
00756 }
00757 
00758 STDMETHODIMP CMgaProject::GetFCOByID(BSTR id, IMgaFCO **pVal) {
00759         COMTRY {
00760                 CComPtr<IMgaObject> p;
00761                 COMTHROW(GetObjectByID(id,&p));
00762                 COMTHROW(p.QueryInterface(pVal));
00763     } COMCATCH(;);
00764 }
00765 
00766 STDMETHODIMP CMgaProject::GetObjectByID(BSTR id, IMgaObject **pVal)
00767 {
00768 
00769         COMTRY {
00770                 CHECK_INSTRPAR(id);
00771                 CHECK_OUTPTRPAR(pVal);
00772                 metaid_type mm; // short
00773                 objid_type ss;  // long
00774                 if (SysStringLen(id) == 0)
00775                 {
00776                         COMTHROW(E_MGA_BAD_ID);
00777                 }
00778                 if( swscanf(id,OLESTR("id-%04hx-%08lx"), &mm, &ss) != 2 || 
00779                         mm < DTID_MODEL || mm > DTID_FOLDER) COMTHROW(E_MGA_BAD_ID);
00780                 CoreObj obj;
00781                 COMTHROW(dataproject->get_Object(mm,ss,&obj.ComPtr()));
00782                 if (obj)
00783                         ObjForCore(obj)->getinterface(pVal);
00784                 else
00785                         COMTHROW(E_MGA_BAD_ID);
00786     } COMCATCH(;);
00787 }
00788 
00789 STDMETHODIMP CMgaProject::GetFCOsByName(BSTR name, IMgaFCOs **pVal)
00790 {
00791 
00792         COMTRY {
00793 // ADD CODE
00794 //                              (*pVal)->Open()
00795                 COMTHROW(E_MGA_NOT_IMPLEMENTED);
00796     }
00797     COMCATCH(;);
00798 }
00799 
00800 STDMETHODIMP CMgaProject::GetFolderByPath(BSTR path, IMgaFolder **pVal)
00801 {
00802 
00803         COMTRY {
00804 // ADD CODE
00805 //                              (*pVal)->Open()
00806                 COMTHROW(E_MGA_NOT_IMPLEMENTED);
00807     }
00808     COMCATCH(;);
00809 }
00810 
00811 // see FCO::get_ObjectByPath for details in MgaFolder.cpp 
00812 STDMETHODIMP CMgaProject::get_ObjectByPath(BSTR path, IMgaObject **pVal) {
00813         COMTRY {
00814                 CHECK_INSTRPAR(path);
00815                 CHECK_OUTPTRPAR(pVal);
00816                 CComPtr<IMgaFolder> f;
00817                 COMTHROW(get_RootFolder(&f));
00818                 COMTHROW(f->get_ObjectByPath(path, pVal));
00819         } COMCATCH(;);
00820 }
00821 
00822 STDMETHODIMP CMgaProject::get_NthObjectByPath(long n_th, BSTR path, IMgaObject **pVal) {
00823         COMTRY {
00824                 CHECK_INSTRPAR(path);
00825                 CHECK_OUTPTRPAR(pVal);
00826                 CComPtr<IMgaFolder> f;
00827                 COMTHROW(get_RootFolder(&f));
00828                 COMTHROW(f->get_NthObjectByPath(n_th, path, pVal));
00829         } COMCATCH(;);
00830 }
00831 
00832 // ----------------------------------------
00833 // Access project properties
00834 // ----------------------------------------
00835 STDMETHODIMP CMgaProject::GetStatistics(BSTR *statstr)
00836 {
00837 
00838         COMTRY {
00839 // ADD CODE
00840     }
00841     COMCATCH(;);
00842 }
00843 
00844 
00845 
00846 STDMETHODIMP CMgaProject::get_CreateTime(BSTR *pVal)
00847 {
00848 
00849         COMTRY {
00850                 CoreObj self;
00851                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00852                 *pVal = CComBSTR(self[ATTRID_CDATE]).Detach();
00853         }
00854     COMCATCH(;);
00855 }
00856 
00857 STDMETHODIMP CMgaProject::get_ChangeTime(BSTR *pVal)
00858 {
00859 
00860         COMTRY {
00861                 CoreObj self;
00862                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00863                 *pVal = CComBSTR(self[ATTRID_MDATE]).Detach();
00864     }
00865     COMCATCH(;);
00866 }
00867 
00868 STDMETHODIMP CMgaProject::get_Author(BSTR *pVal)
00869 {
00870 
00871         COMTRY {
00872                 CoreObj self;
00873                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00874                 *pVal = CComBSTR(self[ATTRID_CREATOR]).Detach();
00875     }
00876     COMCATCH(;);
00877 }
00878 
00879 STDMETHODIMP CMgaProject::put_Author(BSTR newVal)
00880 {
00881 
00882         COMTRY_IN_TRANSACTION {
00883                 CoreObj self;
00884                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00885                 self[ATTRID_CREATOR] = newVal;
00886                 notifyqueueprocessed = true;
00887                 COMTHROW(GlobalNotify(GLOBALEVENT_PROJECT_PROPERTIES));
00888     }
00889     COMCATCH_IN_TRANSACTION(;);
00890 }
00891 
00892 STDMETHODIMP CMgaProject::get_MetaGUID(VARIANT *pVal)
00893 {
00894 
00895         COMTRY
00896         {
00897                 CHECK_OUTPAR(pVal);
00898                 CoreObj self;
00899                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00900                 CComVariant p = self[ATTRID_PARGUID];
00901 
00902                 if( p.vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(p) != sizeof(::GUID) )
00903                 {
00904                         ::GUID guid;
00905                         memset(&guid, 0, sizeof(::GUID));
00906 
00907                         CopyTo(guid, p);
00908                 }
00909                 p.Detach(pVal);
00910         }
00911         COMCATCH(;)
00912 }
00913 
00914 STDMETHODIMP CMgaProject::get_MetaName(BSTR *pVal)
00915 {
00916 
00917         COMTRY
00918         {
00919                 CHECK_OUTSTRPAR(pVal);
00920                 CoreObj self;
00921                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00922                 CComBSTR p = self[ATTRID_PARADIGM];
00923 
00924                 *pVal=p.Detach();
00925         }
00926         COMCATCH(;)
00927 }
00928 
00929 STDMETHODIMP CMgaProject::get_MetaVersion(BSTR *pVal)
00930 {
00931 
00932         COMTRY
00933         {
00934                 CHECK_OUTSTRPAR(pVal);
00935                 CoreObj self;
00936                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00937                 CComBSTR p = self[ATTRID_PARVERSION];
00938 
00939                 *pVal=p.Detach();
00940         }
00941         COMCATCH(;)
00942 }
00943 
00944 STDMETHODIMP CMgaProject::get_GUID(VARIANT *pVal)
00945 {
00946 
00947         COMTRY
00948         {
00949                 CHECK_OUTPAR(pVal);
00950                 
00951                 FixupGUID(false);
00952 
00953                 CoreObj self;
00954                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00955                 CComVariant p = self[ATTRID_GUID];
00956 
00957                 
00958                 if (guidstat == PENDING) {
00959                         p = pendingguid;
00960                 }
00961                 
00962                 if( p.vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(p) != sizeof(::GUID) )
00963                 {
00964                         ::GUID guid;
00965                         memset(&guid, 0, sizeof(::GUID));
00966 
00967                         CopyTo(guid, p);
00968                 }
00969                 p.Detach(pVal);
00970         }
00971         COMCATCH(;)
00972 }
00973 
00974 
00975 STDMETHODIMP CMgaProject::put_GUID(VARIANT newVal)
00976 {
00977         COMTRY_IN_TRANSACTION {
00978                 CHECK_INPAR(newVal);
00979                 CoreObj self;
00980                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
00981 
00982                 if( newVal.vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(newVal) != sizeof(::GUID) )
00983                         COMTHROW(E_INVALIDARG);
00984 
00985                 self[ATTRID_GUID] = newVal;
00986                 guidstat = MANUAL;
00987                 notifyqueueprocessed = true;
00988                 COMTHROW(GlobalNotify(GLOBALEVENT_PROJECT_PROPERTIES));
00989     }
00990     COMCATCH_IN_TRANSACTION(;);
00991 }
00992 
00993 
00994 STDMETHODIMP CMgaProject::get_Comment(BSTR *pVal)
00995 {
00996 
00997         COMTRY {
00998                 CoreObj self;
00999                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01000                 *pVal = CComBSTR(self[ATTRID_EXTDATA]).Detach();
01001     }
01002     COMCATCH(;);
01003 }
01004 
01005 STDMETHODIMP CMgaProject::put_Comment(BSTR newVal)
01006 {
01007 
01008         COMTRY_IN_TRANSACTION {
01009                 CoreObj self;
01010                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01011                 self[ATTRID_EXTDATA] = newVal;
01012                 notifyqueueprocessed = true;
01013                 COMTHROW(GlobalNotify(GLOBALEVENT_PROJECT_PROPERTIES));
01014     }
01015     COMCATCH_IN_TRANSACTION(;);
01016 }
01017 
01018 STDMETHODIMP CMgaProject::put_Name(BSTR newVal)
01019 {
01020 
01021         COMTRY_IN_TRANSACTION {
01022                 CHECK_INSTRPAR(newVal);
01023                 CoreObj self;
01024                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01025                 self[ATTRID_NAME] = newVal;
01026                 notifyqueueprocessed = true;
01027                 COMTHROW(GlobalNotify(GLOBALEVENT_PROJECT_PROPERTIES));
01028     }
01029     COMCATCH_IN_TRANSACTION(;);
01030 }
01031 
01032 STDMETHODIMP CMgaProject::put_Version(BSTR newVal)
01033 {
01034 
01035         COMTRY_IN_TRANSACTION {
01036                 CHECK_INSTRPAR(newVal);
01037                 CoreObj self;
01038                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01039                 self[ATTRID_VERSION] = newVal;
01040                 notifyqueueprocessed = true;
01041                 COMTHROW(GlobalNotify(GLOBALEVENT_PROJECT_PROPERTIES));
01042     }
01043     COMCATCH_IN_TRANSACTION(;);
01044 }
01045 
01046 
01047 STDMETHODIMP CMgaProject::get_Name(BSTR *pVal)
01048 {
01049 
01050         COMTRY {
01051                 CHECK_OUTSTRPAR(pVal);
01052                 CoreObj self;
01053                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01054                 CComBSTR s = self[ATTRID_NAME];
01055                 *pVal = s.Detach();
01056     }
01057     COMCATCH(;);
01058 }
01059 
01060 STDMETHODIMP CMgaProject::get_Version(BSTR *pVal)
01061 {
01062 
01063         COMTRY {
01064                 CHECK_OUTSTRPAR(pVal);
01065                 CoreObj self;
01066                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01067                 CComBSTR s = self[ATTRID_VERSION];
01068                 *pVal = s.Detach();
01069     }
01070     COMCATCH(;);
01071 }
01072 
01073 
01074 STDMETHODIMP CMgaProject::get_ProjectConnStr(BSTR *pVal)
01075 {
01076         COMTRY {
01077                 CHECK_OUTSTRPAR(pVal);
01078                 CComBSTR s = projconn;
01079                 *pVal = s.Detach();
01080     }
01081     COMCATCH(;);
01082 }
01083 
01084 STDMETHODIMP CMgaProject::get_ParadigmConnStr(BSTR *pVal)
01085 {
01086         COMTRY {
01087                 CHECK_OUTSTRPAR(pVal);
01088                 CComBSTR s = parconn;
01089                 *pVal = s.Detach();
01090     }
01091     COMCATCH(;);
01092 }
01093 
01094 
01096 // ----------------------------------------
01097 // TRANSACTION HANDLING & NOTIFICATION 
01098 // ----------------------------------------////////////////////////////////////////////////////////////////////////////////////////////
01100 
01101 
01102 
01103 STDMETHODIMP CMgaProject::CreateTerritory(IMgaEventSink *sink, IMgaTerritory **pp, IMgaEventSink *rwsink) {
01104         COMTRY {
01105                 CHECK_OUTPTRPAR(pp);
01106 // MUST NOT RETURN
01107                 CComPtr<ICoreTerritory> tt;
01108                 COMTHROW(dataproject->CreateTerritory(&tt)); // terge ?? 
01109 // MUST SUCCEED
01110                 CComPtr< CMgaTerritory > ster;
01111                 CreateComObject(ster);
01112                 ster->coreterr = tt;
01113                 ster->mgaproject = this;; 
01114                 allterrs.push_front(ster);
01115                 ster->handler=sink;
01116                 ster->rwhandler=rwsink;
01117                 *pp = ster.Detach();
01118     }
01119     COMCATCH(;);
01120 }
01121 
01122 STDMETHODIMP CMgaProject::CreateTerritoryWithoutSink(IMgaTerritory **pp) {
01123         return CreateTerritory(NULL, pp, NULL);
01124 }
01125 
01126 STDMETHODIMP CMgaProject::CreateAddOn(IMgaEventSink *sink, IMgaAddOn **pp) {
01127         COMTRY {
01128                 CHECK_INPTRPAR(sink);
01129                 CHECK_OUTPTRPAR(pp);
01130 // MUST NOT RETURN
01131 
01132                 
01133                 if(!reserveterr) {
01134                         CComPtr<IMgaTerritory> r;
01135                         COMTHROW(CreateTerritory(NULL, &r));
01136                         reserveterr = static_cast<CMgaTerritory *>(r.p);
01137                 }
01138 // MUST SUCCEED
01139                 CComPtr< CMgaAddOn > saddon;
01140                 CreateComObject(saddon);
01141                 saddon->mgaproject = this;
01142                 saddon->progid = autoaddoncreate_progid;
01143                 alladdons.push_front(saddon);
01144                 saddon->handler=sink;
01145                 if(inautoaddoncreate) {
01146                         saddon->SetAutomatic();
01147                 }
01148                 *pp = saddon.Detach();
01149     }
01150     COMCATCH(;);
01151 
01152 }
01153 
01154 
01155 
01156 STDMETHODIMP CMgaProject::get_ActiveTerritory(IMgaTerritory **aterr) {
01157         COMTRY {
01158                 CHECK_OUTPTRPAR(aterr);
01159                 if((*aterr = baseterr) != NULL) (*aterr)->AddRef();
01160         } COMCATCH(;)
01161 }
01162 
01163 STDMETHODIMP CMgaProject::get_AddOns(IMgaAddOns **addons) {
01164         COMTRY {
01165                 CHECK_OUTPTRPAR(addons);
01166                 CREATECOLLECTION_FOR(IMgaAddOn, q);
01167                 for(addoncoll::iterator j = alladdons.begin(); j != alladdons.end(); ++j) {
01168                         q->Add(*j);
01169                 }
01170                 *addons = q.Detach();
01171         } COMCATCH(;)
01172 }
01173 
01174 STDMETHODIMP CMgaProject::get_Clients(IMgaClients **clients) {
01175         COMTRY {
01176                 CHECK_OUTPTRPAR(clients);
01177                 CREATECOLLECTION_FOR(IMgaClient, q);
01178                 for(clientcoll::iterator j = allclients.begin(); j != allclients.end(); ++j) {
01179                         q->Add(*j);
01180                 }
01181                 *clients = q.Detach();
01182         } COMCATCH(;)
01183 }
01184 
01185 STDMETHODIMP CMgaProject::RegisterClient(BSTR name, IDispatch *OLEServer, IMgaClient **pVal) {
01186         COMTRY {
01187                 CHECK_INPTRPAR(OLEServer);
01188                 CHECK_INSTRPAR(name);
01189 
01190                 CComPtr< CMgaClient > client;
01191                 CreateComObject(client);
01192                 client->active = true;
01193                 client->mgaproject = this;
01194                 client->ole_server = OLEServer;
01195                 client->name = name;
01196                 allclients.push_front(client);
01197                 *pVal = client.Detach();
01198                 // TODO register only if not registered
01199     }
01200     COMCATCH(;);
01201 }
01202 
01203 STDMETHODIMP CMgaProject::GetClientByName(BSTR name, IMgaClient **pVal) {
01204         COMTRY {
01205                 CHECK_INSTRPAR(name);
01206                 clientcoll::iterator j;
01207                 for(j = allclients.begin(); j != allclients.end(); ++j) {
01208                         CComPtr< CMgaClient > client(*j);
01209                         if (client->name == name) {
01210                                 *pVal = client.Detach();
01211                                 break;
01212                         }
01213                 }
01214                 if(j == allclients.end()) 
01215                         return E_MGA_NAME_NOT_FOUND;
01216         }
01217     COMCATCH(;);
01218 }
01219 
01220 
01221 STDMETHODIMP CMgaProject::get_Territories(IMgaTerritories **terrs) {
01222         COMTRY {
01223                 CHECK_OUTPTRPAR(terrs);
01224                 CREATECOLLECTION_FOR2(IMgaTerritory, IMgaTerritories, q);
01225                 for(tercoll::iterator j = allterrs.begin(); j != allterrs.end(); ++j) {
01226                         q->Add(*j);
01227                 }
01228                 *terrs = q.Detach();
01229         } COMCATCH(;)
01230 }
01231 
01232 STDMETHODIMP CMgaProject::get_AddOnComponents(IMgaComponents **comps) {
01233         COMTRY {
01234                 CHECK_OUTPTRPAR(comps);
01235                 CREATECOLLECTION_FOR(IMgaComponent, q);
01236                 for(compcoll::iterator j = autocomps.begin(); j != autocomps.end(); ++j) {
01237                         q->Add(*j);
01238                 }
01239                 *comps = q.Detach();
01240         } COMCATCH(;)
01241 }
01242 
01243 STDMETHODIMP CMgaProject::EnableAutoAddOns(VARIANT_BOOL bEnable) {
01244         COMTRY {
01245                 if(baseterr) COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01246                 bool bnew = (bEnable == VARIANT_TRUE);
01247                 if(bnew == autoaddons) return S_OK;
01248                 autoaddons = bnew;
01249                 if(opened != CLOSED) {
01250                         if(autoaddons) StartAutoAddOns();
01251                         else StopAutoAddOns();
01252                 }
01253         } COMCATCH(;)
01254 }
01255 
01256 
01257 void CMgaProject::StartAutoAddOns() {
01258         if(!autoaddons) return;
01259 #ifdef DEBUG
01260         for(addoncoll::iterator j = alladdons.begin(); j != alladdons.end(); ++j) {
01261                 ASSERT(!(*j)->IsAutomatic());
01262         }
01263 #endif
01264         CComPtr<IMgaRegistrar> reg;
01265         CComBSTR paradigm;
01266         COMTHROW(metapr->get_Name(&paradigm));
01267         CComVariant progids;
01268         COMTHROW(reg.CoCreateInstance(OLESTR("Mga.MgaRegistrar")));
01269         COMTHROW(reg->get_AssociatedComponents(paradigm, COMPONENTTYPE_ADDON, REGACCESS_BOTH, &progids));
01270         long p = GetArrayLength(progids);
01271         ASSERT(p >= 0);
01272         if(p)  {
01273                 std::vector<CComBstrObj> vec;
01274                 vec.resize(p);
01275                 CopyTo(progids, &vec[0], (&vec[0])+vec.size());
01276                 inautoaddoncreate = true;
01277                 CComBSTR errs;
01278                 for(std::vector<CComBstrObj>::iterator i = vec.begin(); i < vec.end(); ++i) {
01279                         try {
01280                                 CComPtr<IMgaComponent> addon;
01281                                 autoaddoncreate_progid = *i;
01282                                 COMTHROW(CreateMgaComponent(addon, *i)); // Was: COMTHROW( addon.CoCreateInstance(*i) );
01283                                 ASSERT( addon != NULL );
01284 
01285                                 COMTHROW( addon->Initialize(this));
01286                                 autocomps.push_front(addon.Detach());
01287                         } catch(hresult_exception &e) {
01288                                 BSTR err = NULL;
01289                                 GetErrorInfo(e.hr, &err);
01290                                 errs += " ";
01291                                 errs += i->p;
01292                                 errs += ": ";
01293                                 errs += err;
01294                         }
01295                 }
01296                 inautoaddoncreate = false;
01297                 autoaddoncreate_progid = L"";
01298                 if (errs) {
01299                         SetErrorInfo(_bstr_t(L"Could not create AddOn: ") + static_cast<const wchar_t*>(errs));
01300                         COMTHROW(E_MGA_COMPONENT_ERROR); // change error type
01301                 }               
01302         }
01303 //      SetAutomatic();
01304         
01305 }
01306 
01307 
01308 MIDL_INTERFACE("805D7A98-D4AF-3F0F-967F-E5CF45312D2C")
01309 IDisposable : public IDispatch {
01310 public:
01311     virtual VOID STDMETHODCALLTYPE Dispose() = 0;
01312 };
01313 
01314 void CMgaProject::StopAutoAddOns() {
01315         while(!autocomps.empty()) {
01316                         CComPtr<IMgaComponent> addon;
01317                         addon.Attach(autocomps.front());
01318                         autocomps.pop_front();
01319                         CComPtr<IDisposable> disposable;
01320                         if (SUCCEEDED(addon->QueryInterface(&disposable)))
01321                         {
01322                                 disposable->Dispose();
01323                         }
01324                         addon.Release();
01325         }
01326 #ifdef DEBUG
01327                 for(addoncoll::iterator j = alladdons.begin(); j != alladdons.end();++j) {
01328                         ASSERT(!(*j)->IsAutomatic());
01329                 }
01330 #endif
01331 }
01332 
01333 void CMgaProject::RemoveClients() {
01334         while(!allclients.empty()) {
01335                         CComPtr< CMgaClient > client;
01336                         client = allclients.front();
01337                         client->active = false;
01338                         allclients.pop_front();
01339         }
01340 }
01341 
01342 
01343 STDMETHODIMP CMgaProject::get_ProjectStatus(long *status) {
01344         COMTRY {
01345                 CHECK_OUTPAR(status);
01346                 if(opened == CLOSED) {
01347                         *status  = 0;
01348                 }       
01349                 else if(opened == CLOSEERROR) {
01350                         *status = 0x80000000;
01351                 }
01352                 else {
01353                         *status = 1 + (opened == CHANGED ? 4 : 0) + (baseterr ? 8 : 0) + (read_only ? 16 : 0);
01354                 }
01355         } COMCATCH(;);
01356 }
01357 
01358 STDMETHODIMP CMgaProject::BeginTransaction(IMgaTerritory *ter, transactiontype_enum mode)
01359 {
01360         COMTRY {
01361                 ASSERT(temporalobjs.empty());
01362                 while (temporalobjs.size())
01363                         temporalobjs.pop();
01364                 ASSERT(changedobjs.empty());
01365                 while (changedobjs.size())
01366                         changedobjs.pop();
01367                 ASSERT(notifyobjs.empty());
01368                 while (notifyobjs.size())
01369                         notifyobjs.pop();
01370                 CComPtr<IMgaTerritory> ttemp;
01371                 if(baseterr)
01372                         COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01373                 if(!ter) {
01374                         COMTHROW(CreateTerritory(NULL,&ttemp));
01375                         ter = ttemp;
01376                 }
01377                 ASSERT(mode == TRANSACTION_GENERAL || mode == TRANSACTION_READ_ONLY  || mode == TRANSACTION_NON_NESTED);
01378                 CComPtr<IMgaProject> p;
01379                 COMTHROW(ter->get_Project(&p));
01380                 if (p != this)
01381                         COMTHROW(E_MGA_FOREIGN_OBJECT);
01382                 CMgaTerritory *t = static_cast<CMgaTerritory *>(ter);
01383                 if (!t->coreterr)
01384                         COMTHROW(E_MGA_TARGET_DESTROYED);
01385                 read_only = (mode == TRANSACTION_READ_ONLY);
01386                 non_nestable = (mode == TRANSACTION_NON_NESTED);
01387                 // this call fails if the project has been closed (maybe we're being called by an FCO destructor)
01388                 HRESULT hr = dataproject->BeginTransaction(read_only? TRANSTYPE_READFIRST : TRANSTYPE_FIRST);
01389                 if (FAILED(hr))
01390                         COMRETURN(hr);
01391                 checkofftemporary = false;
01392                 in_nested = false;
01393                 must_abort = false;
01394                 hr = dataproject->PushTerritory(t->coreterr);
01395                 if (FAILED(hr))
01396                         COMRETURN(hr);
01397                 baseterr = activeterr = t;
01398                 notifyqueueprocessed = false;
01399                 MARKSIG('3');
01400     }
01401     COMCATCH(;);
01402 }
01403 
01404 STDMETHODIMP CMgaProject::BeginTransactionInNewTerr( transactiontype_enum mode, IMgaTerritory **ter)
01405 {
01406         COMTRY {
01407                 if(baseterr) COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01408 
01409                 // create a new territory
01410                 CComPtr<IMgaTerritory> ttemp;
01411                 COMTHROW(CreateTerritory(NULL,&ttemp));
01412                 
01413                 // begin transaction
01414                 BeginTransaction( ttemp, mode);
01415                 
01416                 // [out, return] parameter
01417                 *ter = ttemp.Detach();
01418         }
01419         COMCATCH(;);
01420 }
01421 
01422 STDMETHODIMP CMgaProject::CommitTransaction()
01423 {
01424         COMTRY {
01425                 ASSERT(!in_nested);
01426                 if (!baseterr)
01427                         COMTHROW(E_MGA_NOT_IN_TRANSACTION);
01428                 if (checkoff)
01429                         COMTHROW(CheckSupress(VARIANT_FALSE));
01430                 while (!temporalobjs.empty()) {
01431                         temporalobjs.front()->objrecordchange();
01432                         temporalobjs.pop();
01433                 }
01434                 if(!notifyobjs.empty()) {
01435                         CoreObj self;
01436                         COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01437 //                      self[ATTRID_MDATE] = Now();
01438                 }
01439                 HRESULT hr = CommitNotify();
01440                 if (!temporalobjs.empty()) // CommitNotify may make changes. Notify only territories
01441                 {
01442                         while (!temporalobjs.empty()) {
01443                                 temporalobjs.front()->objrecordchange();
01444                                 temporalobjs.pop();
01445                         }
01446                         while (!changedobjs.empty()) {
01447                                 FCOPtr f = changedobjs.front();
01448                                 changedobjs.pop();
01449                         }
01450                         CommitNotify();
01451                         ASSERT(temporalobjs.empty());
01452                 }
01453                 if (FAILED(hr))
01454                         return hr;
01455                 COMTHROW(dataproject->PopTerritory());
01456                 short nestedCount;
01457                 COMTHROW(dataproject->get_NestedTransactionCount(&nestedCount));
01458                 if (nestedCount == 1 && !read_only)
01459                         COMTHROW(GlobalNotify(GLOBALEVENT_COMMIT_TRANSACTION));
01460                 COMTHROW(dataproject->CommitTransaction(read_only ? TRANSTYPE_READFIRST: TRANSTYPE_FIRST));
01461         baseterr = activeterr= NULL;
01462                 read_only = false;
01463 
01464                 if(notifyqueueprocessed) {
01465                         transactioncount++;
01466                         opened = CHANGED;
01467                         if (guidstat == MANUAL) {
01468                                 guidstat = CLEAN;
01469                         }
01470                         else {
01471                                 guidstat = DIRTY;
01472                         }
01473                 }
01474             MARKSIG('7');
01475     }
01476     COMCATCH(;);
01477 }
01478 
01479 
01480 
01481 STDMETHODIMP CMgaProject::AbortTransaction() {
01482         COMTRY {
01483                 ASSERT(!in_nested);
01484                 if(!baseterr) COMTHROW(E_MGA_NOT_IN_TRANSACTION);
01485                 aurcnt++;
01486                 //COMTHROW(dataproject->PopTerritory()); BGY: see committransaction, it is already popped
01487                 COMTHROW(dataproject->AbortTransaction(read_only ? TRANSTYPE_READFIRST:TRANSTYPE_FIRST));
01488                 baseterr = activeterr= NULL;
01489                 deferredchecks.clear();
01490                 checkoff = false;
01491                 while(!changedobjs.empty()) {
01492                         changedobjs.front()->objforgetrwnotify();
01493                         changedobjs.front()->apool.clear();
01494                         changedobjs.pop();
01495                 }
01496                 while(!notifyobjs.empty()) {
01497                         notifyobjs.front()->objforgetnotify();
01498                         notifyobjs.pop();
01499                 }
01500                 while(!temporalobjs.empty()) {
01501                         temporalobjs.front()->objforgetchange();
01502                         temporalobjs.pop();
01503                 }
01504                 read_only = true;
01505                 {
01506                         CComPtr<IMgaTerritory> t;
01507                         COMTHROW(CreateTerritory(NULL, &t));
01508                         // If this fails, Mga likely didn't close a nested tx
01509                         // ASSERT(dataproject->GetNestedTrCount == 1)
01510                         COMTHROW(BeginTransaction(t, TRANSACTION_READ_ONLY));
01511                         GlobalNotify(GLOBALEVENT_ABORT_TRANSACTION);
01512                         COMTHROW(CommitTransaction());
01513                 }
01514                 read_only = false;
01515             MARKSIG('6');
01516     }
01517     COMCATCH(read_only = false;);
01518 }
01519 
01520 
01521 STDMETHODIMP CMgaProject::CheckSupress(VARIANT_BOOL s) {
01522         COMTRY_IN_TRANSACTION {
01523                 if (s)
01524                         checkoff = true;
01525                 else
01526                 { 
01527                         for(objhash::iterator i = deferredchecks.begin(); i != deferredchecks.end(); ++i) {
01528                                 if (GetMetaID((*i)->self) == DTID_FOLDER)
01529                                         COMTHROW((*i)->Check());
01530                                 else
01531                                         (*i)->CheckRCS();
01532                         }
01533                         deferredchecks.clear();
01534                         checkoff = false;
01535                 }
01536         } COMCATCH_IN_TRANSACTION(;);
01537 }
01538 
01539 
01540 STDMETHODIMP CMgaProject::GlobalNotify(globalevent_enum msg) {
01541   COMTRY {
01542                 {
01543                         addoncoll::iterator i = alladdons.begin(), end = alladdons.end();
01544                         if(i != end) {
01545                                 COMTHROW(pushterr(*reserveterr));
01546 // The addon may Destroy() itself or release a reference while being notified
01547 // But other addons are expected to remain in the list
01548                                 while(i != end) {
01549                                         CComPtr<CMgaAddOn> addon(*i++); // set the iterator to the next addon (since it may be deleted)
01550                                         if(msg == GLOBALEVENT_NOTIFICATION_READY && addon->notified == false) continue;
01551                                         if(addon->handler->GlobalEvent(msg)!= S_OK) {
01552                                                 ASSERT(("Global notification failed", false));
01553                                         }
01554                                 }
01555                                 COMTHROW(popterr());
01556                         }
01557                 }
01558                 tercoll::iterator i = allterrs.begin(), end = allterrs.end();
01559                 for(;i != end; ++i) {
01560                         if(msg == GLOBALEVENT_NOTIFICATION_READY && (*i)->notified == false) continue;
01561                         else (*i)->notified = false;
01562                         if((*i)->handler) {
01563                                 COMTHROW(pushterr(**i));
01564                                 (*i)->handler->GlobalEvent(msg); // Silently ignore failures
01565                                 COMTHROW(popterr());
01566                         }
01567                 }
01568   } COMCATCH(;);
01569 }
01570 
01571 STDMETHODIMP CMgaProject::Notify(globalevent_enum event) {
01572         COMTRY {
01573                 if (baseterr)
01574                         COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01575 
01576                 CComPtr<IMgaTerritory> t;
01577                 COMTHROW(CreateTerritory(NULL, &t));
01578                 COMTHROW(BeginTransaction(t, TRANSACTION_READ_ONLY));
01579                 GlobalNotify(event);
01580                 COMTHROW(CommitTransaction());
01581     }
01582     COMCATCH(;);
01583 }
01584 
01585 
01586 STDMETHODIMP CMgaProject::CommitNotify() {
01587   if(read_only) {
01588                 ASSERT(changedobjs.empty() && notifyobjs.empty());
01589                 return S_OK;
01590   }
01591   COMTRY {
01592                 if(!baseterr)
01593                                         COMTHROW(E_MGA_NOT_IN_TRANSACTION);
01594 
01595                 if(!changedobjs.empty())
01596                                         notifyqueueprocessed = true;
01597                 while(!changedobjs.empty()) {
01598                                 FCOPtr f = changedobjs.front();
01599                                 changedobjs.pop();
01600 
01601                                                                 HRESULT hr = f->objrwnotify();
01602                                                                 if (FAILED(hr))
01603                                                                 {
01604                                                                         read_only = false;
01605                                                                         return hr;
01606                                                                 }
01607                 }
01608 
01609                 read_only = true;
01610                 while(!notifyobjs.empty()) {
01611                                 FCOPtr f = notifyobjs.front();
01612                                 notifyobjs.pop();
01613                                 if(f->objnotify() != S_OK) {
01614                                         ASSERT(("Notification failed", false));
01615                                 }
01616                 }
01617                 COMTHROW(GlobalNotify(GLOBALEVENT_NOTIFICATION_READY));
01618                 read_only = false;
01619   } COMCATCH( read_only = false;);
01620 }
01621 
01622 
01623 
01624 bool CMgaProject::alreadynested() { return in_nested; }
01625 
01626 HRESULT CMgaProject::beginnested() {
01627         ASSERT(!in_nested);
01628 
01629         ASSERT(objstocheck.empty());
01630         objstocheck.clear();            
01631 
01632         HRESULT hr;
01633         if (non_nestable)
01634                 hr = must_abort ? E_MGA_MUST_ABORT : S_OK;
01635         else
01636                 hr = dataproject->BeginTransaction(TRANSTYPE_NESTED);
01637 
01638     MARKSIG('4');
01639         if (hr == S_OK)
01640                 in_nested = true;
01641         return hr;
01642 }
01643 
01644 HRESULT CMgaProject::commitnested() {
01645         ASSERT(in_nested);
01646 
01647         ASSERT(objstocheck.empty());
01648         objstocheck.clear();
01649 
01650         HRESULT hr = S_OK;
01651         if (!non_nestable)
01652                 hr = dataproject->CommitTransaction(TRANSTYPE_NESTED);
01653     MARKSIG('6');
01654         if (hr != S_OK)
01655                 abortnested();
01656         else { 
01657                 in_nested = false;
01658                 while(!temporalobjs.empty()) {
01659                         temporalobjs.front()->objrecordchange();
01660                         temporalobjs.pop();
01661                 }
01662         }
01663         return hr;
01664 }
01665 
01666 HRESULT CMgaProject::abortnested() {
01667         ASSERT(in_nested);
01668         objstocheck.clear();
01669         in_nested = false;
01670         while(!temporalobjs.empty()) {
01671                         temporalobjs.front()->objforgetchange();
01672                         temporalobjs.pop();
01673         }
01674     MARKSIG('5');
01675         must_abort = true;
01676         if (non_nestable)
01677                 return S_OK;
01678         else
01679                 return dataproject->AbortTransaction(TRANSTYPE_NESTED);
01680 }
01681 
01682 
01683 HRESULT CMgaProject::pushterr(CMgaTerritory &ter) {
01684         COMTRY {
01685                 ASSERT(("Territorys overwrite each other",activeterr==baseterr));
01686                 activeterr = &ter;
01687                 COMTHROW(dataproject->PushTerritory(ter.coreterr));
01688         } COMCATCH(;);
01689 }
01690 
01691 HRESULT CMgaProject::popterr() {
01692         COMTRY {
01693                 activeterr= baseterr;
01694                 COMTHROW(dataproject->PopTerritory());
01695         } COMCATCH(;);
01696 }
01697 
01698 
01699 
01700 STDMETHODIMP CMgaProject::Undo() {
01701         COMTRY {
01702                 if(baseterr) COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01703                 COMTHROW(dataproject->UndoTransaction());
01704                 if(!--transactioncount) {
01705                         opened = UNCHANGED;
01706                         guidstat = CLEAN;
01707                 }
01708                 {
01709                         aurcnt++;
01710                         CComPtr<IMgaTerritory> t;
01711                         COMTHROW(CreateTerritory(NULL, &t));
01712                         COMTHROW(BeginTransaction(t, TRANSACTION_READ_ONLY));
01713                         GlobalNotify(GLOBALEVENT_UNDO);
01714                         COMTHROW(CommitTransaction());
01715                 }
01716     }
01717     COMCATCH(;);
01718 }
01719 
01720 STDMETHODIMP CMgaProject::Redo() {
01721 
01722         COMTRY {
01723                 if(baseterr) COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01724                 COMTHROW(dataproject->RedoTransaction());
01725                 transactioncount++;
01726                 opened = CHANGED;
01727                 guidstat = DIRTY;
01728                 {
01729                         aurcnt++;
01730                         CComPtr<IMgaTerritory> t;
01731                         COMTHROW(CreateTerritory(NULL, &t));
01732                         COMTHROW(BeginTransaction(t, TRANSACTION_READ_ONLY));
01733                         GlobalNotify(GLOBALEVENT_REDO);
01734                         COMTHROW(CommitTransaction());
01735                 }
01736     }
01737     COMCATCH(;);
01738 }
01739 
01740 STDMETHODIMP CMgaProject::UndoRedoSize(short *undosize, short *redosize ) {
01741         COMTRY {
01742                 COMTHROW(dataproject->get_UndoQueueSize(undosize));
01743                 COMTHROW(dataproject->get_RedoQueueSize(redosize));
01744     }
01745     COMCATCH(;);
01746 }
01747 
01748 
01749 STDMETHODIMP CMgaProject::FlushUndoQueue() {
01750 
01751         if( dataproject == NULL )
01752                 COMRETURN(E_FAIL);
01753 
01754         COMTRY {
01755                 if(baseterr) COMTHROW(E_MGA_ALREADY_IN_TRANSACTION);
01756                 COMTHROW( dataproject->FlushUndoQueue() );
01757         }
01758         COMCATCH(;)
01759 }
01760 
01761 STDMETHODIMP CMgaProject::UpdateSourceControlInfo( BSTR param)
01762 {
01763         CComPtr<IMgaTerritory> lm;
01764         COMTRY {
01765                 COMTHROW(CreateTerritory(NULL, &lm));
01766                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
01767 
01768                 // hack: core will recognize this action as a source control status update
01769                 CComBSTR hack_str = "UpdateSourceControlInfo";
01770                 CComBSTR para_str( param);
01771                 if( para_str.Length() > 0)
01772                         COMTHROW(hack_str.Append( para_str));
01773                 CoreObj  dataroot;
01774                 COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
01775                 dataroot[ATTRID_MDATE] = hack_str;
01776 
01777                 COMTHROW(CommitTransaction());
01778         }
01779         COMCATCH(;)
01780 }
01781 
01782 STDMETHODIMP CMgaProject::SourceControlActiveUsers()
01783 {
01784         CComPtr<IMgaTerritory> lm;
01785         COMTRY {
01786                 COMTHROW(CreateTerritory(NULL, &lm));
01787                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
01788 
01789                 // hack: core will recognize this value as a command, will show a dlg with user names
01790                 CComBSTR hack_str = "ShowActiveUsers";
01791 
01792                 CoreObj  dataroot;
01793                 COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
01794                 dataroot[ATTRID_MDATE] = hack_str;
01795 
01796                 COMTHROW(CommitTransaction());
01797 
01798         }
01799         COMCATCH(;)
01800 }
01801 
01802 STDMETHODIMP CMgaProject::SourceControlObjectOwner( BSTR p_optionalID)
01803 {
01804         CComPtr<IMgaTerritory> lm;
01805         COMTRY {
01806                 COMTHROW(CreateTerritory(NULL, &lm));
01807                 COMTHROW(BeginTransaction(lm, TRANSACTION_GENERAL));
01808 
01809                 // hack: core will recognize this value as a command, will show a dlg with owneruser
01810                 CComBSTR hack_str = "WhoControlsThisObj";
01811                 CComBSTR para_str( p_optionalID);
01812                 if( para_str.Length() > 0)
01813                         COMTHROW(hack_str.Append( para_str));
01814                 CoreObj  dataroot;
01815                 COMTHROW(dataproject->get_RootObject(&dataroot.ComPtr()));
01816                 dataroot[ATTRID_MDATE] = hack_str;
01817 
01818                 COMTHROW(CommitTransaction());
01819         }
01820         COMCATCH(;)
01821 }
01822 
01823 void CMgaProject::ObjMark(IMgaObject *s, long mask) {
01824         ObjFor(s)->SelfMark(mask);
01825 }
01826 
01827 void CMgaProject::FixupGUID(bool write) {
01828         if (guidstat == DIRTY) {
01829                 ::GUID newGUID;
01830                 COMTHROW(CoCreateGuid(&newGUID));
01831                 pendingguid.Clear();
01832                 CopyTo(newGUID, pendingguid);
01833                 guidstat = PENDING;
01834         }
01835         if ((guidstat == PENDING) && write) {
01836                 ASSERT(baseterr);
01837                 CoreObj self;
01838                 COMTHROW(dataproject->get_RootObject(&self.ComPtr()));
01839                 self[ATTRID_GUID] = pendingguid;
01840                 guidstat = CLEAN;
01841         }
01842 }
01843 
01844 void CMgaProject::UpdateMGAVersion(CoreObj& p_dataroot)
01845 {
01846         mgaversion = p_dataroot[ATTRID_MGAVERSION];
01847         if( mgaversion <= 1L)
01848         {
01849                 // update done by CreateCoreMetaProject so update the ATTRID_MGAVERSION too
01850                 mgaversion = p_dataroot[ATTRID_MGAVERSION] = 2L;
01851         }
01852 }
01853 
01854 void CMgaProject::SetNmspaceInMeta()
01855 {
01856         try {
01857                 ASSERT( metapr);
01858                 if( metapr)
01859                 {
01860                         COMTHROW( metapr->SetNmspc( getNmspc()));
01861                 }
01862         }
01863         catch( hresult_exception& ) {
01864                 ASSERT(0);
01865         }
01866 }
01867 
01868 
01869 CComBSTR CMgaProject::getNmspc()
01870 {
01871         CComBSTR bstr_nm;
01872         try {
01873                 CComPtr<IMgaTerritory> terr;
01874                 COMTHROW( get_ActiveTerritory( &terr));
01875                 if( terr)
01876                 {
01877                         COMTHROW( terr->GetNamespace( &bstr_nm));
01878                 }
01879         }
01880         catch( hresult_exception& ) {
01881                 bstr_nm.Empty();
01882         }
01883         return bstr_nm;
01884 }
01885 
01886 CComBSTR CMgaProject::prefixWNmspc( CComBSTR pKindname)
01887 {
01888         CComBSTR kindname_m;
01889         CComBSTR nm = getNmspc();
01890         if( nm.Length() > 0)// or if not found('::')
01891         {
01892                 COMTHROW(kindname_m.AppendBSTR( nm));
01893                 COMTHROW(kindname_m.Append( "::"));
01894         }
01895 
01896         COMTHROW(kindname_m.AppendBSTR( pKindname));
01897 
01898         return kindname_m;
01899 }
01900 
01901 STDMETHODIMP CMgaProject::CheckCollection(IMgaFCOs *coll) {
01902         COMTRY {
01903                 MGACOLL_ITERATE(IMgaFCO, coll) {
01904                         HRESULT s;
01905                         if((s = MGACOLL_ITER->CheckProject(this)) != S_OK) return s;
01906                 }
01907                 MGACOLL_ITERATE_END;
01908         }
01909         COMCATCH(;)
01910 }
01911 
01912 // by ZolMol
01913 STDMETHODIMP CMgaProject::CheckFolderCollection(IMgaFolders *coll) {
01914         COMTRY {
01915                 MGACOLL_ITERATE(IMgaFolder, coll) {
01916                         HRESULT s;
01917                         if((s = MGACOLL_ITER->CheckProject(this)) != S_OK) return s;
01918                 }
01919                 MGACOLL_ITERATE_END;
01920         }
01921         COMCATCH(;)
01922 }
01923 
01924 
01925 
01926 
01927 
01928 
01929 
01930 
01931 
01932 
01933 
01934 
01935 
01936 
01937 
01938 // ----------------------------------------
01939 // OBSOLETE stuff: Clearlocks
01940 // ----------------------------------------
01941 
01942 #include <set>
01943 #include "../core/CoreUtilities.h"
01944 
01945 bool
01946 #if _MSC_VER >= 1700
01947 constexpr
01948 #endif
01949 std::less<metaobjidpair_type>::operator ()(const metaobjidpair_type &a,const metaobjidpair_type &b) const {
01950         return (a.metaid == b.metaid) ? a.objid < b.objid : a.metaid < b.metaid;
01951 }
01952 
01953 void ClearLocks(ICoreStorage * storage, std::set<metaobjidpair_type> &mset, short mi, long oi, bool clear) {
01954         
01955         metaobjidpair_type mm; 
01956         mm.metaid = mi, mm.objid = oi;
01957 
01958         if(mset.find(mm) != mset.end()) return;
01959         mset.insert(mm);
01960         CComPtr<ICoreMetaProject> mp;
01961         COMTHROW(storage->get_MetaProject(&mp));
01962         CComPtr<ICoreMetaObject> mo;
01963         COMTHROW(mp->get_Object(mi, &mo));
01964         CComPtr<ICoreMetaAttributes> atts;
01965         COMTHROW(mo->get_Attributes(&atts));
01966         long count = 0;
01967         COMTHROW( atts->get_Count(&count) );
01968         std::unique_ptr<CComPtr<ICoreMetaAttribute>[]> array(new CComPtr<ICoreMetaAttribute>[count]);
01969         CComPtr<ICoreMetaAttribute> *arrptr, *arrend = array.get();
01970         if(count > 0) { 
01971                 COMTHROW( atts->GetAll((unsigned long)count, &(*array.get())) ); 
01972         } 
01973         arrend = array.get()+count; 
01974         for(arrptr = array.get(); arrptr != arrend; arrptr++)  {
01975                 unsigned char t;
01976                 COMTHROW((*arrptr)->get_ValueType(&t)); 
01977                 switch(t) {
01978                 case VALTYPE_LOCK:
01979                                 COMTHROW(storage->put_MetaID(mi));
01980                                 COMTHROW(storage->OpenObject(oi));
01981                                 COMTHROW(storage->put_MetaAttribute((*arrptr)));
01982                                 {
01983                                 CComVariant vv;
01984                                 COMTHROW(storage->get_AttributeValue(&vv));
01985                                 ASSERT(vv.vt == VT_I2);
01986                                 if(vv.iVal) {
01987                                         COMTHROW(storage->put_AttributeValue(CComVariant(0)));
01988                                 }
01989                                 }
01990                                 break;
01991                 case VALTYPE_COLLECTION:
01992                                 COMTHROW(storage->put_MetaID(mi));
01993                                 COMTHROW(storage->OpenObject(oi));
01994                                 COMTHROW(storage->put_MetaAttribute((*arrptr)));
01995                                 {
01996                                         CComVariant v;
01997                                         COMTHROW(storage->get_AttributeValue(&v));
01998                                         metaobjidpair_type *i = NULL;
01999                                         metaobjidpair_type *e = NULL;
02000                                         GetArrayBounds(v, i, e);
02001                                         while( i != e ) {
02002                                                 ClearLocks(storage, mset, (short)(*i).metaid, (*i).objid, clear);
02003                                                 i++;
02004                                         }
02005                                 }
02006                 }
02007         }
02008 }
02009 
02010 
02011 
02012 STDMETHODIMP CMgaProject::CheckLocks(BSTR filename, VARIANT_BOOL clearlocks) {
02013   CComPtr<ICoreStorage> storage;
02014   CComPtr<ICoreMetaProject> genericproject;
02015   COMTRY {
02016         CreateCoreMetaProject(genericproject); // use mgaversion = 1 project model
02017         COMTHROW(storage.CoCreateInstance(      OLESTR("Mga.CoreRepository")));
02018         COMTHROW(storage->put_MetaProject(genericproject));
02019         COMTHROW(storage->OpenProject(filename, NULL));
02020         COMTHROW(storage->BeginTransaction());
02021         std::set<metaobjidpair_type> ccc;
02022         ClearLocks(storage, ccc, 1, 1, clearlocks ? true : false);
02023         COMTHROW(storage->CommitTransaction());
02024   } COMCATCH(;)
02025 }
02026 
02027 int CMgaProject::getMaxUndoSize()
02028 {
02029         int retval = 10; // keep in sync with the default value in CoreProject.h
02030         try
02031         {
02032                 CComPtr<IMgaRegistrar> mgareg;
02033                 COMTHROW(mgareg.CoCreateInstance(OLESTR("Mga.MgaRegistrar")));
02034                 CComBSTR undo_size;
02035                 COMTHROW( mgareg->GetUndoQueueSize( REGACCESS_USER, &undo_size));
02036                 if (undo_size != NULL && undo_size != L"") {
02037                         int val = _wtoi(undo_size);
02038                         if (val > 0 && val < 100) // requirement is to be above 0 and below 100
02039                                 retval = val;
02040                 }
02041         }
02042         catch( hresult_exception&)
02043         {
02044                 retval = 10;
02045         }
02046 
02047         return retval;
02048 }
02049 
02050 STDMETHODIMP CMgaProject::GetTopLibraries(BSTR pDispGuid, IMgaFolders **pVal)
02051 {
02052         COMTRY {
02053                 CHECK_INSTRPAR( pDispGuid);
02054                 CREATECOLLECTION_FOR(IMgaFolder,q);
02055 
02056                 CComPtr<IMgaFolder> rootf;
02057                 COMTHROW( get_RootFolder( &rootf));
02058                 CoreObj crf( rootf);
02059                 CoreObjs children = crf[ATTRID_FPARENT+ATTRID_COLLECTION];
02060                 ITERATE_THROUGH(children) {
02061                         if( ITER.GetMetaID() != DTID_FOLDER) continue;
02062                         long perm = ITER[ATTRID_PERMISSIONS];
02063                         if( perm & LIBROOT_FLAG)
02064                         {
02065                                 auto lib = ObjForCore(ITER);
02066                                 if( lib) 
02067                                 {
02068                                         CComBSTR gd;
02069                                         COMTHROW( lib->GetGuidDisp( &gd));
02070 
02071                                         if( gd == pDispGuid)
02072                                         {
02073                                                 CComPtr<IMgaFolder> fld;
02074                                                 lib->getinterface( &fld);
02075                                                 q->Add( fld);
02076                                         }
02077                                 }
02078                         }
02079                 }
02080                 *pVal = q.Detach();
02081         }
02082     COMCATCH(;);
02083 }
02084