bool Registry::Key::HasValue() const
 {
   RefObjQIPtr<IFaces::INamedVariable> Var = Keys.First();
   if (!Var.Get())
     throw RegistryException("Can't get variable");
   RefObjPtr<IFaces::IVariant> Value;
   if (Var->Get(Value.GetPPtr()) != IFaces::retOk)
     throw RegistryException("Can't get value");
   return Value->GetType() != IFaces::IVariant::vtIBase;
 }
 RetCode BOSS_CALL ServiceRegistry::AddService(IServiceInfo *service)
 {
   try
   {
     std::lock_guard<std::recursive_mutex> Lock(Mtx);
     if (!service)
       return Status::InvalidArgument;
     IServiceInfoPtr Info(service);
     ServiceId SrvId = 0;
     RetCode Res = Info->GetServiceId(&SrvId);
     if (Res != Status::Ok)
       return Res;
     RefObjPtr<IEnum> ClassIdsEnum;
     Res = Info->GetClassIds(ClassIdsEnum.GetPPtr());
     if (Res != Status::Ok)
       return Res;
     typedef std::vector<ClassId> ClassIdPool;
     ClassIdPool ClassIds;
     if (ClassIdsEnum->Reset() != Status::Ok)
       return Status::Fail;
     for (RefObjPtr<IBase> i ; ClassIdsEnum->Next(i.GetPPtr()) == Status::Ok ; i.Release())
     {
       RefObjQIPtr<IEntityId> Id(i);
       if (!Id.Get())
         return Status::Fail;
       ClassId ClsId = 0;
       Res = Id->GetId(&ClsId);
       if (Res != Status::Ok)
         return Res;
       if (Services.find(ClsId) != std::end(Services))
         return Status::Fail;
       ClassIds.push_back(ClsId);
     }
     auto Pred = [&] (decltype(*ServicePool::const_iterator()) &info)
       {
         ServiceId Id = 0;
         return info.second->GetServiceId(&Id) == Status::Ok && Id == SrvId;
       };
     auto Iter = std::find_if(std::begin(Services), std::end(Services), Pred);
     if (Iter != std::end(Services))
       return Status::AlreadyExists;
     for (auto const &i : ClassIds)
       Services[i] = Info;
   }
   catch (...)
   {
     return Status::Fail;
   }
   return Status::Ok;
 }
 bool Registry::Key::HasChildKeys() const
 {
   RefObjQIPtr<IFaces::INamedVariable> Var = Keys.First();
   if (!Var.Get())
     throw RegistryException("Can't get variable");
   RefObjPtr<IFaces::IVariant> Value;
   if (Var->Get(Value.GetPPtr()) != IFaces::retOk)
     throw RegistryException("Can't get value");
   if (Value->GetType() != IFaces::IVariant::vtIBase)
     return false;
   RefObjPtr<IFaces::IBase> ChildItem;
   if (Value->GetValue(reinterpret_cast<void**>(ChildItem.GetPPtr())) != IFaces::retOk ||
     !RefObjQIPtr<IFaces::IEnum>(ChildItem).Get())
   {
     throw RegistryException("Unknown child item");
   }
   return true;
 }
 const Registry::Key::KeysPoolPtr Registry::Key::GetChildKeys() const
 {
   KeysPoolPtr RetPool(new KeysPool);
   for (RefObjQIPtr<IFaces::INamedVariable> Var = Keys.First() ;
     Var.Get() ; Var = Keys.Next())
   {
     RefObjPtr<IFaces::IVariant> Value;
     if (Var->Get(Value.GetPPtr()) != IFaces::retOk)
       throw RegistryException("Can't get value");
     if (Value->GetType() != IFaces::IVariant::vtIBase)
       throw RegistryException("Unknown child item");
     RefObjPtr<IFaces::IBase> ChildItem;
     if (Value->GetValue(reinterpret_cast<void**>(ChildItem.GetPPtr())) != IFaces::retOk)
       throw RegistryException("Can't get child enum");
     RefObjQIPtr<IFaces::IEnum> Enum(ChildItem);
     if (!Enum.Get())
       throw RegistryException("Unknown child item");
     RetPool->push_back(KeyPtr(new Key(IFacesImpl::IEnumHelper(Enum), Var->GetName())));
   }
   return RetPool;
 }
 RetCode BOSS_CALL ServiceRegistry::Save(IOStream *stream)
 {
   if (!stream)
     return Status::InvalidArgument;
   try
   {
     std::list<IServiceInfoPtr> ServiceInfoSet;
     {
       std::lock_guard<std::recursive_mutex> Lock(Mtx);
       for (auto const &service : Services)
       {
         if (std::find_if(std::begin(ServiceInfoSet), std::end(ServiceInfoSet),
               [&] (IServiceInfoPtr const &info) { return info.Get() == service.second.Get(); } )
             != std::end(ServiceInfoSet))
         {
           continue;
         }
         ServiceInfoSet.push_back(service.second);
       }
     }
     auto ServiceEnum = Base<Enum>::Create();
     for (auto const &service : ServiceInfoSet)
     {
       RetCode Code = Status::Ok;
       auto ServiceItem = PropertyBagType::Create(ServiceTag);
       ServiceEnum->AddItem(ServiceItem);
       {
         ServiceId SrvId = 0;
         Code = service->GetServiceId(&SrvId);
         if (Code != Status::Ok)
           return Code;
         if ((Code = ServiceItem->SetProperty(ServiceIdTag, Base<EntityId>::Create(SrvId).Get())) != Status::Ok)
           return Code;
       }
       {
         RefObjPtr<IEnum> ClassIds;
         if ((service->GetClassIds(ClassIds.GetPPtr())) != Status::Ok)
           return Code;
         if ((Code = ServiceItem->SetProperty(ClassIdsTag, ClassIds.Get())) != Status::Ok)
           return Code;
       }
       {
         RefObjQIPtr<IRemoteServiceInfo> RemoteService(service);
         if (RemoteService.Get())
         {
           RefObjPtr<IPropertyBag> RemoteServiceProps;
           if ((Code = RemoteService->GetProperties(RemoteServiceProps.GetPPtr())) != Status::Ok ||
               (Code = ServiceItem->SetProperty(RemotePropertiesTag, RemoteServiceProps.Get())) != Status::Ok)
             return Code;
           {
             return Code;
           }
           continue;
         }
       }
       {
         RefObjQIPtr<ILocalServiceInfo> LocalService(service);
         if (LocalService.Get())
         {
           RefObjPtr<IString> ModulePath;
           if ((Code = LocalService->GetModulePath(ModulePath.GetPPtr())) != Status::Ok ||
               (Code = ServiceItem->SetProperty(ModulePathTag, ModulePath.Get())) != Status::Ok)
           {
             return Code;
           }
           continue;
         }
       }
     }
     auto Registry = PropertyBagType::Create(RegistryTag);
     RetCode Code = Registry->SetProperty(ServicesTag, ServiceEnum.Get());
     if (Code != Status::Ok)
       return Code;
     RefObjQIPtr<ISerializable> Serializable(Registry);
     if (!Serializable.Get())
       return Status::Fail;
     if ((Code = Serializable->Save(stream)) != Status::Ok)
       return Code;
   }
   catch (std::exception const &)
   {
     return Status::Fail;
   }
   return Status::Ok;
 }
 RetCode BOSS_CALL ServiceRegistry::Load(IIStream *stream)
 {
   if (!stream)
     return Status::InvalidArgument;
   std::lock_guard<std::recursive_mutex> Lock(Mtx);
   try
   {
     auto Registry = PropertyBagType::Create(RegistryTag);
     RetCode Code = Registry->Load(stream);
     if (Code != Status::Ok)
       return Code;
     RefObjPtr<IBase> ServiceEnumProp;
     if ((Code = Registry->GetProperty(ServicesTag, ServiceEnumProp.GetPPtr())) != Status::Ok)
       return Code;
     RefObjQIPtr<IEnum> ServiceEnum(ServiceEnumProp);
     if (!ServiceEnum.Get())
       return Status::Fail;
     ServicePool NewServices;
     for (RefObjPtr<IBase> i ; ServiceEnum->Next(i.GetPPtr()) == Status::Ok ; i.Release())
     {
       RefObjQIPtr<IPropertyBag> ServiceItem(i);
       if (!ServiceItem.Get())
         return Status::Fail;
       RefObjPtr<IBase> EntId;
       if ((Code = ServiceItem->GetProperty(ServiceIdTag, EntId.GetPPtr())) != Status::Ok)
         return Code;
       RefObjQIPtr<IEntityId> EntSrvId(EntId);
       if (!EntSrvId.Get())
         return Status::Fail;
       ServiceId SrvId = 0;
       if ((Code = EntSrvId->GetId(&SrvId)) != Status::Ok)
         return Code;
       RefObjPtr<IBase> ClassIdsEnumProp;
       if ((Code = ServiceItem->GetProperty(ClassIdsTag, ClassIdsEnumProp.GetPPtr())) != Status::Ok)
         return Code;
       RefObjQIPtr<IEnum> ClassIdsEnum(ClassIdsEnumProp);
       if (!ClassIdsEnum.Get())
         return Status::Fail;
       RefObjPtr<IBase> ModulePathProp;
       RefObjPtr<IServiceInfo> ServiceInfo;
       if (ServiceItem->GetProperty(ModulePathTag, ModulePathProp.GetPPtr()) == Status::Ok)
       {
         RefObjQIPtr<IString> ModulePath(ModulePathProp);
         if (!ModulePath.Get())
           return Status::Fail;
         auto LocalSrvInfo = Base<LocalServiceInfo>::Create();
         LocalSrvInfo->SetServiceId(SrvId);
         LocalSrvInfo->AddCoClassIds(ClassIdsEnum);
         LocalSrvInfo->SetModulePath(ModulePath);
         ServiceInfo = LocalSrvInfo;
       }
       else
       {
         RefObjPtr<IBase> RemotePropertiesProp;
         if (ServiceItem->GetProperty(RemotePropertiesTag, RemotePropertiesProp.GetPPtr()) == Status::Ok)
         {
           RefObjQIPtr<IPropertyBag> RemoteProperties(RemotePropertiesProp);
           if (!RemoteProperties.Get())
             return Status::Fail;
           auto RemoteSrvInfo = Base<RemoteServiceInfo>::Create();
           RemoteSrvInfo->SetServiceId(SrvId);
           RemoteSrvInfo->AddCoClassIds(ClassIdsEnum);
           RemoteSrvInfo->SetProps(RemoteProperties);
           ServiceInfo = RemoteSrvInfo;
         }
         else
           return Status::Fail;
       }
       if ((Code = ClassIdsEnum->Reset()) != Status::Ok)
         return Code;
       for (RefObjPtr<IBase> j ; ClassIdsEnum->Next(j.GetPPtr()) == Status::Ok ; j.Release())
       {
         RefObjQIPtr<IEntityId> ClsId(j);
         if (!ClsId.Get())
           return Status::Fail;
         ClassId Id = 0;
         if ((Code = ClsId->GetId(&Id)) != Status::Ok)
           return Code;
         NewServices[Id] = ServiceInfo;
       }
     }
     std::swap(Services, NewServices);
     return Status::Ok;
   }
   catch (...)
   {
     return Status::Fail;
   }
   return Status::Ok;
 }