GME  13
MgaAttribute.cpp
Go to the documentation of this file.
00001 // MgaAttribute.cpp : Implementation of CMgaAttribute
00002 #include "stdafx.h"
00003 #include "MgaAttribute.h"
00004 #include "MgaFCO.h"
00005 
00006 #include "atlsafe.h"
00007 
00008 #include <unordered_map>
00009 
00010 #include "Core.h"
00011 
00013 // CMgaAttribute
00014 
00015 
00016 // Throws!!!
00017 void CMgaAttribute::Initialize(metaref_type mr, FCO *o, CMgaProject *p) { 
00018         mref = mr;              
00019         fco = o;
00020         mgaproject = p;
00021         CComQIPtr<IMgaMetaAttribute> meta = mgaproject->FindMetaRef(mr);
00022         COMTHROW(meta->get_ValueType(&attrtyp));
00023         inputtyp = attrtyp;
00024         if(attrtyp == ATTVAL_ENUM) attrtyp = ATTVAL_STRING;
00025 }
00026 
00027 STDMETHODIMP CMgaAttribute::get_Owner( IMgaFCO **pVal) {  
00028         COMTRY { 
00029                 CHECK_OUTPTRPAR(pVal);
00030                 fco->getinterface(pVal); 
00031         } COMCATCH(;) 
00032 };
00033 
00034 
00035 STDMETHODIMP CMgaAttribute::get_Status( long *status) {
00036                 COMTRY  {
00037                         CHECK_OUTPAR(status);
00038                         fco->CheckRead();
00039                         if(load_status == ATTSTATUS_INVALID) {
00040                                 CComVariant v;
00041                                 get_Value(&v);
00042                         }
00043                         *status = load_status;
00044                 } COMCATCH(;)
00045 }
00046 
00047 STDMETHODIMP CMgaAttribute::get_Value(VARIANT *pVal) {
00048                 COMTRY {
00049                         CHECK_OUTVARIANTPAR(pVal);
00050                         fco->CheckRead();
00051                         CComVariant var;
00052                         if(load_status == ATTSTATUS_INVALID) {
00053                                 long ls = ATTSTATUS_HERE;
00054                                 CoreObj cur = fco->self;
00055                                 valueobj = NULL;
00056                                 while(cur) {
00057                                         CoreObjs attrs = cur[ATTRID_ATTRPARENT+ATTRID_COLLECTION];
00058                                         ITERATE_THROUGH(attrs) {
00059                                                 if(mref == ITER[ATTRID_META]) {
00060                                                         valueobj = ITER;
00061                                                         break;
00062                                                 }
00063                                         }
00064                                         if(valueobj != NULL) {
00065                                                 load_status = ls;
00066                                                 break;                          // breaks here with >= HERE 
00067                                         }
00068                                         cur = cur[ATTRID_DERIVED];
00069                                         ls++;
00070                                 }
00071                         }
00072                         if(load_status >= ATTSTATUS_HERE) {
00073                                 COMTHROW(valueobj->get_AttributeValue((short)(ATTRID_ATTRTYPESBASE + attrtyp), &var));
00074                         }
00075                         else {
00076                                 CComQIPtr<IMgaMetaAttribute> m(mgaproject->FindMetaRef(mref));
00077                                 COMTHROW(m->get_DefaultValue(&var));
00078 /* METADIFF !!                          
00079                                 if(pVal->vt == VT_EMPTY) {
00080                                         COMTHROW(m->get_Status(&load_status));
00081                                 }
00082                                 else */ 
00083                                         load_status = ATTSTATUS_METADEFAULT;
00084                         }
00085                         {
00086                                 static const VARTYPE vartypes[] = { VT_NULL, VT_BSTR, VT_I4, VT_R8, VT_BOOL, VT_DISPATCH, VT_BSTR };
00087                                 if(vartypes[attrtyp] != var.vt) {
00088                                         COMTHROW(var.ChangeType(vartypes[attrtyp]));
00089                                 }
00090                         }
00091                         var.Detach(pVal);
00092                 } COMCATCH(;)
00093 }
00094 
00095 STDMETHODIMP CMgaAttribute::get_OrigValue(VARIANT *pVal) {
00096                 COMTRY {
00097                         CHECK_OUTVARIANTPAR(pVal);
00098                         fco->CheckRead();
00099                         CComVariant var;
00100                         if(load_status == ATTSTATUS_INVALID) {
00101                                 long ls = ATTSTATUS_HERE;
00102                                 CoreObj cur = fco->self;
00103                                 valueobj = NULL;
00104                                 while(cur) {
00105                                         CoreObjs attrs = cur[ATTRID_ATTRPARENT+ATTRID_COLLECTION];
00106                                         ITERATE_THROUGH(attrs) {
00107                                                 if(mref == ITER[ATTRID_META]) {
00108                                                         valueobj = ITER;
00109                                                         break;
00110                                                 }
00111                                         }
00112                                         if(valueobj != NULL) {
00113                                                 load_status = ls;
00114                                                 break;                          // breaks here with >= HERE 
00115                                         }
00116                                         cur = cur[ATTRID_DERIVED];
00117                                         ls++;
00118                                 }
00119                         }
00120                         if(load_status >= ATTSTATUS_HERE) {
00121                                 COMTHROW(valueobj->get_AttributeValue((short)(ATTRID_ATTRTYPESBASE + attrtyp), &var));
00122                         }
00123                         else {
00124                                 CComQIPtr<IMgaMetaAttribute> m(mgaproject->FindMetaRef(mref));
00125                                 COMTHROW(m->get_DefaultValue(&var));
00126 /* METADIFF !!                          
00127                                 if(pVal->vt == VT_EMPTY) {
00128                                         COMTHROW(m->get_Status(&load_status));
00129                                 }
00130                                 else */ 
00131                                         load_status = ATTSTATUS_METADEFAULT;
00132                         }
00133                         {
00134                                 static const VARTYPE vartypes[] = { VT_NULL, VT_BSTR, VT_I4, VT_R8, VT_BOOL, VT_DISPATCH, VT_BSTR };
00135                                 if(vartypes[attrtyp] != var.vt) {
00136                                         COMTHROW(var.ChangeType(vartypes[attrtyp]));
00137                                 }
00138                         }
00139                         var.Detach(pVal);
00140                 } COMCATCH(;)
00141 }
00142 
00143 
00144 STDMETHODIMP CMgaAttribute::get_HasChanged(VARIANT_BOOL *pVal) {
00145                 COMTRY {
00146                         CHECK_OUTPAR(pVal);
00147                         *pVal = VARIANT_TRUE;
00148                 } COMCATCH(;)
00149 }
00150 
00151 
00152 class attrnotifytask : public DeriveTreeTask {
00153         bool Do(CoreObj self, std::vector<CoreObj> *peers = NULL) {
00154                 ObjForCore(self)->SelfMark(OBJEVENT_ATTR);
00155                 return true;
00156         }
00157 };
00158 
00159 
00160 STDMETHODIMP CMgaAttribute::Clear() {
00161         COMTRY_IN_TRANSACTION {
00162                 fco->CheckWrite();
00163                 CoreObjs attrs = fco->self[ATTRID_ATTRPARENT+ATTRID_COLLECTION];
00164                 ITERATE_THROUGH(attrs) {
00165                         if(mref == ITER[ATTRID_META]) {
00166                                 // lph: Pre-Notification PRE_STATUS (the attribute is being changed to its default value)
00167                                 CComQIPtr<IMgaMetaAttribute> ma(mgaproject->FindMetaRef(mref));
00168                                 CComBSTR name;
00169                                 COMTHROW(ma->get_Name(&name));
00170                                 CComBSTR desc = L"ATTR,";
00171                                 COMTHROW(desc.Append(name));
00172                                 COMTHROW(desc.Append(L",Cleared"));
00173                                 // FIXME: COMTHROW?
00174                                 fco->PreNotify(OBJEVENT_PRE_STATUS, CComVariant(desc));
00175                                 //---------------------------------------------------------------------------------------
00176                                 COMTHROW(ITER->Delete());
00177                                 load_status = ATTSTATUS_INVALID;
00178                                 // lph: added notification of attribute mod
00179                                 attrnotifytask().DoWithDeriveds(fco->self);
00180                                 //-----------------------------------------
00181                                 break;
00182                         }
00183                 }
00184         } COMCATCH_IN_TRANSACTION(;);
00185 }
00186 
00187 
00188 STDMETHODIMP CMgaAttribute::put_Value(VARIANT newVal) {
00189                 COMTRY_IN_TRANSACTION_MAYBE {
00190                         CHECK_INPAR(newVal);
00191                         fco->CheckWrite();
00192                         if(load_status == ATTSTATUS_INVALID) {
00193                                 valueobj = NULL;
00194                                 CoreObjs attrs = fco->self[ATTRID_ATTRPARENT+ATTRID_COLLECTION];
00195                                 ITERATE_THROUGH(attrs) {
00196                                         if(mref == ITER[ATTRID_META]) {
00197                                                 valueobj = ITER;
00198                                                 load_status = ATTSTATUS_HERE;
00199                                                 break;
00200                                         }
00201                                 }
00202                         }
00203                         if(load_status != ATTSTATUS_HERE) {
00204                                         load_status = ATTSTATUS_INVALID;
00205                                         valueobj = NULL;
00206                                         COMTHROW(mgaproject->dataproject->CreateObject(DTID_ATTRTYPESBASE+attrtyp, &valueobj.ComPtr()));
00207                                         // lph: Pre-Notification PRE_STATUS (the attribute is being changed from its default value)
00208                                         CComQIPtr<IMgaMetaAttribute> ma(mgaproject->FindMetaRef(mref));
00209                                         CComBSTR name;
00210                                         COMTHROW(ma->get_Name(&name));
00211                                         CComBSTR desc = L"ATTR,";
00212                                         COMTHROW(desc.Append(name));
00213                                         COMTHROW(desc.Append(L",Defined"));
00214                                         fco->PreNotify(OBJEVENT_PRE_STATUS, CComVariant(desc));
00215                                         //-----------------------------------------------------------------------------------------
00216                                         valueobj[ATTRID_META]=mref;
00217                                         valueobj[ATTRID_ATTRPARENT]=fco->self;
00218                                         load_status = ATTSTATUS_HERE;
00219                         }
00220 
00221                         if(inputtyp == ATTVAL_ENUM) {
00222                                 CComVariant v = newVal;
00223                                 if(v.vt != VT_BSTR) v.ChangeType(VT_BSTR);
00224                                 if(v.vt != VT_BSTR) COMTHROW(E_MGA_BAD_ENUMVALUE);
00225                                 CComQIPtr<IMgaMetaAttribute> m(mgaproject->FindMetaRef(mref));
00226                                 CComPtr<IMgaMetaEnumItems> enms;
00227                                 COMTHROW(m->get_EnumItems(&enms));
00228                                 MGACOLL_ITERATE(IMgaMetaEnumItem, enms) {
00229                                         CComBSTR b;
00230                                         COMTHROW(MGACOLL_ITER->get_Value(&b));
00231                                         if(b == v.bstrVal) break;
00232                                 } 
00233                                 if(MGACOLL_AT_END) COMTHROW(E_MGA_BAD_ENUMVALUE);
00234                                 MGACOLL_ITERATE_END;
00235 
00236                                 valueobj[ATTRID_ATTRTYPESBASE + ATTVAL_STRING] = v;
00237                         }
00238                         else valueobj[ATTRID_ATTRTYPESBASE + attrtyp] = newVal;
00239                         {
00240                                 CComPtr<IMgaFCO> p;
00241                                 COMTHROW(get_Owner(&p));
00242                                 attrnotifytask().DoWithDeriveds(fco->self);
00243                         }
00244                 } COMCATCH_IN_TRANSACTION_MAYBE(;)
00245 }
00246 
00247 
00248 STDMETHODIMP CMgaAttribute::get_StringValue(BSTR *pVal) {
00249                 if(!(mgaproject->preferences & MGAPREF_RELAXED_RDATTRTYPES) &&
00250                         attrtyp != ATTVAL_STRING && inputtyp != ATTVAL_ENUM) return E_MGA_ACCESS_TYPE;
00251                 COMTRY {
00252                         CHECK_OUTSTRPAR(pVal);
00253                         CComVariant v;
00254                         COMTHROW( get_Value(&v));
00255                         CopyTo(v, pVal);
00256                 } COMCATCH(;)
00257 }
00258 
00259 STDMETHODIMP CMgaAttribute::put_StringValue(BSTR newVal) {
00260                 if(!(mgaproject->preferences & MGAPREF_RELAXED_WRATTRTYPES) &&
00261                         attrtyp != ATTVAL_STRING) return E_MGA_ACCESS_TYPE;
00262                 COMTRY {
00263                         CHECK_INSTRPAR(newVal);
00264                         COMTHROW( put_Value(CComVariant(newVal)));
00265                 } COMCATCH(;)
00266 }
00267 
00268 STDMETHODIMP CMgaAttribute::get_IntValue(long *pVal) {
00269                 if(!(mgaproject->preferences & MGAPREF_RELAXED_RDATTRTYPES) &&
00270                         attrtyp != ATTVAL_INTEGER && inputtyp != ATTVAL_ENUM) return E_MGA_ACCESS_TYPE;
00271                 COMTRY {
00272                         CHECK_OUTPAR(pVal);
00273                         CComVariant v;
00274                         COMTHROW( get_Value(&v));
00275                         if(inputtyp == ATTVAL_ENUM) {
00276                                 long ord = 0;
00277                                 if(v.vt != VT_BSTR) v.ChangeType(VT_BSTR);
00278                                 if(v.vt != VT_BSTR) COMTHROW(E_MGA_BAD_ENUMVALUE);
00279                                 CComQIPtr<IMgaMetaAttribute> m(mgaproject->FindMetaRef(mref));
00280                                 CComPtr<IMgaMetaEnumItems> enms;
00281                                 COMTHROW(m->get_EnumItems(&enms));
00282                                 MGACOLL_ITERATE(IMgaMetaEnumItem, enms) {
00283                                         CComBSTR b;
00284                                         COMTHROW(MGACOLL_ITER->get_Value(&b));
00285                                         if(b == v.bstrVal) break;
00286                                         ord++;
00287                                 } 
00288                                 if(MGACOLL_AT_END) COMTHROW(E_MGA_BAD_ENUMVALUE);
00289                                 MGACOLL_ITERATE_END;
00290                                 *pVal = ord;
00291                         }
00292                         else CopyTo(v, *pVal);  // throws if type mismatch
00293                 } COMCATCH(;)
00294 }
00295 
00296 STDMETHODIMP CMgaAttribute::put_IntValue(long newVal) {
00297                 if(!(mgaproject->preferences & MGAPREF_RELAXED_WRATTRTYPES) &&
00298                    attrtyp != ATTVAL_INTEGER && inputtyp != ATTVAL_ENUM) return E_MGA_ACCESS_TYPE;
00299                 COMTRY {
00300                         CHECK_INPAR(newVal);
00301                         if(inputtyp == ATTVAL_ENUM) {
00302                                 CComQIPtr<IMgaMetaAttribute> m(mgaproject->FindMetaRef(mref));
00303                                 CComPtr<IMgaMetaEnumItems> enms;
00304                                 CComPtr<IMgaMetaEnumItem> enm;
00305                                 COMTHROW(m->get_EnumItems(&enms));
00306                                 long count;
00307                                 COMTHROW(enms->get_Count(&count));
00308                                 if(newVal < 0 || newVal > count) COMTHROW(E_MGA_BAD_ENUMVALUE);
00309                                 COMTHROW(enms->get_Item(1+newVal, &enm));
00310                                 CComBSTR estr;
00311                                 COMTHROW(enm->get_Value(&estr));
00312                                 COMTHROW( put_Value(CComVariant(estr)));
00313                         }
00314                         COMTHROW( put_Value(CComVariant(newVal)));
00315                 } COMCATCH(;)
00316 }
00317 
00318 STDMETHODIMP CMgaAttribute::get_BoolValue(VARIANT_BOOL *pVal) {
00319                 if(!(mgaproject->preferences & MGAPREF_RELAXED_RDATTRTYPES) &&
00320                         attrtyp != ATTVAL_BOOLEAN) return E_MGA_ACCESS_TYPE;
00321                 COMTRY {
00322                         CHECK_OUTPAR(pVal);
00323                         CComVariant v;
00324                         COMTHROW( get_Value(&v));
00325                         CopyTo(v, *pVal);
00326                 } COMCATCH(;)
00327 }
00328 
00329 STDMETHODIMP CMgaAttribute::put_BoolValue(VARIANT_BOOL newVal) {
00330                 if(!(mgaproject->preferences & MGAPREF_RELAXED_WRATTRTYPES) &&
00331                    attrtyp != ATTVAL_BOOLEAN) return E_MGA_ACCESS_TYPE;
00332                 COMTRY {
00333                         CHECK_INPAR(newVal);
00334                         COMTHROW( put_Value(CComVariant(newVal)));
00335                 } COMCATCH(;)
00336 }
00337 
00338 STDMETHODIMP CMgaAttribute::get_FloatValue(double *pVal) {
00339                 if(!(mgaproject->preferences & MGAPREF_RELAXED_RDATTRTYPES) &&
00340                         attrtyp != ATTVAL_DOUBLE) return E_MGA_ACCESS_TYPE;
00341                 COMTRY {
00342                         CHECK_OUTPAR(pVal);
00343                         CComVariant v;
00344                         COMTHROW( get_Value(&v));
00345                         CopyTo(v, *pVal);
00346                 } COMCATCH(;)
00347 }
00348 
00349 STDMETHODIMP CMgaAttribute::put_FloatValue(double newVal) {
00350                 if(!(mgaproject->preferences & MGAPREF_RELAXED_WRATTRTYPES) &&
00351                    attrtyp != ATTVAL_DOUBLE) return E_MGA_ACCESS_TYPE;
00352                 COMTRY {
00353                         CHECK_INPAR(newVal);
00354                         COMTHROW( put_Value(CComVariant(newVal)));
00355                 } COMCATCH(;)
00356 }
00357 
00358 STDMETHODIMP CMgaAttribute::get_FCOValue(IMgaFCO **pVal)
00359 {
00360         if(attrtyp != ATTVAL_REFERENCE) return E_MGA_ACCESS_TYPE;
00361         COMTRY {
00362                 CHECK_OUTPTRPAR(pVal);
00363                 CComVariant v;
00364                 COMTHROW( get_Value(&v));
00365                 CoreObj h;
00366                 if(v.vt != VT_DISPATCH) COMTHROW(E_MGA_MODULE_INCOMPATIBILITY);
00367                 if(v.pdispVal) COMTHROW(v.pdispVal->QueryInterface(_uuidof(ICoreObject), (void **)&h));
00368                 if(!h) COMTHROW(E_MGA_MODULE_INCOMPATIBILITY);
00369                 ObjForCore(h)->getinterface(pVal);
00370         } COMCATCH(;)
00371 }
00372 
00373 STDMETHODIMP CMgaAttribute::put_FCOValue(IMgaFCO *newVal)
00374 {
00375         if(attrtyp != ATTVAL_REFERENCE) return E_MGA_ACCESS_TYPE;
00376         COMTRY {
00377                 CHECK_MYINPTRPAR(newVal);
00378                 COMTHROW( put_Value(CComVariant(CoreObj(newVal))));
00379         } COMCATCH(;)
00380 
00381 }
00382 
00383 
00384 STDMETHODIMP CMgaAttribute::get_RegistryNode( BSTR path,  IMgaRegNode **pVal) {  
00385                 COMTRY {
00386                         fco->CheckRead();
00387                         CHECK_OUTPTRPAR(pVal);
00388                         CHECK_INSTRPAR(path);
00389       
00390                         CComBSTR xpath(regprefix);
00391                         COMTHROW(xpath.Append(L"/"));
00392                         COMTHROW(xpath.AppendBSTR(path));
00393                         COMTHROW(fco->get_RegistryNode(xpath, pVal));
00394                 } COMCATCH(;)
00395 }
00396 
00397 STDMETHODIMP CMgaAttribute::get_Registry( VARIANT_BOOL virtuals, IMgaRegNodes **pVal) {  
00398                 COMTRY {
00399                         fco->CheckRead();
00400                         CHECK_OUTPTRPAR(pVal);
00401                         CComPtr<IMgaRegNode> p;
00402                         COMTHROW(fco->get_RegistryNode(regprefix, &p));
00403                         COMTHROW(p->get_SubNodes(virtuals, pVal));
00404                 } COMCATCH(;);
00405 }
00406 
00407 STDMETHODIMP CMgaAttribute::get_RegistryValue( BSTR path,  BSTR *pVal) {  
00408                 COMTRY {
00409                         fco->CheckRead();
00410                         CHECK_OUTPAR(pVal);
00411                         CHECK_INSTRPAR(path);
00412                         CComPtr<IMgaRegNode> p;
00413                         COMTHROW(get_RegistryNode(path, &p));
00414                         COMTHROW(p->get_Value(pVal));
00415                 } COMCATCH(;)
00416 }
00417 
00418 STDMETHODIMP CMgaAttribute::put_RegistryValue( BSTR path,  BSTR newval) {  
00419                 COMTRY_IN_TRANSACTION {
00420                         fco->CheckWrite();
00421                         CHECK_INSTRPAR(path);
00422                         CHECK_INSTRPAR(newval);
00423                         CComPtr<IMgaRegNode> p;
00424                         COMTHROW(get_RegistryNode(path, &p));
00425                         COMTHROW(p->put_Value(newval));
00426                 } COMCATCH_IN_TRANSACTION(;)
00427 }
00428 
00429 
00430 
00431 void MergeAttrs(const CoreObj &src, CoreObj &dst) {
00432         CoreObjs dstcoll = dst[ATTRID_ATTRPARENT+ATTRID_COLLECTION];
00433         ITERATE_THROUGH(src[ATTRID_ATTRPARENT+ATTRID_COLLECTION]) {
00434                 CoreObj &srcn = ITER;
00435                 CoreObj dstn;
00436                 metaref_type srcmeta = srcn[ATTRID_META];
00437                 ITERATE_THROUGH(dstcoll) {
00438                         if(srcmeta == ITER[ATTRID_META]) {
00439                                 break;
00440                         }
00441                 }
00442                 if(!ITER_BROKEN) {
00443                         CComPtr<ICoreProject> p;
00444                         COMTHROW(srcn->get_Project(&p));
00445                         metaid_type mi = srcn.GetMetaID();
00446                         COMTHROW(p->CreateObject(mi, &dstn.ComPtr()));
00447                         dstn[ATTRID_META] = srcmeta;
00448                         dstn[ATTRID_ATTRPARENT] = dst;
00449 // MAGIC with attrtype numbers   to set the value attribute
00450                         dstn[ATTRID_ATTRTYPESBASE + (mi - DTID_ATTRTYPESBASE) ] = srcn[ATTRID_ATTRTYPESBASE + (mi - DTID_ATTRTYPESBASE)];
00451                 }
00452         }
00453 }
00454 
00455 
00459 
00460 
00461 
00462 // THROWS!!!
00463 // RECURSIVE!!!
00464 // Used when an FCO is detached from its basetype. 
00465 // All nodes present in src node will be added to dst node, unless dst already has 
00466 // a node with the same name and a value.
00467 // If dst node is opaque, src is not copied and recursion also stops.
00468 
00469 void MergeRegs(const CoreObj &src, CoreObj &dst) {
00470         {
00471                 // KMS: need to set ATTRID_REGNODE for write ops
00472                 CComVariant attr = dst[ATTRID_REGNODE];
00473                 dst[ATTRID_REGNODE] = attr;
00474         }
00475 
00476         CComVariant attr = dst[ATTRID_REGNODE];
00477         CComPtr<ICoreDictionaryAttributeValue> dictval;
00478         COMTHROW(attr.pdispVal->QueryInterface(&dictval));
00479         VARIANT vmap;
00480         COMTHROW(dictval->get_Map(&vmap));
00481         CMgaRegNode::map_type* map = (CMgaRegNode::map_type*)(void*)vmap.llVal;
00482 
00483         CoreObj s = src;
00484         do {
00485                 CComVariant sattr = s[ATTRID_REGNODE];
00486                 CComPtr<ICoreDictionaryAttributeValue> sdictval;
00487                 COMTHROW(sattr.pdispVal->QueryInterface(&sdictval));
00488                 VARIANT svmap;
00489                 COMTHROW(sdictval->get_Map(&svmap));
00490                 CMgaRegNode::map_type* smap = (CMgaRegNode::map_type*)(void*)svmap.llVal;
00491 
00492                 for (auto it = smap->begin(); it != smap->end(); it++)
00493                 {
00494                         if (map->find(it->first) == map->end())
00495                         {
00496                                 map->insert(CMgaRegNode::map_type::value_type(it->first, it->second));
00497                         }
00498                 }
00499 
00500                 if (!s.IsFCO())
00501                         break;
00502         } while (s = s[ATTRID_DERIVED]);
00503 }
00504 
00505 class regnotifytask : public DeriveTreeTask {
00506         bool Do(CoreObj self, std::vector<CoreObj> *peers = NULL) {
00507                 ObjForCore(self)->SelfMark(OBJEVENT_REGISTRY);
00508                 return true;
00509         }
00510 };
00511 
00512 
00513 template<class F>
00514 void CMgaRegNode::WalkKeyValues(CoreObj& obj, F& f, long status, bool& continue_)
00515 {
00516         CComVariant attr = obj[ATTRID_REGNODE];
00517         CComPtr<ICoreDictionaryAttributeValue> oldval;
00518         COMTHROW(attr.pdispVal->QueryInterface(&oldval));
00519         VARIANT vmap;
00520         COMTHROW(oldval->get_Map(&vmap));
00521         map_type* map = (map_type*)(void*)vmap.llVal;
00522 
00523         for (auto it = map->begin(); it != map->end(); it++)
00524         {
00525                 f(*map, it, status, continue_);
00526         }
00527 }
00528 
00529 template<class F>
00530 void CMgaRegNode::WalkKeyValuesInher(F& f)
00531 {
00532         bool continue_ = true;
00533         CoreObj s = fco->self;
00534         long status = ATTSTATUS_HERE;
00535         do {
00536                 WalkKeyValues(s, f, status, continue_);
00537                 status = min(ATTSTATUS_IN_ARCHETYPE4, status + 1);
00538                 if (!continue_)
00539                         break;
00540                 if (!s.IsFCO())
00541                         break;
00542         } while (s = s[ATTRID_DERIVED]);
00543 }
00544 
00545 void CMgaRegNode::SetValue(const wchar_t* path, const wchar_t* value)
00546 {
00547         {
00548                 // KMS: need to set ATTRID_REGNODE for write ops
00549                 CComVariant attr = fco->self[ATTRID_REGNODE];
00550                 fco->self[ATTRID_REGNODE] = attr;
00551         }
00552 
00553         CComVariant attr = fco->self[ATTRID_REGNODE];
00554         CComPtr<ICoreDictionaryAttributeValue> newval;
00555         COMTHROW(attr.pdispVal->QueryInterface(&newval));
00556 
00557         VARIANT vmap;
00558         COMTHROW(newval->get_Map(&vmap));
00559         map_type* map = (map_type*)(void*)vmap.llVal;
00560 
00561         if (value == NULL_SENTINEL) {
00562                 auto ent = map->find(CComBSTR(path));
00563                 if (ent != map->end())
00564                         map->erase(ent);
00565         } else
00566                 (*map)[CComBSTR(path)] = CComBSTR(value);
00567 }
00568 
00569 const wchar_t* CMgaRegNode::NULL_SENTINEL = (const wchar_t*) "\0xFF\0xFE\0";
00570 
00571 
00572 void CMgaRegNode::markchg() {
00573         regnotifytask().DoWithDeriveds(fco->self);
00574 }
00575 
00576 
00577 
00578 
00579 
00580 STDMETHODIMP CMgaRegNode::get_Object( IMgaObject **pVal) {  
00581         COMTRY {
00582                 CHECK_OUTPTRPAR(pVal);
00583                 IMgaFCO *p;
00584                 fco->getinterface(&p); 
00585                 *pVal = p;
00586         } COMCATCH(;) 
00587 };
00588 
00589 STDMETHODIMP CMgaRegNode::get_Status( long *status) {
00590                 COMTRY  {
00591                         fco->CheckRead();
00592                         CHECK_OUTPAR(status);
00593 
00594                         *status = ATTSTATUS_UNDEFINED;
00595                         CoreObj s = fco->self;
00596                         long _status = ATTSTATUS_HERE;
00597                         do {
00598                                 CComVariant attr = s[ATTRID_REGNODE];
00599                                 CComPtr<ICoreDictionaryAttributeValue> oldval;
00600                                 COMTHROW(attr.pdispVal->QueryInterface(&oldval));
00601 
00602                                 CComPtr<ICoreDictionaryAttributeValue> newval = oldval;
00603                                 VARIANT vmap;
00604                                 COMTHROW(newval->get_Map(&vmap));
00605                                 map_type* map = (map_type*)(void*)vmap.llVal;
00606                                 if (map->find(mypath) != map->end())
00607                                 {
00608                                         *status = _status;
00609                                         return S_OK;
00610                                 }
00611 
00612                                 _status = min(ATTSTATUS_IN_ARCHETYPE4, _status + 1);
00613                                 if (!s.IsFCO())
00614                                         break;
00615                         } while (s = s[ATTRID_DERIVED]);
00616 
00617                         metaref_type mref = fco->self[ATTRID_META];
00618                         if(mref) {
00619                                 CComQIPtr<IMgaMetaBase> m(mgaproject->FindMetaRef(mref));
00620                                 CComPtr<IMgaMetaRegNode> rn;
00621                                 HRESULT hr = m->get_RegistryNode(mypath, &rn);
00622                                 if (hr == E_NOTFOUND) {
00623                                         *status = ATTSTATUS_UNDEFINED;
00624                                 }
00625                                 else if (SUCCEEDED(hr)) {
00626                                         *status = ATTSTATUS_METADEFAULT;
00627                                 }
00628                                 else if(hr != E_NOTFOUND)
00629                                         COMTHROW(hr);
00630                         }
00631 
00632                         return S_OK;
00633                 } COMCATCH(;)
00634 }
00635 
00636 
00637 void MgaRegNode_get_Value(CMgaProject* mgaproject, FCO * fco, CoreObj s, BSTR mypath, BSTR *pVal)
00638 {
00639         do {
00640                 CComVariant attr = s[ATTRID_REGNODE];
00641                 CComPtr<ICoreDictionaryAttributeValue> dict;
00642                 COMTHROW(attr.pdispVal->QueryInterface(&dict));
00643                 VARIANT vmap;
00644                 COMTHROW(dict->get_Map(&vmap));
00645                 CMgaRegNode::map_type* map = (CMgaRegNode::map_type*)(void*)vmap.llVal;
00646 
00647                 CMgaRegNode::map_type::iterator it = map->find(mypath);
00648                 if (it != map->end()) {
00649                         *pVal = CComBSTR(it->second).Detach();
00650                         return;
00651                 }
00652                 if (!s.IsFCO())
00653                         break;
00654         } while (s = s[ATTRID_DERIVED]);
00655 
00656         metaref_type mref = fco->self[ATTRID_META];
00657         if(mref) {
00658                 CComQIPtr<IMgaMetaBase> m(mgaproject->FindMetaRef(mref));
00659                 CComPtr<IMgaMetaRegNode> rn;
00660                 HRESULT hr = m->get_RegistryNode(mypath, &rn);
00661                 if(hr == S_OK) {
00662                         COMTHROW(rn->get_Value(pVal));
00663                         return;
00664                 }
00665                 else if(hr != E_NOTFOUND)
00666                         COMTHROW(hr);
00667         }
00668         *pVal = NULL;
00669 }
00670 
00671 STDMETHODIMP CMgaRegNode::get_Value(BSTR *pVal) {
00672         COMTRY {
00673                 CHECK_OUTVARIANTPAR(pVal);
00674                 CoreObj s = fco->self;
00675                 MgaRegNode_get_Value(mgaproject, fco, s, mypath, pVal);
00676         } COMCATCH(;)
00677 }
00678 
00679 STDMETHODIMP CMgaRegNode::get_FCOValue(IMgaFCO **pVal) {
00680                 COMTRY  {
00681                         fco->CheckRead();
00682                         CHECK_OUTPTRPAR(pVal);
00683 
00684                         fco->getinterface(pVal);
00685                 } COMCATCH(;)
00686 }
00687 
00688 STDMETHODIMP CMgaRegNode::get_Opacity( VARIANT_BOOL *pVal) {
00689         COMTRY {
00690                 long status;
00691                 COMTHROW(get_Status(&status));
00692                 *pVal = status == ATTSTATUS_HERE ? VARIANT_TRUE : VARIANT_FALSE;
00693         } COMCATCH(;);
00694 }
00695 
00696 STDMETHODIMP CMgaRegNode::put_Opacity( VARIANT_BOOL newVal) {
00697         return S_OK;
00698 }
00699 
00700 
00701 STDMETHODIMP CMgaRegNode::put_Value(BSTR newVal) {
00702                 COMTRY {
00703                         CHECK_INSTRPAR(newVal);
00704                         fco->CheckWrite();
00705                         SetValue(mypath, newVal);
00706                         markchg();
00707                 } COMCATCH(;)
00708 }
00709 
00710 STDMETHODIMP CMgaRegNode::put_FCOValue(IMgaFCO *newVal) {
00711         return E_NOTIMPL;
00712 }
00713 
00714 STDMETHODIMP CMgaRegNode::get_SubNodes( VARIANT_BOOL virtuals, IMgaRegNodes **pVal) {
00715                 COMTRY {
00716                         fco->CheckRead();
00717                         CHECK_OUTPTRPAR(pVal);
00718 
00719                         CoreObj s = fco->self;
00720                         CREATEEXCOLLECTION_FOR(MgaRegNode,q);
00721                         std::set<std::wstring> paths;
00722                         WalkKeyValuesInher([&](map_type& map, map_type::iterator& it, int inher, bool& continue_) {
00723                                 if (virtuals == VARIANT_FALSE && inher != ATTSTATUS_HERE)
00724                                 {
00725                                         continue_ = false;
00726                                         return;
00727                                 }
00728                                 if (wcsncmp(it->first ? it->first : L"", mypath, mypath.Length()) == 0)
00729                                 {
00730                                         std::wstring path = it->first ? it->first : L"";
00731                                         if (path.length() > mypath.Length() && (mypath.Length() == 0 || path[mypath.Length()] == L'/'))
00732                                         {
00733                                                 size_t end = path.find(L'/', mypath.Length() + 1);
00734                                                 if (end != std::wstring::npos)
00735                                                         path = path.substr(0, end);
00736                                                 paths.insert(std::move(path));
00737                                         }
00738                                 }
00739                         });
00740                         if(virtuals) {
00741                                 metaref_type mref = fco->self[ATTRID_META];
00742                                 if(mref) {
00743                                         CComQIPtr<IMgaMetaBase> m(mgaproject->FindMetaRef(mref));
00744                                         CComPtr<IMgaMetaRegNode> rn;
00745                                         HRESULT hr;
00746                                         if (mypath == L"")
00747                                                 hr = S_OK;
00748                                         else
00749                                                 hr = m->get_RegistryNode(mypath, &rn);
00750                                         CComPtr<IMgaMetaRegNodes> rns;
00751                                         if(hr == S_OK) {
00752                                                 if (mypath == L"")
00753                                                         COMTHROW(m->get_RegistryNodes(&rns));
00754                                                 else
00755                                                         COMTHROW(rn->get_RegistryNodes(&rns));
00756                                                 MGACOLL_ITERATE(IMgaMetaRegNode, rns) {
00757                                                         CComBSTR path;
00758                                                         COMTHROW(MGACOLL_ITER->get_Name(&path));
00759                                                         CComBSTR subpath(mypath);
00760                                                         if (mypath != L"")
00761                                                                 COMTHROW(subpath.Append("/"));
00762                                                         COMTHROW(subpath.Append(path));
00763                                                         paths.insert(std::wstring(subpath));
00764                                                 } MGACOLL_ITERATE_END;
00765                                         }
00766                                 }
00767                         }
00768                         for (std::set<std::wstring>::iterator pathsIt = paths.begin(); pathsIt != paths.end(); pathsIt++)
00769                         {
00770                                 CComPtr<CMgaRegNode> regnode;
00771                                 CreateComObject(regnode);
00772                                 regnode->Initialize(CComBSTR(pathsIt->c_str()), fco, mgaproject);
00773                                 q->Append(regnode);
00774                         }
00775                         *pVal = q.Detach();
00776                 } COMCATCH(;)
00777 }
00778 
00779 STDMETHODIMP CMgaRegNode::get_SubNodeByName(BSTR name, IMgaRegNode **pVal) {
00780                 COMTRY {
00781                         fco->CheckRead();
00782                         CHECK_OUTPTRPAR(pVal);
00783                         CHECK_INSTRPAR(name);
00784       
00785                         CComBSTR xpath(mypath);
00786                         COMTHROW(xpath.Append(L"/"));
00787                         COMTHROW(xpath.AppendBSTR(name));
00788                         COMTHROW(fco->get_RegistryNode(xpath, pVal));
00789                 } COMCATCH(;)
00790 }
00791 
00792 STDMETHODIMP CMgaRegNode::get_ParentNode(IMgaRegNode **pVal) {
00793                 COMTRY {
00794                         fco->CheckRead();
00795                         CHECK_OUTPTRPAR(pVal);
00796       
00797                         wchar_t* p = (mypath == NULL ? NULL : wcsrchr(mypath, L'/'));
00798                         if(p) {
00799                                 CComBSTR xpath;
00800                                 xpath.Attach(::SysAllocStringLen(mypath,p-mypath));
00801                                 COMTHROW(fco->get_RegistryNode(xpath, pVal));
00802                         }
00803                 } COMCATCH(;);
00804 }
00805 
00806 
00807 STDMETHODIMP CMgaRegNode::Clear() {
00808                 COMTRY {
00809                         fco->CheckWrite();
00810                         SetValue(mypath, NULL_SENTINEL);
00811 
00812                         markchg();
00813                 } COMCATCH(;);
00814 }
00815 
00816 STDMETHODIMP CMgaRegNode::RemoveTree() {
00817         COMTRY {
00818                 fco->CheckWrite();
00819                 // lph: Pre-Notification PRE_STATUS (the registry node is being destroyed)
00820                 CComBSTR desc = L"REGISTRY,";
00821                 COMTHROW(desc.Append(mypath));
00822                 COMTHROW(desc.Append(L",Removed"));
00823                 fco->PreNotify(OBJEVENT_PRE_STATUS, CComVariant(desc));
00824 
00825                 {
00826                 // KMS: need to set ATTRID_REGNODE for write ops
00827                 CComVariant attr = fco->self[ATTRID_REGNODE];
00828                 fco->self[ATTRID_REGNODE] = attr;
00829                 }
00830 
00831                 CComVariant attr = fco->self[ATTRID_REGNODE];
00832                 CComPtr<ICoreDictionaryAttributeValue> oldval;
00833                 COMTHROW(attr.pdispVal->QueryInterface(&oldval));
00834                 VARIANT vmap;
00835                 COMTHROW(oldval->get_Map(&vmap));
00836                 map_type* map = (map_type*)(void*)vmap.llVal;
00837 
00838                 for (auto it = map->begin(); it != map->end();)
00839                 {
00840                         std::wstring path = it->first ? it->first : L"";
00841                         if (wcsncmp(path.c_str(), mypath, mypath.Length()) == 0)
00842                         {
00843                                 // PV: Remove only true subtree nodes (not just prefix testing)
00844                                 if (mypath.Length() == 0 || mypath.Length() == path.length() || (path.length() > mypath.Length() && path[mypath.Length()] == L'/')) {
00845                                         map->erase(it++);
00846                                         continue;       // modify collection while iterating
00847                                 }
00848                         }
00849                         it++;
00850                 }
00851                 // TODO
00852                 markchg();
00853         } COMCATCH(;);
00854 }
00855 
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 STDMETHODIMP CMgaPart::get_Model(struct IMgaModel **pVal ) {
00864                 COMTRY {
00865                         fco->CheckRead();
00866                         CHECK_OUTPTRPAR(pVal);
00867                         CComPtr<IMgaContainer> parent;
00868                         COMTHROW(fco->GetParent(&parent));
00869                         COMTHROW(parent.QueryInterface(pVal));
00870                 } COMCATCH(;);
00871 };
00872 
00873 STDMETHODIMP CMgaPart::get_MetaAspect(struct IMgaMetaAspect **pVal ) { 
00874                 COMTRY {
00875                         fco->CheckRead();
00876                         CHECK_OUTPTRPAR(pVal);
00877                         CComPtr<IMgaMetaPart> part;
00878                         part = CComQIPtr<IMgaMetaPart>(mgaproject->FindMetaRef(mref));
00879                         COMTHROW(part->get_ParentAspect(pVal));
00880                 } COMCATCH(;);
00881 };
00882 
00883 STDMETHODIMP CMgaPart::get_Meta(struct IMgaMetaPart **pVal ) { 
00884                 COMTRY {
00885                         fco->CheckRead();
00886                 CHECK_OUTPTRPAR(pVal);
00887                 *pVal = CComQIPtr<IMgaMetaPart>(mgaproject->FindMetaRef(mref)).Detach();
00888                 } COMCATCH(;);
00889 };
00890 
00891 STDMETHODIMP CMgaPart::get_MetaRole(struct IMgaMetaRole **pVal ) { 
00892                 COMTRY {
00893                         fco->CheckRead();
00894                         CHECK_OUTPTRPAR(pVal);
00895                         COMTHROW(fco->get_MetaRole(pVal));
00896                 } COMCATCH(;);
00897 }
00898 
00899  
00900 STDMETHODIMP CMgaPart::get_FCO(struct IMgaFCO **pVal) { 
00901                 COMTRY {
00902                         CHECK_OUTPTRPAR(pVal);
00903                         fco->getinterface(pVal); 
00904                 } COMCATCH(;);
00905 };
00906 
00907 STDMETHODIMP CMgaPart::get_AccessMask(long *) { return E_MGA_NOT_IMPLEMENTED; }
00908 
00909 STDMETHODIMP CMgaPart::GetGmeAttrs(BSTR *icon,long *x,long *y) { 
00910                 COMTRY {
00911                         fco->CheckRead();
00912                         CComBSTR vval;
00913                         _bstr_t regValueIcon;
00914                         if (icon)
00915                                 regValueIcon = RegistryValue[L"Icon"];
00916                         if(x || y) {
00917                                 CComBSTR bb;
00918                                 COMTHROW(get_RegistryValue(CComBSTR(L"Position"), &bb));
00919                                 long ld, *lx = x?x:&ld, *ly = y?y:&ld;
00920                                 if(!bb) { *lx = -1; *ly = -1;  }
00921                                 else if(swscanf(bb,OLESTR("%ld,%ld"), lx, ly) != 2) COMTHROW(E_MGA_BAD_POSITIONVALUE);
00922                         }
00923                         if (icon)
00924                                 *icon = regValueIcon.Detach();
00925                 } COMCATCH(;)
00926 }
00927 
00928 STDMETHODIMP CMgaPart::SetGmeAttrs(BSTR icon,long x,long y) { 
00929         COMTRY_IN_TRANSACTION_MAYBE {
00930                         fco->CheckWrite();
00931                         CComBSTR vval;
00932                         if(icon != NULL) COMTHROW(put_RegistryValue(CComBSTR(L"Icon"), icon));
00933                         if(x >= 0 && y >= 0) {
00934                                 OLECHAR bbc[40];
00935                                 swprintf(bbc, 40, OLESTR("%ld,%ld"), x, y);
00936                                 CComBSTR bb(bbc);
00937                                 COMTHROW(put_RegistryValue(CComBSTR(L"Position"), bb));
00938                         }
00939         } COMCATCH_IN_TRANSACTION_MAYBE(;)
00940 };
00941 
00942 
00943 STDMETHODIMP CMgaPart::get_RegistryMode( VARIANT_BOOL *own) {  return E_MGA_NOT_IMPLEMENTED; }
00944 STDMETHODIMP CMgaPart::put_RegistryMode( VARIANT_BOOL own) {  return E_MGA_NOT_IMPLEMENTED; }
00945 
00946 STDMETHODIMP CMgaPart::get_RegistryNode( BSTR path,  IMgaRegNode **pVal) {  
00947                 COMTRY {
00948                         fco->CheckRead();
00949                         CHECK_OUTPTRPAR(pVal);
00950                         CHECK_INSTRPAR(path);
00951       
00952                         CComBSTR xpath(regprefix);
00953                         COMTHROW(xpath.Append(L"/"));
00954                         COMTHROW(xpath.AppendBSTR(path));
00955                         COMTHROW(fco->get_RegistryNode(xpath, pVal));
00956                 } COMCATCH(;)
00957 }
00958 
00959 STDMETHODIMP CMgaPart::get_Registry(VARIANT_BOOL virtuals, IMgaRegNodes **pVal) {  
00960                 COMTRY {
00961                         fco->CheckRead();
00962                         CHECK_OUTPTRPAR(pVal);
00963                         CComPtr<IMgaRegNode> p;
00964                         COMTHROW(fco->get_RegistryNode(regprefix, &p));
00965                         COMTHROW(p->get_SubNodes(virtuals, pVal));
00966                 } COMCATCH(;);
00967 }
00968 
00969 STDMETHODIMP CMgaPart::get_RegistryValue( BSTR path,  BSTR *pVal) {  
00970                 COMTRY {
00971                         fco->CheckRead();
00972                         CHECK_OUTPAR(pVal);
00973                         CHECK_INSTRPAR(path);
00974                         CComPtr<IMgaRegNode> p;
00975                         COMTHROW(get_RegistryNode(path, &p));
00976                         COMTHROW(p->get_Value(pVal));
00977                 } COMCATCH(;)
00978 }
00979 
00980 STDMETHODIMP CMgaPart::put_RegistryValue( BSTR path,  BSTR newval) {  
00981                 COMTRY_IN_TRANSACTION_MAYBE {
00982                         fco->CheckWrite();
00983                         CHECK_INSTRPAR(path);
00984                         CHECK_INSTRPAR(newval);
00985                         CComPtr<IMgaRegNode> p;
00986                         COMTHROW(get_RegistryNode(path, &p));
00987                         COMTHROW(p->put_Value(newval));
00988                 } COMCATCH_IN_TRANSACTION_MAYBE(;)
00989 }
00990         
00991 
00992 CMgaPart::CMgaPart()    : prevptr(NULL), next(NULL), load_status(ATTSTATUS_INVALID) {   }
00993 CMgaPart::~CMgaPart() {                                         // remove object from hash
00994                 if (next)
00995                         next->prevptr = prevptr;
00996                 if (prevptr)
00997                         *prevptr = next;
00998 }
00999 void CMgaPart::Initialize(metaref_type mr, ::FCO *o, CMgaProject *p) {   // Throws!!!
01000                 mref = mr;              
01001                 fco = o;
01002                 mgaproject = p;
01003 }