static void test_lock(void) { int i = 0; int n = 100; //int counter = 0; Lock* lock = lock_create(); for(i = 0; i < n; i++) { assert(lock_read(lock) == RET_OK); //assert(lock_get_rcounter(lock, &counter) == RET_OK); //assert(counter == 1); assert(data == 0); assert(lock_unread(lock) == RET_OK); //assert(lock_get_rcounter(lock, &counter) == RET_OK); //assert(counter == 0); assert(lock_write(lock) == RET_OK); data = 1; assert(lock_unwrite(lock) == RET_OK); assert(lock_read(lock) == RET_OK); assert(data == 1); assert(lock_unread(lock) == RET_OK); assert(lock_write(lock) == RET_OK); data = 0; assert(lock_unwrite(lock) == RET_OK); } lock_destroy(lock); return; }
const ControlFlowNode * MatchTableAbstract::apply_action(Packet *pkt) { entry_handle_t handle; bool hit; ReadLock lock = lock_read(); const ActionEntry &action_entry = lookup(*pkt, &hit, &handle); // we're holding the lock for this... if(hit) { ELOGGER->table_hit(*pkt, *this, handle); BMLOG_DEBUG_PKT(*pkt, "Table '{}': hit with handle {}", get_name(), handle); } else { ELOGGER->table_miss(*pkt, *this); BMLOG_DEBUG_PKT(*pkt, "Table '{}': miss", get_name()); } BMLOG_DEBUG_PKT(*pkt, "Action entry is {}", action_entry); action_entry.action_fn(pkt); const ControlFlowNode *next_node = action_entry.next_node; return next_node; }
STDMETHODIMP LightOPCServer::GetGroupByName(LPCWSTR szGroupName, REFIID riid, LPUNKNOWN *ppUnk) { HRESULT hr = S_OK; LightOPCGroup *grp; LO_CHECK_STATEz1("GetGroupByName", ppUnk); UL_TRACE((LOG_SR("GetGroupByName(%ls)"), loWnul(szGroupName))); if (!ppUnk) hr = E_INVALIDARG; else { if (!szGroupName) hr = E_INVALIDARG; else { lock_read(); hr = loOPC_E_NOTFOUND; if (grp = by_name(szGroupName)) hr = grp->QueryInterface(riid, (LPVOID*)ppUnk); unlock(); } } if (S_OK != hr) UL_INFO((LOG_SR("GetGroupByName(%ls) =%s"), loWnul(szGroupName), loStrError(hr))); else UL_NOTICE((LOG_SR("GetGroupByName(%ls) =%u /%p"), szGroupName, ((LightOPCGroup*)grp)->ServerHandle, *ppUnk)); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::GetState (DWORD *pUpdateRate, BOOL *pActive, LPWSTR *ppName, LONG *pTimeBias, FLOAT *pPercentDeadband, DWORD *pLCID, OPCHANDLE * phClientGroup, OPCHANDLE * phServerGroup) { HRESULT hr = S_OK; LO_CHECK_STATEz1("GetState", ppName); if (!ppName) { hr = E_INVALIDARG; goto Return; } UL_TRACE((LOG_GRH("LightOPCGroup::GetState()"))); lock_read(); if (phClientGroup) *phClientGroup = ClientHandle; if (phServerGroup) *phServerGroup = ServerHandle; if (pUpdateRate) *pUpdateRate = UpdateRate; if (pActive) *pActive = Active; if (pPercentDeadband) *pPercentDeadband = Deadband; if (pLCID) *pLCID = grLCID; if (pTimeBias) *pTimeBias = TimeBias; if (ppName && !(*ppName = loComWstrdup(name))) hr = E_OUTOFMEMORY; unlock(); Return: if (S_OK != hr) UL_INFO((LOG_GRH("GetGroupState() =%s"), loStrError(hr))); else UL_NOTICE((LOG_GRH("GetGroupState(%ls) = Ok"), loWnul(ppName? *ppName: 0))); LO_FINISH(); return hr; }
void MatchTable::dump(std::ostream &stream) const { ReadLock lock = lock_read(); stream << name << ":\n"; match_unit->dump(stream); stream << "default: " << default_entry << "\n"; }
static void test_invalid_params(void) { printf("==========Warning is normal begin==========\n"); assert(lock_read(NULL) == RET_INVALID_PARAMS); assert(lock_unread(NULL) == RET_INVALID_PARAMS); assert(lock_write(NULL) == RET_INVALID_PARAMS); assert(lock_unwrite(NULL) == RET_INVALID_PARAMS); printf("==========Warning is normal end============\n"); return; }
void MatchTableIndirectWS::dump(std::ostream &stream) const { ReadLock lock = lock_read(); MatchTableIndirect::dump_(stream); stream << "groups:\n"; for(grp_hdl_t grp : grp_handles) { stream << grp << ": "; group_entries[grp].dump(stream); stream << "\n"; } }
MatchErrorCode MatchTableIndirectWS::get_num_members_in_group(grp_hdl_t grp, size_t *nb) const { ReadLock lock = lock_read(); if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; const GroupInfo &group_info = group_entries[grp]; *nb = group_info.size(); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableAbstract::query_counters(entry_handle_t handle, counter_value_t *bytes, counter_value_t *packets) const { ReadLock lock = lock_read(); if(!with_counters) return MatchErrorCode::COUNTERS_DISABLED; if(!is_valid_handle(handle)) return MatchErrorCode::INVALID_HANDLE; const MatchUnit::EntryMeta &meta = match_unit_->get_entry_meta(handle); // should I hide counter implementation more? meta.counter.query_counter(bytes, packets); return MatchErrorCode::SUCCESS; }
void async_read(AsyncReadStream & stream, std::size_t read_size, ReadHandler handler) { if(!lock_read(stream, handler)) return; if(read_size < m_buffer.size()) { stream.get_io_service().post(std::bind(&read_stream_buffer<StreamBufferClass, PodType>::template read_complete<ReadHandler>, this, read_size, read_size, std::error_code(), 0, handler)); return; } asio::async_read(stream, m_buffer, asio::transfer_at_least( read_size - m_buffer.size()), std::bind(&read_stream_buffer::template read_complete<ReadHandler>, this, m_buffer.size(), read_size, std::placeholders::_1, std::placeholders::_2, handler)); }
void MatchTableIndirect::dump(std::ostream &stream) const { ReadLock lock = lock_read(); dump_(stream); }
void MatchTableAbstract::sweep_entries(std::vector<entry_handle_t> &entries) const { ReadLock lock = lock_read(); // TODO: how to avoid this? match_unit_->sweep_entries(entries); }
STDMETHODIMP LightOPCGroup::Write(DWORD dwCount, OPCHANDLE *phServer, VARIANT *pItemValues, DWORD dwTransactionID, DWORD *pdwCancelID, HRESULT **ppErrors) { HRESULT hr = S_FALSE; HRESULT *errs = 0; loRequest *rq = 0; unsigned items_ok = 0; LO_CHECK_STATEz1("AsyncIO2:Write", ppErrors); UL_TRACE((LOG_GRH("AsyncIO2:Write(%u)..."), dwCount)); if (!phServer || !dwCount || !pdwCancelID || !pItemValues) { hr = E_INVALIDARG; goto Return; } *pdwCancelID = 0; if (owner->q_req.metric_overload) { hr = CONNECT_E_ADVISELIMIT; goto Return; } errs = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); rq = lo_req_alloc(dwCount, loUPL_AsyncWrite); if (!rq || !errs) { hr = E_OUTOFMEMORY; goto Return; } loTagPair_init(rq->upl.tagpair, dwCount); rq->operation = loRQ_OP_WRITE | loRQ_CONN_DATABACK | loRQ_DEVICE; rq->group_key = ServerHandle; rq->serv_key = owner->serv_key; rq->upl.transaction_id = dwTransactionID; rq->upl.rctx = owner->ctxt; lock_read(); rq->upl.rctx.cta.vc_lcid = grLCID; if (owner->access_mode & loAM_RDONLY_OP) { unsigned ii; for(ii = 0; ii < dwCount; ii++) errs[ii] = OPC_E_BADRIGHTS; goto Unlock; } if (0 == (advise_present & loRQ_CONN_DATABACK)/*conn_databack*/) hr = CONNECT_E_NOCONNECTION; else { unsigned ii; loTagPair *tpl = rq->upl.tagpair; // HRESULT *errors = rq->upl.errors; LightOPCItem *it; loTagEntry *tags = owner->se->tags; for(ii = 0; ii < dwCount; ii++, pItemValues++) if (!(it = by_index(phServer[ii]))) errs[ii] = OPC_E_INVALIDHANDLE; else { loTagEntry *te = &tags[it->tid]; #if 0 != LO_CHECK_RIGHTS if (!(OPC_WRITEABLE & te->attr.taRights)) errs[ii] = OPC_E_BADRIGHTS; else #endif if (VT_EMPTY == V_VT(pItemValues) || /*) *errors = OPC_E_BADTYPE; else if (*/S_OK == (errs[ii] = VariantCopy(&rq->upl.variant[ii], pItemValues))) { tpl->tpTi = te->attr.taTi; tpl->tpRt = te->attr.taRt; tpl->tpAP = it->AcPath; tpl++; rq->upl.opchandle[items_ok++] = it->hClient; errs[ii] = S_OK; } }/* end of for */ } Unlock: unlock(); if (items_ok) { rq->upl.used = items_ok; rq->upl.master_err = hr = items_ok == dwCount? S_OK: S_FALSE; if (0 == (*pdwCancelID = lo_req_put_async(&owner->q_req, rq))) hr = CONNECT_E_ADVISELIMIT; rq = 0; } Return: if (rq) lo_req_free(rq); if (SUCCEEDED(hr)) { if (ppErrors) *ppErrors = errs, errs = 0; UL_NOTICE((LOG_GRH("AsyncIO2:Write(%u) = %u -> %x Ok"), dwCount, items_ok, *pdwCancelID)); } else { UL_INFO((LOG_GRH("AsyncIO2:Write(%u) = %u /%s"), dwCount, items_ok, loStrError(hr))); } if (errs) loComFree(errs); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::Write(DWORD dwCount, OPCHANDLE *phServer, VARIANT *pItemValues, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; unsigned items_ok = 0; loRequest *rq; LO_CHECK_STATEz1("SyncIO:Write", ppErrors); UL_TRACE((LOG_GRH("SyncIO:Write(%u)..."), dwCount)); if (!phServer || !pItemValues || !dwCount) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); rq = lo_req_alloc(dwCount, loUPL_variant /*| loUPL_errors*/ | loUPL_tagpair); if (!rq || !err) { hr = E_OUTOFMEMORY; goto Return; } rq->operation = loRQ_OP_WRITE | loRQ_SYNC | loRQ_DEVICE; rq->group_key = ServerHandle; rq->serv_key = owner->serv_key; rq->com_allocated = rq->upl.errors = err; loTagPair_init(rq->upl.tagpair, dwCount); rq->upl.rctx = owner->ctxt; lock_read(); rq->upl.rctx.cta.vc_lcid = grLCID; if (owner->access_mode & loAM_RDONLY_OP) { unsigned ii; for(ii = 0; ii < dwCount; ii++) err[ii] = OPC_E_BADRIGHTS; } else { loService *se = owner->se; loTagEntry *tags = se->tags; loTagPair *tpl = rq->upl.tagpair; // HRESULT *errors = rq->upl.errors; VARIANT *variant = rq->upl.variant; LightOPCItem *it; unsigned ii; for(ii = 0; ii < dwCount; ii++, tpl++, pItemValues++) if (!(it = by_index(phServer[ii]))) err[ii] = OPC_E_INVALIDHANDLE; else { loTagEntry *te = &tags[it->tid]; #if 0 != LO_CHECK_RIGHTS if (!(OPC_WRITEABLE & te->attr.taRights)) err[ii] = OPC_E_BADRIGHTS; else #endif if (VT_EMPTY == V_VT(pItemValues) ||/*) *errors = OPC_E_BADTYPE; else if (*/ S_OK == (err[ii] = VariantCopy(&variant[ii], pItemValues))) { err[ii] = S_OK; tpl->tpTi = te->attr.taTi; tpl->tpRt = te->attr.taRt; tpl->tpAP = it->AcPath; items_ok++; } else UL_TRACE((LOG_GRH("SyncIO:Write(%u) [ %x / %x ] %s"), ii, V_VT(pItemValues), taVTYPE(&te->attr), loStrError(err[ii]))); } rq->upl.used = dwCount; } unlock(); // rq->upl.used = dwCount; if (0 == items_ok) { // memcpy(err, rq->upl.errors, dwCount * sizeof(*err)); rq->com_allocated = 0; lo_req_free(rq); hr = S_FALSE; } else { rq->upl.master_err = items_ok == dwCount? S_OK: S_FALSE; err = 0; if (rq = lo_req_put_sync(&owner->q_req, &owner->q_ret, rq)) { hr = rq->upl.master_err; // memcpy(err, rq->upl.errors, dwCount * sizeof(*err)); err = rq->upl.errors; rq->com_allocated = 0; lo_req_free(rq); } else hr = LO_E_SHUTDOWN; } Return: if (SUCCEEDED(hr)) { if (ppErrors) *ppErrors = err, err = 0; // if (items_ok != dwCount && hr == S_OK) hr = S_FALSE; UL_NOTICE((LOG_GRH("SyncIO:Write(%u) = %u Ok"), dwCount, items_ok)); } else { UL_INFO((LOG_GRH("SyncIO:Write(%u) = %u /%s"), dwCount, items_ok, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
int LightOPCServer::send_callback(LightOPCGroup *grp, unsigned group_key, loUpdList *upl, int advmask) { int tr = 0; IOPCDataCallback *c_databack = 0; IAdviseSink *c_datatime = 0, *c_dataonly = 0, *c_writecomp = 0; unsigned cform_dtime, cform_donly, cform_wrcompl; OPCHANDLE client_handle; // UL_DEBUG((LOGID, "send_notify(){...")); if (!upl->used) { if (!upl->trqid) return 0; if (S_OK == upl->master_err) upl->master_err = S_FALSE; } if (FAILED(upl->master_err)) upl->master_qual = S_FALSE; if (!grp) { lock_read(); if (0 == (grp = by_handle_g(group_key))) { unlock(); UL_INFO((LOGID, "send_callback(%x) FAILED: No such group")); return 0; } } #if LO_USE_BOTHMODEL && 0 else group_key = grp->ServerHandle; #endif client_handle = grp->ClientHandle; /* There is only client_sched() thread allowed to change connection info under read_lock ! */ if ((advmask & loRQ_CONN_DATABACK) && grp->conn_databack) loGET_IFACE(c_databack, grp->conn_databack, IOPCDataCallback, grp->initphase); if (advmask & (loRQ_CONN_DATA_1 | loRQ_CONN_WRITECOMPL)) { if ((advmask & loRQ_CONN_DATATIME) && grp->conn_datatime) { cform_dtime = se->cform_datatime; loGET_IFACE(c_datatime, grp->conn_datatime, IAdviseSink, grp->initphase); /* ?? advise_present &= ~loRQ_CONN_DATATIME */ } if ((advmask & loRQ_CONN_DATAONLY) && grp->conn_dataonly) { cform_donly = se->cform_dataonly; loGET_IFACE(c_dataonly, grp->conn_dataonly, IAdviseSink, grp->initphase); /* ?? advise_present &= ~loRQ_CONN_DATAONLY */ } if ((advmask & loRQ_CONN_WRITECOMPL) && grp->conn_writecompl) { cform_wrcompl = se->cform_writecompl; loGET_IFACE(c_writecomp, grp->conn_writecompl, IAdviseSink, grp->initphase); /* ?? advise_present &= ~loRQ_CONN_WRITECOMPL */ } } unlock(); // UL_DEBUG((LOGID, "send_notify() #3")); if (c_databack) { HRESULT hr = E_INVALIDARG; switch(advmask & loRQ_OPER_MASK) { case loRQ_OP_REFRESH: hr = c_databack->OnDataChange(upl->trqid, client_handle, upl->master_err, upl->master_qual, upl->used, upl->opchandle, upl->variant, upl->quality, upl->timestamp, upl->errors); break; case loRQ_OP_READ: hr = c_databack->OnReadComplete(upl->transaction_id, client_handle, upl->master_err, upl->master_qual, upl->used, upl->opchandle, upl->variant, upl->quality, upl->timestamp, upl->errors); break; case loRQ_OP_WRITE: hr = c_databack->OnWriteComplete(upl->transaction_id, client_handle, upl->master_err, upl->used, upl->opchandle, upl->errors); break; case loRQ_OP_CANCEL: hr = c_databack->OnCancelComplete(upl->transaction_id, client_handle); break; } c_databack->Release(); if (S_OK == hr) { tr++; UL_DEBUG((LOGID, "OnDataChange2(0x%X) Ok", advmask)); } else { UL_WARNING((LOGID, "%!l OnDataChange2(0x%X) FAILED", hr, advmask)); } // UL_WARNING((LOGID, "OnDataChange() 2 Ok")); } if (advmask & loRQ_CONN_DATA_1) { HGLOBAL gmem = 0; unsigned datasize = 0; if (c_datatime) { // UL_DEBUG((LOGID, "OnDataChange1() with time")); if (0 <= lo_OnDataChange1(upl, client_handle, cform_dtime, 1, c_datatime, &gmem, &datasize)) tr++; c_datatime->Release(); } if (c_dataonly) { // UL_DEBUG((LOGID, "OnDataChange1() without time")); if (0 <= lo_OnDataChange1(upl, client_handle, cform_donly, 0, c_dataonly, &gmem, &datasize)) tr++; c_dataonly->Release(); } if (gmem && (// && (!GlobalSize(gmem) ||*/ GlobalFree(gmem))) //(GlobalFlags(gmem) & (GMEM_INVALID_HANDLE | GMEM_DISCARDED)) || GlobalFree(gmem) ) ) { UL_WARNING((LOGID, "%!L GlobalFree(%X) FAILED flags=0x%X", gmem, GlobalFlags(gmem))); } } else if (c_writecomp) { // UL_DEBUG((LOGID, "OnWriteComplete1()")); if (0 <= lo_OnWriteComplete1(upl, client_handle, cform_wrcompl, c_writecomp, 0)) tr++; c_writecomp->Release(); } // UL_DEBUG((LOGID, "send_datachange() finished}")); return tr; }
void async_read_until(AsyncReadStream & stream, const std::string & delim, ReadHandler handler) { if(!lock_read(stream, handler)) return; asio::async_read_until(stream, m_buffer, delim, std::bind( &read_stream_buffer::template read_complete<ReadHandler>, this, 0, -1, std::placeholders::_1, std::placeholders::_2, handler)); }
HRESULT LightOPCGroup::internalValidateItems(DWORD dwCount, OPCITEMDEF *pItemDefs, loTagId *tid, void **acpath, OPCITEMRESULT **ppResults, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; OPCITEMRESULT *ir = 0; DWORD ii; loService *se; loTagEntry *tags; int free_tid = 0, inc_ap = 0, ai_goal = loDAIG_ADDITEM, am_mask; loCallerx cctx; loAA_DECLARE(sizeof(loTagId)); if (!tid) { free_tid = 1; ai_goal = loDAIG_VALIDATE; tid = (loTagId*)loAA_ALLOC(dwCount * sizeof(loTagId)); } if (acpath) inc_ap = 1; UL_TRACE((LOG_GRH("loGroup::intValidateItems(%lu, %p %p %p)"), dwCount, pItemDefs, ppResults, ppErrors)); if (ppResults) *ppResults = 0; if (ppErrors) *ppErrors = 0; if (!dwCount || !pItemDefs || !ppResults) { hr = E_INVALIDARG; goto Return; } cctx = owner->ctxt; se = owner->se; tags = se->tags; err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); ir = (OPCITEMRESULT*)loComAlloc(dwCount * sizeof(OPCITEMRESULT)); if (!err || !ir || !tid) { hr = E_OUTOFMEMORY; goto Return; } memset(ir, 0, dwCount * sizeof(OPCITEMRESULT)); am_mask = owner->access_mode & loAM_RDONLY_ADD? (loOPC_RIGHTS & ~OPC_WRITEABLE): loOPC_RIGHTS; lw_rw_rdlock(&se->lkMgmt); for(ii = 0; ii < dwCount; ii++, acpath += inc_ap) if (tid[ii] = loFindItemID(se, &owner->ctxt.cactx, 1, pItemDefs[ii].szItemID, pItemDefs[ii].szAccessPath, pItemDefs[ii].vtRequestedDataType, ai_goal, acpath, &err[ii])) { loTagAttrib *ta = &tags[tid[ii]].attr; ir[ii].dwAccessRights = am_mask/*loOPC_RIGHTS*/ & ta->taRights; ir[ii].vtCanonicalDataType = taVTYPE(ta); } else hr = S_FALSE; lw_rw_unlock(&se->lkMgmt); lock_read(); cctx.cta.vc_lcid = grLCID; unlock(); for(ii = 0; ii < dwCount; ii++) if (S_OK == err[ii]) { loTagAttrib *ta = &tags[tid[ii]].attr; if (loTF_EMPTY & ta->taFlags) { err[ii] = OPC_E_INVALIDITEMID; tid[ii] = 0; hr = S_FALSE; goto LogErr; } else if ( /*VT_EMPTY != pItemDefs[ii].vtRequestedDataType &&*/ S_OK != (err[ii] = lo_checktype(&cctx, ta, pItemDefs[ii].vtRequestedDataType))) { /*err[ii] = OPC_E_BADTYPE */; tid[ii] = 0; hr = S_FALSE; goto LogErr; } else UL_TRACE((LOG_GR("intValidateItem(%ls)(%ls) = %u"), loWnul(pItemDefs[ii].szItemID), loWnul(pItemDefs[ii].szAccessPath), tid[ii])); } else { LogErr: UL_NOTICE((LOG_GR("intValidateItem(%ls)(%ls) = %s"), loWnul(pItemDefs[ii].szItemID), loWnul(pItemDefs[ii].szAccessPath), loStrError(err[ii]))); } Return: if (free_tid) { loAA_FREE(tid); } if (FAILED(hr)) { UL_TRACE((LOG_GRH("intValidateItems(%lu) = %s"), dwCount, loStrError(hr))); } else { *ppResults = ir, ir = 0; if (ppErrors) *ppErrors = err, err = 0; UL_TRACE((LOG_GRH("intValidateItems(%lu) = %s"), dwCount, loStrError(hr))); } if (ir) loComFree(ir); if (err) loComFree(err); return hr; }
STDMETHODIMP LightOPCGroup::CloneGroup(LPCWSTR szName, REFIID riid, LPUNKNOWN *ppUnk) { HRESULT hr = S_OK; LightOPCGroup *grp = 0; OPCHANDLE serverhandle; LO_CHECK_STATEz1("CloneGroup", ppUnk); UL_TRACE((LOG_GRH("CloneGroup(-> %ls)"), loWnul(szName))); if (!ppUnk) { hr = E_INVALIDARG; goto Exit; } if (!(grp = new LightOPCGroup) || !grp->iam_valid()) { hr = E_OUTOFMEMORY; goto Exit; } lock_read(); if (szName && owner->by_name(szName)) hr = OPC_E_DUPLICATENAME; else { unsigned ii; LightOPCItem *proto; /* do cloning of items here */ for(ii = 0; ii < itl.gl_count; ii++) if (proto = (LightOPCItem*)itl.gl_list[ii]) { LightOPCItem *newby = new LightOPCItem; if (newby) { newby->convtype = proto->convtype; newby->tid = proto->tid; newby->AcPath = proto->AcPath; newby->bActive = proto->bActive; newby->hClient = proto->hClient; newby->vtRequestedDataType = proto->vtRequestedDataType; if (S_OK != (hr = newby->set_accpath(proto->szAccessPath)) || S_OK != (hr = newby->set_itemid(proto->szItemID))) { delete newby; break; } if (!grp->add(newby)) { delete newby; hr = E_OUTOFMEMORY; break; } newby->Quality = -1; if (newby->bActive) grp->active_count++; else newby->Quality = OPC_QUALITY_OUT_OF_SERVICE; } else { hr = E_OUTOFMEMORY; break; } } } unlock(); if (S_OK == hr) hr = owner->internalAddGroup(grp, szName, 0/*bActive*/, UpdateRate, ClientHandle, &TimeBias, &Deadband, grLCID, &serverhandle, riid, ppUnk); Exit: if (S_OK == hr) { UL_NOTICE((LOG_GRH("CloneGroup(-> %ls) =%u /%p"), loWnul(szName), serverhandle, *ppUnk)); } else { UL_INFO((LOG_GRH("CloneGroup(-> %ls) =%s"), loWnul(szName), loStrError(hr))); if (grp) delete grp; } LO_FINISH(); return hr; }