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