GME
13
|
00001 #include "stdafx.h" 00002 #include "CoreBinFile.h" 00003 #include "CommonCollection.h" 00004 #include "..\Mga\MgaGeneric.h" 00005 00006 00007 /* 00008 examples: 00009 00010 MGA=D:\Data\metamodel.mga 00011 */ 00012 00013 // --------------------------- BinAttr 00014 00015 BinAttrBase *BinAttrBase::Create(BinAttrBase& attr, valtype_type valtype) 00016 { 00017 ASSERT( valtype != VALTYPE_NONE ); 00018 00019 BinAttrBase *binattr = NULL; 00020 00021 switch(valtype) 00022 { 00023 case VALTYPE_LONG: 00024 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_LONG>(); 00025 break; 00026 00027 case VALTYPE_STRING: 00028 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_STRING>(); 00029 break; 00030 00031 case VALTYPE_BINARY: 00032 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_BINARY>; 00033 break; 00034 00035 case VALTYPE_LOCK: 00036 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_LOCK>; 00037 break; 00038 00039 case VALTYPE_POINTER: 00040 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_POINTER>; 00041 break; 00042 00043 case VALTYPE_COLLECTION: 00044 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_COLLECTION>; 00045 break; 00046 00047 case VALTYPE_DICT: 00048 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_DICT>; 00049 break; 00050 case VALTYPE_REAL: 00051 binattr = new ((void*)(&attr)) BinAttr<VALTYPE_REAL>; 00052 break; 00053 00054 default: 00055 HR_THROW(E_METAPROJECT); 00056 } 00057 00058 // FIXME: can't take this if branch (is nothrow new intended?) 00059 if( binattr == NULL ) 00060 HR_THROW(E_OUTOFMEMORY); 00061 00062 return binattr; 00063 }; 00064 00065 // --------------------------- BinObject 00066 void getMeAGuid( long *p_l1, long *p_l2, long *p_l3, long *p_l4) 00067 { 00068 GUID t_guid = GUID_NULL; 00069 COMTHROW(CoCreateGuid(&t_guid)); 00070 00071 ASSERT(t_guid != GUID_NULL); 00072 //char buff[39]; 00073 //sprintf( buff, "{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}", 00074 // t_guid.Data1, t_guid.Data2, t_guid.Data3, 00075 // t_guid.Data4[0], t_guid.Data4[1], t_guid.Data4[2], t_guid.Data4[3], 00076 // t_guid.Data4[4], t_guid.Data4[5], t_guid.Data4[6], t_guid.Data4[7]); 00077 00078 // thus replace the old guid with a new one 00079 *p_l1 = t_guid.Data1; // Data1: 32 b, Data2, Data 3: 16 b, Data4: 64 bit 00080 *p_l2 = (t_guid.Data2 << 16) + t_guid.Data3; 00081 *p_l3 = (((((t_guid.Data4[0] << 8) + t_guid.Data4[1]) << 8) + t_guid.Data4[2]) << 8) + t_guid.Data4[3]; 00082 *p_l4 = (((((t_guid.Data4[4] << 8) + t_guid.Data4[5]) << 8) + t_guid.Data4[6]) << 8) + t_guid.Data4[7]; 00083 } 00084 00085 void WalkRegistry(CCoreDictionaryAttributeValue::map_type& map, CComBSTR& path, CCoreBinFile* p_bf, BinObject& node) 00086 { 00087 binattrs_iterator i = node.binattrs.begin(); 00088 binattrs_iterator e = node.binattrs.end(); 00089 while( i != e) 00090 { 00091 if( i->attrid == ATTRID_REGNOWNER + ATTRID_COLLECTION) { 00092 // Copy, since we're going to remove from it 00093 std::vector<objects_iterator> a = ((BinAttr<VALTYPE_COLLECTION>*)(void*)&(*i))->a; 00094 for (auto it = a.begin(); it != a.end(); it++) 00095 { 00096 objects_type::iterator regnode = p_bf->objects.find((*it)->first); 00097 if (regnode == p_bf->objects.end()) 00098 throw E_BINFILE; 00099 00100 CComVariant name; 00101 regnode->second.Find(ATTRID_NAME)->Get(p_bf, &name); 00102 #define RFLAG_HASVALUE 1 00103 #define RFLAG_OPAQUE 2 00104 CComVariant flag; 00105 regnode->second.Find(ATTRID_REGFLAGS)->Get(p_bf, &flag); 00106 00107 CComBSTR newPath(path); 00108 if (path != L"") 00109 newPath += L"/"; 00110 newPath += name.bstrVal; 00111 if (flag.intVal & RFLAG_HASVALUE) { 00112 CComVariant value; 00113 regnode->second.Find(ATTRID_REGNODEVALUE)->Get(p_bf, &value); 00114 map[newPath] = CComBSTR(value.bstrVal); 00115 } 00116 WalkRegistry(map, newPath, p_bf, regnode->second); 00117 p_bf->opened_object = regnode; 00118 regnode->second.Find(ATTRID_REGNOWNER)->Set(p_bf, CComVariant()); 00119 } 00120 return; 00121 } 00122 ++i; 00123 } 00124 } 00125 00126 void BinObject::UpgradeRegistryIfNecessary(CCoreBinFile* p_bf) 00127 { 00128 binattrs_iterator i = binattrs.begin(); 00129 binattrs_iterator e = binattrs.end(); 00130 while( i != e) 00131 { 00132 if( i->attrid == ATTRID_REGNOWNER + ATTRID_COLLECTION) { 00133 CCoreDictionaryAttributeValue::map_type map; 00134 00135 WalkRegistry(map, CComBSTR(), p_bf, *this); 00136 00137 BinAttrBase::Create(*i, VALTYPE_DICT); 00138 i->attrid = ATTRID_REGNODE; 00139 CComVariant dict; 00140 i->Get(p_bf, &dict); 00141 ((CCoreDictionaryAttributeValue*)dict.pdispVal)->m_dict = map; 00142 return; 00143 } 00144 ++i; 00145 } 00146 } 00147 00148 void BinObject::HasGuidAndStatAttributes(GUID& t_guid, bool* p_statusFound, bool* p_oldRegFound) 00149 { 00150 int a1( 0), a2( 0), a3( 0), a4( 0); 00151 00152 binattrs_iterator i = binattrs.begin(); 00153 binattrs_iterator e = binattrs.end(); 00154 while( i != e) 00155 { 00156 switch ((i)->attrid) 00157 { 00158 case ATTRID_GUID1: 00159 t_guid.Data1 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a; 00160 break; 00161 case ATTRID_GUID2: 00162 t_guid.Data2 = (reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a) >> 16; 00163 t_guid.Data3 = (reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a) & 0xFFFF; 00164 break; 00165 00166 case ATTRID_GUID3: { 00167 long v3 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a; 00168 t_guid.Data4[0] = (v3 >> 24); 00169 t_guid.Data4[1] = (v3 >> 16) & 0xFF; 00170 t_guid.Data4[2] = (v3 >> 8) & 0xFF; 00171 t_guid.Data4[3] = v3 & 0xFF; 00172 } break; 00173 case ATTRID_GUID4: { 00174 long v4 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a; 00175 t_guid.Data4[4] = (v4 >> 24); 00176 t_guid.Data4[5] = (v4 >> 16) & 0xFF; 00177 t_guid.Data4[6] = (v4 >> 8) & 0xFF; 00178 t_guid.Data4[7] = v4 & 0xFF; 00179 } break; 00180 case ATTRID_FILESTATUS: *p_statusFound = true; break; 00181 case ATTRID_REGNOWNER + ATTRID_COLLECTION: 00182 *p_oldRegFound = true; break; 00183 }; 00184 00185 ++i; 00186 } 00187 } 00188 00189 // this method will create Guid attributes for mga objects 00190 // loaded from MGA files saved with a previous version of gme 00191 void BinObject::CreateGuidAttributes( CCoreBinFile* p_bf) 00192 { 00193 // create a new guid 00194 CComVariant l1, l2, l3, l4; 00195 l4.vt = l3.vt = l2.vt = l1.vt = VT_I4; 00196 getMeAGuid( &l1.lVal, &l2.lVal, &l3.lVal, &l4.lVal); 00197 00198 // create BinAttrs of LONG type 00199 binattrs.emplace_back(ATTRID_NONE); 00200 BinAttrUnion& binattr1space = binattrs.back(); 00201 BinAttrBase* binattr1 = BinAttrBase::Create(binattr1space, VALTYPE_LONG); 00202 binattrs.emplace_back(ATTRID_NONE); 00203 BinAttrUnion& binattr2space = binattrs.back(); 00204 BinAttrBase* binattr2 = BinAttrBase::Create(binattr2space, VALTYPE_LONG); 00205 binattrs.emplace_back(ATTRID_NONE); 00206 BinAttrUnion& binattr3space = binattrs.back(); 00207 BinAttrBase* binattr3 = BinAttrBase::Create(binattr3space, VALTYPE_LONG); 00208 binattrs.emplace_back(ATTRID_NONE); 00209 BinAttrUnion& binattr4space = binattrs.back(); 00210 BinAttrBase* binattr4 = BinAttrBase::Create(binattr4space, VALTYPE_LONG); 00211 00212 00213 // fill the only public field 00214 binattr1->attrid = ATTRID_GUID1; 00215 binattr2->attrid = ATTRID_GUID2; 00216 binattr3->attrid = ATTRID_GUID3; 00217 binattr4->attrid = ATTRID_GUID4; 00218 00219 // set the values 00220 binattr1->Set( p_bf, l1); 00221 binattr2->Set( p_bf, l2); 00222 binattr3->Set( p_bf, l3); 00223 binattr4->Set( p_bf, l4); 00224 00225 } 00226 00227 // this method will create a status attribute for mga objects 00228 // loaded from MGA files saved with a previous version of gme 00229 void BinObject::CreateStatusAttribute( CCoreBinFile* p_bf) 00230 { 00231 // create BinAttr of LONG type 00232 binattrs.emplace_back(ATTRID_NONE); 00233 BinAttrUnion& binattrspace = binattrs.back(); 00234 BinAttrBase* binattr = BinAttrBase::Create(binattrspace, VALTYPE_LONG); 00235 00236 // fill the only public field 00237 binattr->attrid = ATTRID_FILESTATUS; 00238 00239 // set the value 00240 binattr->Set( p_bf, CComVariant( 0L)); 00241 } 00242 00243 void BinObject::CreateAttributes(ICoreMetaObject *metaobject) 00244 { 00245 ASSERT( metaobject != NULL ); 00246 ASSERT( binattrs.empty() ); 00247 00248 CComObjPtr<ICoreMetaAttributes> metaattributes; 00249 COMTHROW( metaobject->get_Attributes(PutOut(metaattributes)) ); 00250 ASSERT( metaattributes != NULL ); 00251 00252 typedef std::vector< CComObjPtr<ICoreMetaAttribute> > metaattributelist_type; 00253 metaattributelist_type metaattributelist; 00254 GetAll<ICoreMetaAttributes, ICoreMetaAttribute>(metaattributes, metaattributelist); 00255 00256 binattrs.reserve(metaattributelist.size()); 00257 00258 metaattributelist_type::iterator i = metaattributelist.begin(); 00259 metaattributelist_type::iterator e = metaattributelist.end(); 00260 while( i != e ) 00261 { 00262 valtype_type valtype; 00263 COMTHROW( (*i)->get_ValueType(&valtype) ); 00264 00265 attrid_type attrid = ATTRID_NONE; 00266 COMTHROW( (*i)->get_AttrID(&attrid) ); 00267 00268 binattrs.emplace_back(ATTRID_NONE); 00269 BinAttrUnion& binattrspace = binattrs.back(); 00270 BinAttrBase *binattr = BinAttrBase::Create(binattrspace, valtype); 00271 00272 ASSERT( attrid != ATTRID_NONE ); 00273 binattr->attrid = attrid; 00274 00275 ++i; 00276 } 00277 } 00278 00279 void BinObject::DestroyAttributes() 00280 { 00281 binattrs.clear(); 00282 } 00283 00284 void BinObject::Read(CCoreBinFile *binfile) 00285 { 00286 ASSERT( binfile != NULL ); 00287 ASSERT( binattrs.empty() ); 00288 00289 valtype_type valtype; 00290 00291 // First count how many attributes this object has, so we can intelligently size this->binattrs 00292 size_t num_attrs = 0; 00293 char* cifs_save = binfile->cifs; 00294 for (;;) 00295 { 00296 binfile->read(valtype); 00297 if( valtype == VALTYPE_NONE ) 00298 break; 00299 num_attrs++; 00300 00301 attrid_type attrid; 00302 binfile->read(attrid); 00303 00304 // These need to be the same as CCoreBinFile::Read()s, but without the expense 00305 switch(valtype) 00306 { 00307 case VALTYPE_LONG: 00308 { long x; binfile->read(x); } 00309 break; 00310 00311 case VALTYPE_STRING: 00312 { int len; binfile->read(len); binfile->cifs += len; } // FIXME maybe cifs > cifs_eof 00313 break; 00314 00315 case VALTYPE_DICT: 00316 case VALTYPE_BINARY: 00317 { int len; binfile->read(len); binfile->cifs += len; } // FIXME maybe cifs > cifs_eof 00318 break; 00319 00320 case VALTYPE_LOCK: 00321 break; 00322 00323 case VALTYPE_POINTER: 00324 { 00325 metaid_type metaid; 00326 binfile->read(metaid); 00327 if( metaid != METAID_NONE ) 00328 { 00329 objid_type objid; 00330 binfile->read(objid); 00331 } 00332 } 00333 00334 case VALTYPE_COLLECTION: 00335 break; 00336 00337 case VALTYPE_REAL: 00338 { double x; binfile->read(x); } 00339 break; 00340 00341 default: 00342 HR_THROW(E_METAPROJECT); 00343 } 00344 } 00345 binfile->cifs = cifs_save; 00346 binattrs.reserve(num_attrs); 00347 00348 for(;;) 00349 { 00350 binfile->read(valtype); 00351 if( valtype == VALTYPE_NONE ) 00352 break; 00353 00354 binattrs.emplace_back(ATTRID_NONE); 00355 BinAttrUnion& binattrspace = binattrs.back(); 00356 BinAttrBase *binattr = BinAttrBase::Create(binattrspace, valtype); 00357 ASSERT( binattr != NULL ); 00358 00359 attrid_type attrid; 00360 binfile->read(attrid); 00361 ASSERT( attrid != ATTRID_NONE ); 00362 00363 binattr->attrid = attrid; 00364 00365 // Possible pitfall: binattr == &binattrspace. It is possible the compiler will figure this out, and call BinAttrUnion::Read() (which we don't want) 00366 binattr->Read(binfile); 00367 } 00368 ASSERT(binattrs.size() == num_attrs); 00369 }; 00370 00371 void BinObject::Write(CCoreBinFile *binfile) 00372 { 00373 ASSERT( binfile != NULL ); 00374 ASSERT( !deleted ); 00375 00376 binattrs_iterator i = binattrs.begin(); 00377 binattrs_iterator e = binattrs.end(); 00378 while( i != e ) 00379 { 00380 ASSERT( (i)->GetValType() != VALTYPE_NONE ); 00381 ASSERT( (i)->attrid != ATTRID_NONE ); 00382 00383 binfile->write( (i)->GetValType() ); 00384 binfile->write( (i)->attrid ); 00385 (i)->Write(binfile); 00386 00387 ++i; 00388 } 00389 00390 binfile->write((valtype_type)VALTYPE_NONE); 00391 } 00392 00393 bool BinObject::HasEmptyPointers() const 00394 { 00395 if( deleted ) 00396 return true; 00397 00398 binattrs_type::const_iterator i = binattrs.begin(); 00399 binattrs_type::const_iterator e = binattrs.end(); 00400 while( i != e ) 00401 { 00402 if( (i)->GetValType() == VALTYPE_POINTER ) 00403 { 00404 if( !( ( ( BinAttr<VALTYPE_POINTER>*)(&*i))->isEmpty)) 00405 return false; 00406 } 00407 ++i; 00408 } 00409 00410 return true; 00411 } 00412 00413 // --------------------------- CCoreBinFile 00414 00415 CCoreBinFile::CCoreBinFile() 00416 { 00417 metaid = METAID_NONE; 00418 attrid = ATTRID_NONE; 00419 intrans = false; 00420 modified = false; 00421 isEmpty = true; 00422 } 00423 00424 CCoreBinFile::~CCoreBinFile() 00425 { 00426 } 00427 00428 // ------- MetaProject 00429 00430 STDMETHODIMP CCoreBinFile::get_MetaProject(ICoreMetaProject **p) 00431 { 00432 CHECK_OUT(p); 00433 00434 CopyTo(metaproject, p); 00435 00436 return S_OK; 00437 } 00438 00439 STDMETHODIMP CCoreBinFile::put_MetaProject(ICoreMetaProject *p) 00440 { 00441 COMTRY 00442 { 00443 CloseMetaProject(); 00444 00445 metaproject = p; 00446 00447 if( metaproject != NULL ) 00448 OpenMetaProject(); 00449 } 00450 COMCATCH( CloseMetaProject() ) 00451 } 00452 00453 void CCoreBinFile::OpenMetaProject() 00454 { 00455 ASSERT( metaprojectid.empty() ); 00456 ASSERT( metaproject != NULL ); 00457 00458 CComVariant tmp; 00459 COMTHROW(metaproject->get_GUID(PutOut(tmp))); 00460 CopyTo(tmp, metaprojectid); 00461 } 00462 00463 void CCoreBinFile::CloseMetaProject() 00464 { 00465 if( IsOpened() && metaproject != NULL ) 00466 CloseProject(); 00467 00468 CloseMetaObject(); 00469 00470 metaproject = NULL; 00471 metaprojectid.clear(); 00472 } 00473 00474 // ------- MetaObject 00475 00476 STDMETHODIMP CCoreBinFile::get_MetaObject(ICoreMetaObject **p) 00477 { 00478 CHECK_OUT(p); 00479 00480 CopyTo(metaobject, p); 00481 00482 return S_OK; 00483 } 00484 00485 STDMETHODIMP CCoreBinFile::put_MetaObject(ICoreMetaObject *p) 00486 { 00487 if( metaproject == NULL ) 00488 COMRETURN(E_INVALID_USAGE); 00489 00490 if( metaobject == p ) 00491 return S_OK; 00492 00493 COMTRY 00494 { 00495 if( p != NULL ) 00496 { 00497 CComObjPtr<ICoreMetaProject> t; 00498 COMTHROW( p->get_Project(PutOut(t)) ); 00499 if( !IsEqualObject(metaproject, t) ) 00500 HR_THROW(E_SAMEPROJECT); 00501 } 00502 00503 CloseMetaObject(); 00504 metaobject = p; 00505 if( metaobject != NULL ) 00506 OpenMetaObject(); 00507 } 00508 COMCATCH( CloseMetaObject() ) 00509 } 00510 00511 STDMETHODIMP CCoreBinFile::get_MetaID(metaid_type *p) 00512 { 00513 CHECK_OUT(p); 00514 00515 *p = metaid; 00516 00517 return S_OK; 00518 } 00519 00520 STDMETHODIMP CCoreBinFile::put_MetaID(metaid_type metaid) 00521 { 00522 if( metaproject == NULL ) 00523 COMRETURN(E_INVALID_USAGE); 00524 00525 COMTRY 00526 { 00527 if( metaid != METAID_NONE ) 00528 { 00529 CComObjPtr<ICoreMetaObject> p; 00530 COMTHROW( metaproject->get_Object(metaid, PutOut(p)) ); 00531 ASSERT( p != NULL ); 00532 00533 if( metaobject != p ) 00534 { 00535 CloseMetaObject(); 00536 MoveTo(p, metaobject); 00537 OpenMetaObject(); 00538 } 00539 } 00540 else 00541 CloseMetaObject(); 00542 } 00543 COMCATCH( CloseMetaObject() ) 00544 } 00545 00546 void CCoreBinFile::OpenMetaObject() 00547 { 00548 ASSERT( metaobject != NULL ); 00549 00550 COMTHROW( metaobject->get_MetaID(&metaid) ); 00551 } 00552 00553 void CCoreBinFile::CloseMetaObject() 00554 { 00555 CloseObject(); 00556 CloseMetaAttribute(); 00557 metaobject = NULL; 00558 metaid = METAID_NONE; 00559 } 00560 00561 // ------- MetaAttribute 00562 00563 STDMETHODIMP CCoreBinFile::get_MetaAttribute(ICoreMetaAttribute **p) 00564 { 00565 CHECK_OUT(p); 00566 00567 CopyTo(metaattribute, p); 00568 00569 return S_OK; 00570 } 00571 00572 STDMETHODIMP CCoreBinFile::put_MetaAttribute(ICoreMetaAttribute *p) 00573 { 00574 if( metaobject == NULL ) 00575 COMRETURN(E_INVALID_USAGE); 00576 ASSERT( metaproject != NULL ); 00577 00578 if( metaattribute == p ) 00579 return S_OK; 00580 00581 COMTRY 00582 { 00583 if( metaattribute != NULL ) 00584 { 00585 CComObjPtr<ICoreMetaObject> t; 00586 COMTHROW( metaattribute->get_Object(PutOut(t)) ); 00587 if( !IsEqualObject(metaobject, t) ) 00588 { 00589 metaattribute = NULL; 00590 return E_INVALIDARG; 00591 } 00592 } 00593 00594 CloseMetaAttribute(); 00595 metaattribute = p; 00596 if( metaattribute != NULL ) 00597 OpenMetaAttribute(); 00598 } 00599 COMCATCH( CloseMetaAttribute() ) 00600 } 00601 00602 STDMETHODIMP CCoreBinFile::get_AttrID(attrid_type *p) 00603 { 00604 CHECK_OUT(p); 00605 00606 if( metaattribute ) 00607 return metaattribute->get_AttrID(p); 00608 00609 *p = 0; 00610 return S_OK; 00611 } 00612 00613 STDMETHODIMP CCoreBinFile::put_AttrID(attrid_type attrid) 00614 { 00615 if( metaobject == NULL ) 00616 COMRETURN(E_INVALID_USAGE); 00617 ASSERT( metaproject != NULL ); 00618 00619 COMTRY 00620 { 00621 if( attrid != ATTRID_NONE ) 00622 { 00623 CComObjPtr<ICoreMetaAttribute> p; 00624 COMTHROW( metaobject->get_Attribute(attrid, PutOut(p)) ); 00625 ASSERT( p != NULL ); 00626 00627 if( metaattribute != p ) 00628 { 00629 CloseMetaAttribute(); 00630 metaattribute = p; 00631 OpenMetaAttribute(); 00632 } 00633 } 00634 else 00635 CloseMetaAttribute(); 00636 } 00637 COMCATCH( CloseMetaAttribute() ) 00638 } 00639 00640 void CCoreBinFile::OpenMetaAttribute() 00641 { 00642 ASSERT( metaattribute != NULL ); 00643 00644 COMTHROW( metaattribute->get_AttrID(&attrid) ); 00645 00646 if( attrid == ATTRID_NONE ) 00647 HR_THROW(E_METAPROJECT); 00648 } 00649 00650 void CCoreBinFile::CloseMetaAttribute() 00651 { 00652 metaattribute = NULL; 00653 attrid = ATTRID_NONE; 00654 } 00655 00656 // ------- Ios 00657 00658 void CCoreBinFile::read(bindata &b) 00659 { 00660 int len; 00661 00662 read(len); 00663 ASSERT( len >= 0 ); 00664 00665 try { 00666 b.resize(len); 00667 } catch (std::bad_alloc&) { 00668 // KMS: could get here if the project is corrupt and len is incorrect 00669 COMTHROW(E_OUTOFMEMORY); 00670 } 00671 if( len > 0 ) { 00672 if (len > cifs_eof - cifs) { 00673 HR_THROW(E_FILEOPEN); 00674 } 00675 memcpy(&b[0], cifs, len); 00676 cifs += len; 00677 } 00678 } 00679 00680 void CCoreBinFile::read(unsigned char*& b, int& len) 00681 { 00682 read(len); 00683 ASSERT( len >= 0 ); 00684 00685 b = (unsigned char*)malloc(len); 00686 if (b == NULL) { 00687 // KMS: could get here if the project is corrupt and len is incorrect 00688 COMTHROW(E_OUTOFMEMORY); 00689 } 00690 if( len > 0 ) { 00691 if (len > cifs_eof - cifs) { 00692 HR_THROW(E_FILEOPEN); 00693 } 00694 memcpy(b, cifs, len); 00695 cifs += len; 00696 } 00697 } 00698 00699 void CCoreBinFile::readstring(char*& pos) { 00700 pos = cifs; 00701 int len; 00702 00703 read(len); 00704 cifs += len; 00705 } 00706 00707 void CCoreBinFile::read(CComBstrObj &ss) 00708 { 00709 read(ss, cifs); 00710 } 00711 00712 void CCoreBinFile::read(CComBstrObj &ss, char*& cifs) 00713 { 00714 int len; 00715 00716 //read(len); 00717 // use local cifs 00718 CoreBinFile_read(len, 4); 00719 ASSERT( len >= 0 ); 00720 00721 if( len > 0 ) { 00722 if (len > cifs_eof - cifs) { 00723 HR_THROW(E_FILEOPEN); 00724 } 00725 CopyTo(cifs, len, &ss.p, CP_UTF8); 00726 cifs += len; 00727 } else { 00728 std::string s; 00729 CopyTo(s, ss); 00730 } 00731 } 00732 00733 void CCoreBinFile::write(const bindata &b) 00734 { 00735 ASSERT( ofs.is_open() ); 00736 00737 int len = b.size(); 00738 ASSERT( len >= 0 ); 00739 00740 write(len); 00741 00742 if( len > 0 ) 00743 ofs.write( (const char *) &b[0], len); 00744 } 00745 00746 void CCoreBinFile::write(const unsigned char* b, int len) 00747 { 00748 ASSERT( ofs.is_open() ); 00749 00750 ASSERT( len >= 0 ); 00751 00752 write(len); 00753 00754 if( len > 0 ) 00755 ofs.write( (const char *) b, len); 00756 } 00757 00758 void CCoreBinFile::write(const CComBstrObj &ss) 00759 { 00760 ASSERT( ofs.is_open() ); 00761 00762 int len = GetCharLength(ss, SysStringLen(ss.p), CP_UTF8); 00763 char* s = NULL; 00764 if (len) { 00765 s = new char[len]; 00766 CopyTo(ss.p, s, len, CP_UTF8); 00767 } 00768 00769 ASSERT( len >= 0 ); 00770 00771 write(len); 00772 00773 if( len > 0 ) 00774 ofs.write( (const char *) &s[0], len); 00775 delete[] s; 00776 } 00777 00778 void CCoreBinFile::writestring(const char* pos) 00779 { 00780 int len; 00781 memcpy(&len, pos, sizeof(len)); 00782 write(len); 00783 ofs.write(pos+sizeof(int), len); 00784 } 00785 00786 00787 // ------- Attribute 00788 00789 STDMETHODIMP CCoreBinFile::get_AttributeValue(VARIANT *p) 00790 { 00791 CHECK_OUT(p); 00792 00793 if( isEmpty || !InTransaction()) 00794 COMRETURN(E_INVALID_USAGE); 00795 00796 COMTRY 00797 { 00798 BinAttrBase *attr = opened_object->second.Find(attrid); 00799 ASSERT( attr != NULL ); 00800 00801 attr->Get(this, p); 00802 } 00803 COMCATCH(;) 00804 } 00805 00806 STDMETHODIMP CCoreBinFile::put_AttributeValue(VARIANT p) 00807 { 00808 if( isEmpty || !InTransaction()) 00809 COMRETURN(E_INVALID_USAGE); 00810 00811 COMTRY 00812 { 00813 BinAttrBase *attr = opened_object->second.Find(attrid); 00814 00815 /* std::pair<BinAttrBase *const, CComVariant> r(attr, CComVariant()); 00816 std::pair<undos_iterator, bool> t = undos.insert(r); 00817 00818 if( t.second ) 00819 attr->Get(this, PutOut(t.first->second)); 00820 */ 00821 attr->Set(this, p); 00822 } 00823 COMCATCH(;) 00824 } 00825 00826 // ------- Object 00827 00828 void CCoreBinFile::InitMaxObjIDs() 00829 { 00830 ASSERT( metaproject != NULL ); 00831 00832 maxobjids.clear(); 00833 00834 CComObjPtr<ICoreMetaObjects> metaobjects; 00835 COMTHROW( metaproject->get_Objects(PutOut(metaobjects)) ); 00836 ASSERT( metaobjects != NULL ); 00837 00838 typedef std::vector< CComObjPtr<ICoreMetaObject> > metaobjectlist_type; 00839 metaobjectlist_type metaobjectlist; 00840 GetAll<ICoreMetaObjects, ICoreMetaObject>(metaobjects, metaobjectlist); 00841 00842 metaobjectlist_type::iterator i = metaobjectlist.begin(); 00843 metaobjectlist_type::iterator e = metaobjectlist.end(); 00844 while( i != e ) 00845 { 00846 ASSERT( *i != NULL ); 00847 00848 metaid_type metaid = METAID_NONE; 00849 COMTHROW( (*i)->get_MetaID(&metaid) ); 00850 ASSERT( metaid != METAID_NONE ); 00851 00852 ASSERT( maxobjids.find(metaid) == maxobjids.end() ); 00853 maxobjids.insert( core::pair<const metaid_type, objid_type>(metaid, OBJID_NONE) ); 00854 00855 ++i; 00856 } 00857 } 00858 00859 STDMETHODIMP CCoreBinFile::OpenObject(objid_type objid) 00860 { 00861 if( metaobject == NULL || !InTransaction() ) 00862 COMRETURN(E_INVALID_USAGE); 00863 00864 ASSERT( metaid != METAID_NONE ); 00865 00866 metaobjidpair_type idpair; 00867 idpair.metaid = metaid; 00868 idpair.objid = objid; 00869 00870 if( !isEmpty && 00871 metaobjidpair_equalkey()(opened_object->first, idpair) ) 00872 return S_OK; 00873 00874 COMTRY 00875 { 00876 opened_object = objects.find(idpair); 00877 isEmpty = false; 00878 if( (opened_object == objects.end()) || 00879 opened_object->second.deleted ) 00880 { 00881 isEmpty = true; 00882 HR_THROW(E_NOTFOUND); 00883 } 00884 } 00885 COMCATCH(;) 00886 } 00887 00888 STDMETHODIMP CCoreBinFile::CreateObject(objid_type *objid) 00889 { 00890 CHECK_OUT(objid); 00891 00892 if( metaobject == NULL || !InTransaction() ) 00893 COMRETURN(E_INVALID_USAGE); 00894 00895 COMTRY 00896 { 00897 modified = true; 00898 00899 isEmpty = true; 00900 00901 ASSERT( metaid != METAID_NONE ); 00902 00903 maxobjids_iterator i = maxobjids.find(metaid); 00904 ASSERT( i != maxobjids.end() ); 00905 00906 metaobjidpair_type idpair; 00907 idpair.metaid = metaid; 00908 idpair.objid = ++(i->second); 00909 00910 ASSERT( metaobject != NULL ); 00911 00912 std::pair<objects_iterator, bool> t = objects.insert( 00913 objects_type::value_type(idpair,BinObject())); 00914 ASSERT( t.second ); 00915 00916 t.first->second.deleted = false; 00917 t.first->second.CreateAttributes(metaobject); 00918 00919 created_objects.push_front(t.first); 00920 00921 opened_object = t.first; 00922 isEmpty = false; 00923 *objid = idpair.objid; 00924 } 00925 COMCATCH(;) 00926 } 00927 00928 STDMETHODIMP CCoreBinFile::CloseObject() 00929 { 00930 isEmpty = true; 00931 return S_OK; 00932 } 00933 00934 STDMETHODIMP CCoreBinFile::LockObject() 00935 { 00936 if( isEmpty || !InTransaction()) 00937 COMRETURN(E_INVALID_USAGE); 00938 00939 return S_OK; 00940 } 00941 00942 STDMETHODIMP CCoreBinFile::DeleteObject() 00943 { 00944 if( isEmpty || !InTransaction()) 00945 COMRETURN(E_INVALID_USAGE); 00946 00947 ASSERT( metaobject != NULL ); 00948 00949 ASSERT( opened_object->second.deleted == false ); 00950 00951 modified = true; 00952 00953 deleted_objects.push_front(opened_object); 00954 00955 opened_object->second.deleted = true; 00956 isEmpty = true; 00957 00958 return S_OK; 00959 } 00960 00961 // ------- Project 00962 00963 void CCoreBinFile::CancelProject() 00964 { 00965 CloseMetaObject(); 00966 00967 cifs = 0; 00968 cifs_eof = 0; 00969 00970 if( ofs.is_open() ) 00971 ofs.close(); 00972 00973 filename.clear(); 00974 intrans = false; 00975 modified = false; 00976 00977 isEmpty = true; 00978 deleted_objects.clear(); 00979 created_objects.clear(); 00980 maxobjids.clear(); 00981 resolvelist.clear(); 00982 objects.clear(); 00983 } 00984 00985 static DWORD __stdcall prog(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred,LARGE_INTEGER StreamSize, 00986 LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData) 00987 { 00988 return PROGRESS_STOP; 00989 } 00990 00991 00992 void CCoreBinFile::SaveProject(const std::wstring& origfname, bool keepoldname) 00993 { 00994 ASSERT( !ofs.is_open() ); 00995 ASSERT( metaprojectid.size() == 16 ); 00996 00997 00998 std::wstring filenameout = filename; 00999 // origfname == filename => file_buffer has filename locked FILE_SHARE_READ 01000 // CopyFile because: 01001 // SetEndOfFileInformationFile 01002 // Preserves extended attributes, NTFS alternate streams, file attributes (and newer Windows: security attributes) 01003 if (origfname == filename && GetFileAttributesW(origfname.c_str()) != INVALID_FILE_ATTRIBUTES) 01004 { 01005 filenameout += L"tmp"; 01006 BOOL cancel = FALSE; 01007 BOOL succ = CopyFileExW(origfname.c_str(), filenameout.c_str(), &prog, NULL, &cancel, 0); 01008 if (!succ && GetLastError() != ERROR_REQUEST_ABORTED) 01009 { 01010 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 01011 _bstr_t err; 01012 GetErrorInfo(hr, err.GetAddress()); 01013 throw_com_error(hr, _bstr_t(L"Error saving '") + filenameout.c_str() + L"': " + err); 01014 } 01015 } 01016 // TODO: 01017 // GetNamedSecurityInfo(source, GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION) 01018 // SetNamedSecurityInfo(target, GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION) 01019 01020 ofs.clear(); 01021 ofs.open(filenameout.c_str(), std::ios::out | std::ios::binary); 01022 if( ofs.fail() || !ofs.is_open() ) { 01023 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 01024 ofs.close(); 01025 ofs.clear(); 01026 _bstr_t err; 01027 GetErrorInfo(hr, err.GetAddress()); 01028 throw_com_error(hr, _bstr_t(L"Error saving '") + filenameout.c_str() + L"': " + err); 01029 } 01030 01031 write(metaprojectid); 01032 01033 objects_iterator i = objects.begin(); 01034 objects_iterator e = objects.end(); 01035 while( i != e ) 01036 { 01037 ASSERT( (*i).first.metaid != METAID_NONE ); 01038 ASSERT( (*i).first.objid != OBJID_NONE ); 01039 01040 if( ((*i).first.metaid == METAID_ROOT && (*i).first.objid == OBJID_ROOT) 01041 || !(*i).second.HasEmptyPointers() ) 01042 { 01043 write( (metaid_type)(*i).first.metaid ); 01044 write( (objid_type)(*i).first.objid ); 01045 01046 (*i).second.Write(this); 01047 } 01048 01049 ++i; 01050 } 01051 01052 write((metaid_type)METAID_NONE); 01053 01054 if( ofs.fail() ) 01055 HR_THROW(E_FILEOPEN); 01056 01057 ofs.close(); 01058 01059 if( ofs.fail() ) 01060 HR_THROW(E_FILEOPEN); 01061 01062 file_buffer.~membuf(); 01063 new ((void*)&file_buffer) membuf(); 01064 01065 if (origfname == filename) 01066 { 01067 BOOL succ = MoveFileExW(filenameout.c_str(), filename.c_str(), MOVEFILE_REPLACE_EXISTING); 01068 if (!succ) 01069 { 01070 HR_THROW(HRESULT_FROM_WIN32(GetLastError())); 01071 } 01072 } 01073 01074 if (file_buffer.open((keepoldname ? origfname : filename).c_str()) != 0) { 01075 HR_THROW(HRESULT_FROM_WIN32(GetLastError())); 01076 } 01077 cifs = file_buffer.getBegin(); 01078 cifs_eof = file_buffer.getEnd(); 01079 } 01080 01081 // KMS: due to a bug in MgaFolder::CopyFCOs (ObjTreeCopyFoldersToo) fixed in r2297, some mga files may have duplicate GUIDs 01082 static void SetNewGuid(CCoreBinFile* p_bf, BinObject& o) 01083 { 01084 CComVariant l1, l2, l3, l4; 01085 l4.vt = l3.vt = l2.vt = l1.vt = VT_I4; 01086 getMeAGuid( &l1.lVal, &l2.lVal, &l3.lVal, &l4.lVal); 01087 01088 binattrs_iterator i = o.binattrs.begin(); 01089 binattrs_iterator e = o.binattrs.end(); 01090 while( i != e) 01091 { 01092 switch (i->attrid) 01093 { 01094 case ATTRID_GUID1: 01095 i->Set(p_bf, l1); 01096 break; 01097 case ATTRID_GUID2: 01098 i->Set(p_bf, l2); 01099 break; 01100 case ATTRID_GUID3: 01101 i->Set(p_bf, l3); 01102 break; 01103 case ATTRID_GUID4: 01104 i->Set(p_bf, l4); 01105 break; 01106 default: 01107 break; 01108 } 01109 i++; 01110 } 01111 } 01112 01113 struct GUID_hash { 01114 size_t operator()(const GUID& guid) const 01115 { 01116 int* iGuid = (int*)(void*)&guid; 01117 return iGuid[0] ^ iGuid[1] ^ iGuid[2] ^ iGuid[3]; 01118 } 01119 }; 01120 01121 void CCoreBinFile::LoadProject() 01122 { 01123 InitMaxObjIDs(); 01124 01125 if (file_buffer.open(filename.c_str()) != 0) { 01126 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 01127 _bstr_t err; 01128 GetErrorInfo(hr, err.GetAddress()); 01129 throw_com_error(hr, _bstr_t(L"Error opening '") + filename.c_str() + L"': " + err); 01130 } 01131 cifs = file_buffer.getBegin(); 01132 cifs_eof = file_buffer.getEnd(); 01133 01134 std::unordered_map<GUID, bool, GUID_hash> guids; 01135 01136 bindata guid; 01137 read(guid); 01138 01139 if( !(guid == metaprojectid) ) 01140 HR_THROW(E_PROJECT_MISMATCH); 01141 01142 ASSERT( resolvelist.empty() ); 01143 bool oldReg_found = false; 01144 01145 for(;;) 01146 { 01147 metaid_type metaid; 01148 read(metaid); 01149 if( metaid == METAID_NONE ) 01150 break; 01151 01152 objid_type objid; 01153 read(objid); 01154 ASSERT( objid != OBJID_NONE ); 01155 01156 maxobjids_iterator i = maxobjids.find(metaid); 01157 if (i == maxobjids.end()) 01158 { 01159 // e.g. 0x79==121: registry node from old-style registry 01160 i = maxobjids.insert(maxobjids_type::value_type(metaid, 1)).first; 01161 } 01162 01163 if( i->second < objid ) 01164 i->second = objid; 01165 01166 metaobjidpair_type idpair; 01167 idpair.metaid = metaid; 01168 idpair.objid = objid; 01169 01170 std::pair<objects_iterator, bool> t = objects.insert( 01171 objects_type::value_type(idpair,BinObject())); 01172 ASSERT( t.second ); 01173 01174 opened_object = t.first; 01175 isEmpty = false; 01176 opened_object->second.deleted = false; 01177 opened_object->second.Read(this); 01178 01179 // if the object read is folder or fco and it does NOT have guid attributes (old version mga file) 01180 if( metaid >= DTID_MODEL && metaid <= DTID_FOLDER) // 101 .. 106 01181 { 01182 bool stat_found( false); 01183 01184 GUID zero_guid = {0}; 01185 GUID guid = {0}; 01186 opened_object->second.HasGuidAndStatAttributes(guid, &stat_found, &oldReg_found); 01187 01188 if(guid == zero_guid) // we will create guid attributes for it 01189 opened_object->second.CreateGuidAttributes( this); 01190 01191 std::pair<std::hash_map<GUID, bool>::iterator, bool> guid_insert = guids.emplace(std::make_pair(guid, true)); 01192 if (guid_insert.second == false) 01193 { 01194 SetNewGuid(this, opened_object->second); 01195 } 01196 01197 if( !stat_found && ( metaid == DTID_MODEL || metaid == DTID_FOLDER)) // we will create status attribute for M and F 01198 opened_object->second.CreateStatusAttribute( this); 01199 } 01200 } 01201 01202 resolvelist_type::iterator i = resolvelist.begin(); 01203 resolvelist_type::iterator e = resolvelist.end(); 01204 while( i != e ) 01205 { 01206 opened_object = i->obj; 01207 isEmpty = false; 01208 01209 // ASSERT( !isEmpty ); 01210 01211 BinAttrBase *base = opened_object->second.Find(i->attrid); 01212 ASSERT( base != NULL ); 01213 01214 ASSERT( base->GetValType() == VALTYPE_POINTER ); 01215 01216 objects_iterator j = objects.find( i->idpair ); 01217 if( j == objects.end() ) 01218 HR_THROW(E_BINFILE); 01219 01220 ((BinAttr<VALTYPE_POINTER>*)base)->Set(this, j); 01221 01222 ++i; 01223 } 01224 01225 isEmpty = true; 01226 resolvelist.clear(); 01227 01228 if (oldReg_found) { 01229 for (auto it = objects.begin(); it != objects.end(); it++) 01230 { 01231 if (it->first.metaid >= DTID_MODEL && it->first.metaid <= DTID_FOLDER) // 101 .. 106 01232 { 01233 it->second.UpgradeRegistryIfNecessary(this); 01234 } 01235 } 01236 for (auto it = objects.begin(); it != objects.end(); ) 01237 { 01238 if (it->first.metaid == DTID_REGNODE) 01239 objects.erase(it++); 01240 else 01241 it++; 01242 } 01243 } 01244 01245 ofs.clear(); 01246 // FIXME: set read_only correctly 01247 read_only = false; 01248 } 01249 01250 STDMETHODIMP CCoreBinFile::OpenProject(BSTR connection, VARIANT_BOOL *ro_mode) { 01251 if( IsOpened() || metaproject == NULL ) 01252 COMRETURN(E_INVALID_USAGE); 01253 01254 COMTRY 01255 { 01256 if (SysStringLen(connection)) 01257 filename = connection; 01258 if (!(std::wstring(filename, 0, 4) == L"MGA=")) 01259 throw_com_error(E_INVALID_USAGE, L"Connection string must start with MGA="); 01260 01261 filename.erase(0, 4); 01262 01263 LoadProject(); 01264 01265 01266 modified = false; 01267 if(ro_mode) *ro_mode = read_only ? VARIANT_TRUE : VARIANT_FALSE; 01268 01269 ASSERT( IsOpened() ); 01270 } 01271 COMCATCH( CancelProject(); ) 01272 } 01273 01274 STDMETHODIMP CCoreBinFile::CreateProject(BSTR connection) 01275 { 01276 if( IsOpened() || metaproject == NULL ) 01277 COMRETURN(E_INVALID_USAGE); 01278 01279 COMTRY 01280 { 01281 if (SysStringLen(connection)) 01282 filename = connection; 01283 if( !(std::wstring(filename, 0, 4) == L"MGA=") ) 01284 throw_com_error(E_INVALID_USAGE, L"Connection string must start with MGA="); 01285 01286 01287 filename.erase(0, 4); 01288 01289 InitMaxObjIDs(); 01290 01291 CComObjPtr<ICoreMetaObject> mo; 01292 COMTHROW( metaproject->get_Object(METAID_ROOT, PutOut(mo)) ); 01293 ASSERT( mo != NULL ); 01294 01295 maxobjids_iterator i = maxobjids.find(METAID_ROOT); 01296 i->second = OBJID_ROOT; 01297 01298 metaobjidpair_type idpair; 01299 idpair.metaid = METAID_ROOT; 01300 idpair.objid = OBJID_ROOT; 01301 01302 std::pair<objects_iterator, bool> t = objects.insert( 01303 objects_type::value_type(idpair,BinObject())); 01304 ASSERT( t.second ); 01305 01306 t.first->second.deleted = false; 01307 t.first->second.CreateAttributes(mo); 01308 01309 if (filename.empty()) 01310 filename = L"."; 01311 01312 modified = false; 01313 01314 ASSERT( IsOpened() ); 01315 } 01316 COMCATCH( CancelProject(); ) 01317 } 01318 01319 STDMETHODIMP CCoreBinFile::SaveProject(BSTR connection, VARIANT_BOOL keepoldname = VARIANT_TRUE) 01320 { 01321 std::wstring origfname = filename; 01322 COMTRY 01323 { 01324 std::wstring fn; 01325 if (SysStringLen(connection)) 01326 fn = connection; 01327 01328 if( !fn.empty() ) 01329 { 01330 if( !(std::wstring(fn, 0, 4) == L"MGA=") ) 01331 { 01332 throw_com_error(E_INVALID_USAGE, L"Connection string must start with MGA="); 01333 } 01334 01335 fn.erase(0, 4); 01336 filename = fn; 01337 if(filename.empty()) 01338 filename = L"."; 01339 } 01340 if (filename == L".") 01341 COMTHROW(E_NAMEMISSING); 01342 SaveProject(origfname, keepoldname != VARIANT_FALSE); 01343 if (keepoldname != VARIANT_FALSE) 01344 filename = origfname; 01345 } 01346 COMCATCH( filename = origfname;) 01347 } 01348 01349 STDMETHODIMP CCoreBinFile::CloseProject( VARIANT_BOOL abort) { 01350 if( !IsOpened() || metaproject == NULL ) 01351 COMRETURN(E_INVALID_USAGE); 01352 01353 COMTRY 01354 { 01355 if( abort == VARIANT_FALSE && modified && !(filename == L".")) 01356 { 01357 HRESULT hr = SaveProject(NULL); 01358 if (FAILED(hr)) 01359 HR_THROW(hr); 01360 } 01361 01362 ASSERT( IsOpened() ); 01363 01364 CancelProject(); 01365 } 01366 COMCATCH(;) 01367 } 01368 01369 STDMETHODIMP CCoreBinFile::BeginTransaction() 01370 { 01371 if( !IsOpened() || InTransaction() ) 01372 COMRETURN(E_INVALID_USAGE); 01373 01374 ASSERT( deleted_objects.empty() ); 01375 ASSERT( created_objects.empty() ); 01376 01377 intrans = true; 01378 01379 return S_OK; 01380 } 01381 01382 STDMETHODIMP CCoreBinFile::CommitTransaction() 01383 { 01384 if( !InTransaction() ) 01385 COMRETURN(E_INVALID_USAGE); 01386 01387 ASSERT( IsOpened() ); 01388 01389 CloseObject(); 01390 01391 auto i = deleted_objects.begin(); 01392 auto e = deleted_objects.end(); 01393 while( i != e ) 01394 { 01395 ASSERT( (*i)->second.deleted ); 01396 01397 objects.erase(*i); 01398 01399 ++i; 01400 } 01401 01402 undos.clear(); 01403 deleted_objects.clear(); 01404 created_objects.clear(); 01405 01406 intrans = false; 01407 01408 return S_OK; 01409 } 01410 01411 STDMETHODIMP CCoreBinFile::AbortTransaction() 01412 { 01413 if( !InTransaction() ) 01414 COMRETURN(E_INVALID_USAGE); 01415 01416 ASSERT( IsOpened() ); 01417 01418 CloseObject(); 01419 01420 undos_iterator j = undos.begin(); 01421 undos_iterator f = undos.end(); 01422 while( j != f ) 01423 { 01424 j->first->Set(this, j->second); 01425 01426 ++j; 01427 } 01428 01429 auto i = deleted_objects.begin(); 01430 auto e = deleted_objects.end(); 01431 while( i != e ) 01432 { 01433 ASSERT( (*i)->second.deleted ); 01434 01435 (*i)->second.deleted = false; 01436 01437 ++i; 01438 } 01439 01440 i = created_objects.begin(); 01441 e = created_objects.end(); 01442 while( i != e ) 01443 { 01444 ASSERT( !(*i)->second.deleted ); 01445 01446 objects.erase(*i); 01447 01448 ++i; 01449 } 01450 01451 undos.clear(); 01452 deleted_objects.clear(); 01453 created_objects.clear(); 01454 01455 intrans = false; 01456 01457 return S_OK; 01458 } 01459 01460 STDMETHODIMP CCoreBinFile::get_StorageType(long *p) 01461 { 01462 CHECK_OUT(p); 01463 01464 *p = 0; 01465 return S_OK; 01466 } 01467