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;
 }
 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;
 }