STDMETHODIMP LightOPCGroup::RemoveItems(DWORD dwCount, OPCHANDLE *phServer, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; LO_CHECK_STATEz1("RemoveItems", ppErrors); if (!dwCount || !phServer) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount;) { unsigned tt; loTagId ti[32]; for(tt = 0; tt < SIZEOF_ARRAY(ti) && ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { if (item->bActive) { active_count--; ti[tt++] = item->tid; } del((unsigned)phServer[ii]); err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } if (tt && Active) loChangeActivity(&owner->ctxt.cactx, 0, tt, ti); } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("RemoveItems(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("RemoveItems(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCServer::GetItemID( /* [in] */ LPWSTR szItemDataID, /* [string][out] */ LPWSTR *szItemID) { HRESULT hr = S_OK; LO_CHECK_STATEz1("GetItemID", szItemID); if (!szItemID) hr = E_INVALIDARG; else { loWchar *itemid = 0; int ii = -1; lock_browse(); // UL_DEBUG((LOG_SR("GetItemID->(%ls)(%ls)"), loWnul(browsepos.sb_str),loWnul(szItemDataID))); if (0 <= (ii = cat_browsepos(szItemDataID))) { itemid = loComWstrdup(browsepos.sb_str/*? browsepos.sb_str: L""*/); browsepos.sb_str[ii] = 0; } unlock_browse(); if (!itemid) { hr = E_OUTOFMEMORY; UL_INFO((LOG_SR("GetItemID(%ls) = %s"), loWnul(szItemDataID), loStrError(hr))); } else { /* loFindItemID() will go faster */ if (loFindItemID(se, &ctxt.cactx, 0, itemid, 0, VT_EMPTY, loDAIG_BROWSE, 0, &hr) || lo_browse_branch(se, itemid) ) *szItemID = itemid, hr = S_OK; else { //if (!FAILED(hr)) loOPC_E_NOTFOUND; hr = E_INVALIDARG; UL_INFO((LOG_SR("GetItemID(%ls)(%ls) = %s"), loWnul(szItemDataID), loWnul(itemid), loStrError(hr))); loComFree(itemid); } } } if (S_OK == hr) { UL_NOTICE((LOG_SR("GetItemID(%ls) = %ls"), loWnul(szItemDataID), *szItemID)); } LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::SetClientHandles(DWORD dwCount, OPCHANDLE *phServer, OPCHANDLE *phClient, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; LO_CHECK_STATEz1("SetClientHandles", ppErrors); if (!dwCount || !phServer || !phClient) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { item->hClient = phClient[ii]; err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetClientHandles(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetClientHandles(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); 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; }
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 loConnPnt1::EnumConnectionPoints(IEnumConnectionPoints **ppEnum) { HRESULT hr = S_OK; if (!ppEnum) hr = E_POINTER; else { *ppEnum = 0; if (S_OK == (hr = icp_AddRef())) { loEnumConnPnt1 *en = new loEnumConnPnt1(this); if (en) { if (S_OK == (hr = en->initiate(icp_ObjTracker()))) { *ppEnum = en; #if LO_USE_FREEMARSHALL if (!freemarsh) en->DisableFreemarsh(); #else en->DisableFreemarsh(); #endif } else delete en; } else hr = E_OUTOFMEMORY; icp_Release(); } } UL_NOTICE((LOGID, "EnumConnPoints() %s", loStrError(hr))); return hr; }
STDMETHODIMP LightOPCGroup::ValidateItems(DWORD dwCount, OPCITEMDEF *pItemArray, BOOL bBlobUpdate, OPCITEMRESULT **ppValidationResults, HRESULT **ppErrors) { HRESULT hr; LO_CHECK_STATEz2("ValidateItems", ppValidationResults, ppErrors); hr = internalValidateItems(dwCount, pItemArray, 0, 0, ppValidationResults, ppErrors); if (FAILED(hr)) { UL_INFO((LOG_GRH("ValidateItems(%lu) FAILED/ %s"), dwCount, loStrError(hr))); } else { UL_NOTICE((LOG_GRH("ValidateItems(%lu) = %s"), dwCount, loStrError(hr))); } LO_FINISH(); return hr; }
STDMETHODIMP loConnPnt1::GetConnectionPointContainer(IConnectionPointContainer **ppCPC) { HRESULT hr = S_OK; if (!ppCPC) hr = E_POINTER; else if (S_OK == (hr = icp_AddRef())) { // IConnectionPointContainer::AddRef(); (*ppCPC = this)->AddRef(); icp_Release(); } UL_NOTICE((LOGID, "GetConnPointContainer() %s", loStrError(hr))); return hr; }
STDMETHODIMP loConnPnt1::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) { HRESULT hr = S_OK; IID myiid; if (!ppCP) hr = E_POINTER; else if (S_OK == (hr = GetConnectionInterface(&myiid))) if (!IsEqualIID(riid, myiid)) hr = CONNECT_E_NOCONNECTION; else if (S_OK == (hr = icp_AddRef())) { // IConnectionPoint::AddRef(); (*ppCP = this)->AddRef(); icp_Release(); } UL_NOTICE((LOGID, "FindConnPoints() %s", loStrError(hr))); return hr; }
STDMETHODIMP LightOPCGroup::SetState(DWORD *pRequestedUpdateRate, DWORD *pRevisedUpdateRate, BOOL *pActive, LONG *pTimeBias, FLOAT *pPercentDeadband, DWORD *pLCID, OPCHANDLE *phClientGroup) { HRESULT hr = S_OK; LO_CHECK_STATEz0("SetState"); UL_TRACE((LOG_GRH("LightOPCGroup::SetState()"))); if (pLCID && owner->se->driver.ldCheckLocale && owner->se->driver.ldCheckLocale(&owner->ctxt.cactx, *pLCID)) pLCID = 0; /* ignore on errors */ lock_write(); if (pRequestedUpdateRate) { // if (!pRevisedUpdateRate) hr = E_INVALIDARG; DWORD revised_rate = loReviseUpdateRate(owner->se, *pRequestedUpdateRate); if (UpdateRate > revised_rate && (!pActive || *pActive) /* && Active && 0 != (advise_present & advise_enabled)*/) UpdateRate = revised_rate, actuate_async(0); else UpdateRate = revised_rate; if (UpdateRate != *pRequestedUpdateRate) hr = OPC_S_UNSUPPORTEDRATE; } if (pRevisedUpdateRate) *pRevisedUpdateRate = UpdateRate; if (pActive) set_active(*pActive); if (pTimeBias) TimeBias = *pTimeBias; if (pPercentDeadband) if (lo_IsNANf(*pPercentDeadband) || *pPercentDeadband < 0. || *pPercentDeadband > 100.) hr = E_INVALIDARG; else Deadband = *pPercentDeadband; if (pLCID) grLCID = *pLCID; if (phClientGroup) ClientHandle = *phClientGroup; unlock(); if (!FAILED(hr)) UL_NOTICE((LOG_GR("SetGroupState(%u) =(%umS (%umS) %g%%)Ok"), ServerHandle, (unsigned)UpdateRate, (unsigned)(pRequestedUpdateRate? *pRequestedUpdateRate: 0), Deadband)); else UL_INFO((LOG_GR("SetGroupState(%u) =%s"), ServerHandle, loStrError(hr))); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCServer::RemoveGroup(OPCHANDLE groupHandleID, BOOL bForce) { HRESULT hr = loOPC_E_INVALIDHANDLE; LO_CHECK_STATEz0("RemoveGroup"); UL_TRACE((LOG_SR("RemoveGroup(%u %s)"), groupHandleID, bForce? "FORCE": "")); if (groupHandleID) { #if LO_USE_BOTHMODEL if (ldFlags & loDf_BOTHMODEL) { loRequest *rq = lo_req_alloc(0, 0); UL_DEBUG((LOG_SR("RemoveGroup() going to async"))); if (!rq) hr = E_OUTOFMEMORY; else { rq->operation = loRQ_SYNC | loRQ_OP_REMOVE_GROUP | (bForce? loRQ_OF_REMOVE_FORCE: 0); rq->group_key = groupHandleID; rq->serv_key = serv_key; if (rq = lo_req_put_sync(&q_req, &q_ret, rq)) { hr = rq->upl.master_err; lo_req_free(rq); } else hr = E_FAIL; } } else #endif hr = internalRemoveGroup(groupHandleID, bForce); } if (S_OK != hr) UL_INFO((LOG_SR("RemoveGroup(%u %s) =%s"), groupHandleID, bForce? "FORCE": "", loStrError(hr))); else UL_NOTICE((LOG_SR("RemoveGroup(%u %s) =Ok"), groupHandleID, bForce? "FORCE": "")); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::SetName(LPCWSTR szName) { HRESULT hr = S_OK; LO_CHECK_STATEz0("SetName"); UL_TRACE((LOG_GRH("LightOPCGroup::SetName()"))); if (!szName) hr = E_INVALIDARG; else { LightOPCGroup *grp; lock_write(); grp = owner->by_name(szName); if (!grp) hr = set_name(szName); else if (grp != this) hr = OPC_E_DUPLICATENAME; unlock(); } if (S_OK != hr) UL_INFO((LOG_GRH("SetGroupName(%ls) =%s"), loWnul(szName), loStrError(hr))); else UL_NOTICE((LOG_GRH("SetGroupName(%ls)"), szName)); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCServer::BrowseAccessPaths( /* [string][in] */ LPCWSTR szItemID, /* [out] */ LPENUMSTRING *ppIEnumString) { HRESULT hr = E_NOTIMPL; LO_CHECK_STATEz1("BrowseAccessPath", ppIEnumString); if (!ppIEnumString) hr = E_INVALIDARG; else { if (se->driver.ldBrowseAccessPath) { loEnumString *es = new loEnumString(0); if (es) { *ppIEnumString = es; hr = se->driver.ldBrowseAccessPath(&ctxt.cactx, szItemID, ppIEnumString); if (!*ppIEnumString && !FAILED(hr)) hr = E_FAIL; if (FAILED(hr)) { if (*ppIEnumString == (LPENUMSTRING)es) *ppIEnumString = 0; delete es; } else if (*ppIEnumString != (LPENUMSTRING)es) delete es; else if (S_OK != (hr = es->initiate(&otrk))) delete es; } else hr = E_OUTOFMEMORY; } } UL_NOTICE((LOG_SR("BrowseAccessPath(%ls) = %s"), loWnul(szItemID), loStrError(hr))); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCServer::BrowseOPCItemIDs( /* [in] */ OPCBROWSETYPE dwBrowseFilterType, /* [string][in] */ LPCWSTR szFilterCriteria, /* [in] */ VARTYPE vtDataTypeFilter, /* [in] */ DWORD dwAccessRightsFilter, /* [out] */ LPENUMSTRING *ppIEnumString) { HRESULT hr = S_OK; loEnumString *ulist = 0; LO_CHECK_STATEz1("BrowseOPCItemIDs", ppIEnumString); if (szFilterCriteria && !*szFilterCriteria) szFilterCriteria = 0; if (!ppIEnumString || dwBrowseFilterType != OPC_FLAT && dwBrowseFilterType != OPC_BRANCH && dwBrowseFilterType != OPC_LEAF) { hr = E_INVALIDARG; goto Return; } if (!(ulist = new loEnumString(0))) { hr = E_OUTOFMEMORY; goto Return; } { loTagId ti; lo_hash *hash_list = 0; loWchar brsep = se->branch_sep; BOOL casesens = 0 == (/*se->driver.*/ldFlags & loDF_IGNCASE); loWchar *brpos = 0; unsigned brlen = 0; int am_mask; loCallerx cctx = ctxt; loStringBuf aname; loStringBuf_init(&aname); lock_browse(); if (browsepos.sb_str) { brlen = wcslen(browsepos.sb_str); brpos = loWstrdup(browsepos.sb_str); } cctx.cta.vc_lcid = ctxt.cta.vc_lcid; unlock_browse(); if (brlen && !brpos) { hr = E_OUTOFMEMORY; goto Return; } if (!brsep) dwBrowseFilterType = OPC_FLAT; // level = lo_name_level(brsep, browsepos.sb_str); UL_TRACE((LOG_SR("Browse for: %u/%ls/ access %d"), brlen, loWnul(brpos), dwAccessRightsFilter)); dwAccessRightsFilter &= loOPC_RIGHTS; if (dwAccessRightsFilter == (OPC_READABLE | OPC_WRITEABLE)) dwAccessRightsFilter = 0; am_mask = dwAccessRightsFilter; if (access_mode & loAM_RDONLY_BROWSE) am_mask &= ~OPC_WRITEABLE; //loMilliSec stst = lo_millisec(); loLOCK_MGMT_O(&se->lkMgmt); for(ti = 0; ti = lo_browse_tag(se, ti, brpos, brlen, dwBrowseFilterType); ti++) { unsigned alen; loTagEntry *te = &se->tags[ti]; const loWchar *item = te->attr.taName + brlen; if (!*item) continue; /* don't return itself */ if (brsep == *item) item++; switch(dwBrowseFilterType) { case OPC_LEAF: if (wcschr(item, brsep)) continue; //if (1 < lo_name_level(brsep, item)) continue; case OPC_FLAT: alen = wcslen(item); if (dwAccessRightsFilter && !(am_mask/*dwAccessRightsFilter*/ & te->attr.taRights)) continue; if (vtDataTypeFilter != VT_EMPTY && S_OK != lo_checktype(&cctx, &te->attr, vtDataTypeFilter)) continue; break; case OPC_BRANCH: if (!wcschr(item, brsep)) continue; //if (1 >= lo_name_level(brsep, item)) continue; alen = lo_name_levlen(brsep, item, 1); { loWchar *uit; if (ulist->total && !se->wstrncmp(item, uit = ulist->list[ulist->total - 1], alen) && 0 == uit[alen]) continue; /* duplicate */ } break; } if (!loStringBuf_REALLOC(&aname, alen + 1)) { hr = E_OUTOFMEMORY; break; } wcsncpy(aname.sb_str, item, alen); aname.sb_str[alen] = 0; if (szFilterCriteria && !MatchPattern(aname.sb_str, szFilterCriteria, casesens)) continue; if (OPC_BRANCH == dwBrowseFilterType) { unsigned uu; lo_hash a_hash = loSTRHASH(se, aname.sb_str); for(uu = ulist->total; uu; uu--) if (a_hash == hash_list[uu-1] && !se->wstrcmp(aname.sb_str, ulist->list[uu-1]) ) break; if (uu) continue; if (!preallocX((void**)&hash_list, sizeof(*hash_list)*(ulist->total+1))) { hr = E_OUTOFMEMORY; break; } hash_list[ulist->total] = a_hash; } //UL_DEBUG((LOG_SR("Browse %ls"), aname.sb_str)); hr = ulist->add_item(&aname.sb_str); if (S_OK != hr) break; } /* end of for() */ loUnLOCK_MGMT_O(&se->lkMgmt); /* UL_WARNING((LOG_SR("BrowseOPC <%ls> %d TIME %d"), loWnul(brpos), ulist->total, lo_millisec() - stst)); //*/ if (brpos) freeX(brpos); if (hash_list) freeX(hash_list); loStringBuf_clear(&aname); } Return: if (S_OK == hr && S_OK == (hr = ulist->initiate(&otrk))) { *ppIEnumString = (LPENUMSTRING)ulist; UL_NOTICE((LOG_SR("BrowseOPCItemIDs() = %u"), ulist->total)); if (!ulist->total) { ENUM_EMPTY(hr, ldFlags, ppIEnumString); } } else { if (ulist) { delete ulist; ulist = 0; } UL_INFO((LOG_SR("BrowseOPCItemIDs() = %s"), loStrError(hr))); } LO_FINISH(); return hr; }
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 LightOPCServer::ChangeBrowsePosition( /* [in] */ OPCBROWSEDIRECTION dwBrowseDirection, /* [string][in] */ LPCWSTR szString) { HRESULT hr = S_OK; LO_CHECK_STATEz0("ChangeBrowsePosition"); lock_browse(); { loWchar brsep; int ii; //UL_WARNING((LOG_SR("ChangeBrowsePosition->(%ls)(%ls)"), loWnul(browsepos.sb_str),loWnul(szString))); if (!(brsep = se->branch_sep)) { hr = E_FAIL; UL_TRACE((LOG_SR("ChangeBrowsePosition() on the FLAT"))); } else switch(dwBrowseDirection) { case OPC_BROWSE_UP: if (0 >= (ii = lo_name_level(brsep, browsepos.sb_str))) { hr = E_FAIL; /* already on root */ UL_TRACE((LOG_SR("ChangeBrowsePosition() already on root"))); } else { hr = set_browsepos(browsepos.sb_str, lo_name_levlen(brsep, browsepos.sb_str, ii - 1)); } break; case OPC_BROWSE_DOWN: if (!szString || !*szString) hr = E_INVALIDARG;//loOPC_E_NOTFOUND; else if (0 > (ii = cat_browsepos(szString))) hr = E_OUTOFMEMORY; else if (!lo_browse_branch(se, browsepos.sb_str)) { browsepos.sb_str[ii] = 0; hr = E_INVALIDARG;//loOPC_E_NOTFOUND; } break; case OPC_BROWSE_TO: if (!szString || !*szString) hr = set_browsepos(0); else hr = lo_browse_branch(se, szString)? set_browsepos(szString): E_INVALIDARG;//loOPC_E_NOTFOUND; break; default: hr = E_INVALIDARG; UL_TRACE((LOG_SR("ChangeBrowsePosition() unknown direction"))); break; } } UL_TRACE((LOG_SR("ChangeBrowsePosition(%X <%ls>) = %ls"), dwBrowseDirection, loWnul(szString), loWnul(browsepos.sb_str))); unlock_browse(); if (S_OK != hr) { UL_INFO((LOG_SR("ChangeBrowsePosition(%X <%ls>) = %s"), dwBrowseDirection, loWnul(szString), loStrError(hr))); } LO_FINISH(); 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; }
HRESULT LightOPCServer::internalAddGroup( LightOPCGroup *grp, LPCWSTR szName, BOOL bActive, DWORD UpdateRate, OPCHANDLE hClientGroup, LONG *pTimeBias, FLOAT *pPercentDeadband, DWORD dwLCID, OPCHANDLE *phServerGroup, REFIID riid, LPUNKNOWN *ppUnk ) { HRESULT hr = S_OK; unsigned servindex = 0; OPCHANDLE servhandle = 0; loWchar tname[loUNIQUE_LEN]; if (phServerGroup) *phServerGroup = 0; if (!ppUnk) { hr = E_INVALIDARG; goto Exit; } *ppUnk = 0; /* if (!grp && !(grp = new LightOPCGroup()) || grp->sstate != loST_READY) { hr = E_OUTOFMEMORY; goto Exit; }*/ /* need assign all group atributes */ grp->ClientHandle = hClientGroup; grp->UpdateRate = UpdateRate; grp->Active = bActive != 0; grp->Deadband = .0f; if (pPercentDeadband) { if (lo_IsNANf(*pPercentDeadband) || *pPercentDeadband < 0. || *pPercentDeadband > 100.) { hr = E_INVALIDARG; goto Exit; } grp->Deadband = *pPercentDeadband; } if (se->driver.ldCheckLocale && se->driver.ldCheckLocale(&ctxt.cactx, dwLCID)) GetLocaleID(&dwLCID); grp->grLCID = dwLCID; if (pTimeBias) grp->TimeBias = *pTimeBias; else { TIME_ZONE_INFORMATION tzi; tzi.Bias = 0; GetTimeZoneInformation(&tzi); grp->TimeBias = tzi.Bias; } if (szName) if (!*szName) szName = 0; else if (S_OK != grp->set_name(szName)) { hr = E_OUTOFMEMORY; goto Exit; } // grp->sstate = loST_READY; hr = grp->QueryInterface(riid, (void**)ppUnk); // grp->sstate = loST_DOWN; if (S_OK != hr) goto Exit; lock_write(); if (!szName) { if (S_OK == (hr = mk_unique(tname, grp))) hr = grp->set_name(szName = tname); } else if (by_name(szName)) hr = OPC_E_DUPLICATENAME; if (S_OK == hr) if (servindex = add(grp)) { do { if ((servhandle = ++unique_GroupHandle) == 0) servhandle = ++unique_GroupHandle; } while(by_handle(servhandle)); grp->ServerHandle = servhandle; ostatus.dwGroupCount++; } else { hr = E_OUTOFMEMORY; /* delete grp; will be deleted by caller */ } unlock(); if (phServerGroup) *phServerGroup = servhandle; Exit: if (S_OK == hr) { UL_TRACE((LOG_SR("intAddGroup(%ls) i:%u h:%u /%p"), szName? szName: tname, servindex, servhandle, *ppUnk)); } else { UL_TRACE((LOG_SR("intAddGroup(%ls) =%s"), loWnul(szName), loStrError(hr))); // if (grp) delete grp; *ppUnk = 0; } return hr; }
STDMETHODIMP LightOPCGroup::SetDatatypes(DWORD dwCount, OPCHANDLE *phServer, VARTYPE *pRequestedDatatypes, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; loTagEntry *te; loCallerx cctx; LO_CHECK_STATEz1("SetDatatypes", ppErrors); if (!dwCount || !phServer || !pRequestedDatatypes) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } te = owner->se->tags; cctx = owner->ctxt; lock_write(); { DWORD ii; LightOPCItem *item; cctx.cta.vc_lcid = grLCID; for(ii = 0; ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { VARTYPE vt; loTagAttrib *ta; /* if (VT_EMPTY == (vt = pRequestedDatatypes[ii])) item->vtRequestedDataType = vt, err[ii] = S_OK; else */ if (S_OK == (err[ii] = lo_checktype(&cctx, ta = &te[item->tid].attr, vt = pRequestedDatatypes[ii]))) { item->vtRequestedDataType = vt; item->convtype = lo_check_conversion(ta, vt); } else hr = S_FALSE; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetDatatypes(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetDatatypes(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::SetActiveState(DWORD dwCount, OPCHANDLE *phServer, BOOL bActive, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; int aqual = OPC_QUALITY_OUT_OF_SERVICE; unsigned aact = 0; LO_CHECK_STATEz1("SetActiveState", ppErrors); if (!dwCount || !phServer /*|| !ppErrors*/) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } if (bActive = 0 != bActive) aqual = -1; lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount;) { unsigned tt; loTagId ti[32]; for(tt = 0; tt < SIZEOF_ARRAY(ti) && ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { if (item->bActive != bActive /*&& (OPC_READABLE & tags[item->tid].attr.flag)*/) { aact++; item->bActive = bActive; ti[tt++] = item->tid; item->Quality = aqual; item->TouchChanged(); } err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } if (tt && Active) loChangeActivity(&owner->ctxt.cactx, bActive, tt, ti); } if (bActive) active_count += aact, last_trid = 0; else active_count -= aact; } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetActiveState(%lu, %u) = %s"), dwCount, bActive, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetActiveState(%lu, %u) = %s"), dwCount, bActive, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCServer::AddGroup( LPCWSTR szName, BOOL bActive, DWORD dwRequestedUpdateRate, OPCHANDLE hClientGroup, LONG *pTimeBias, FLOAT *pPercentDeadband, DWORD dwLCID, OPCHANDLE *phServerGroup, DWORD *pRevisedUpdateRate, REFIID riid, LPUNKNOWN *ppUnk ) { HRESULT hr = S_OK; LightOPCGroup *grp = 0; DWORD RevisedRate; OPCHANDLE ServerGroup; LO_CHECK_STATEz1("AddGroup", ppUnk); UL_TRACE((LOG_SR("AddGroup(%ls)"), loWnul(szName))); if (!ppUnk) { hr = E_INVALIDARG; goto Exit; } // if (!phServerGroup || !pRevisedUpdateRate) { hr = E_INVALIDARG; goto Exit; } if (!phServerGroup) phServerGroup = &ServerGroup; if (!(grp = new LightOPCGroup) || !grp->iam_valid()) { hr = E_OUTOFMEMORY; goto Exit; } /* need assign all group atributes */ RevisedRate = loReviseUpdateRate(se, dwRequestedUpdateRate); hr = internalAddGroup(grp, szName, bActive, RevisedRate, hClientGroup, pTimeBias, pPercentDeadband, dwLCID, phServerGroup, riid, ppUnk); Exit: // if (!szName && grp) szName = grp->name; if (S_OK == hr) { if (pRevisedUpdateRate) *pRevisedUpdateRate = RevisedRate; if (RevisedRate != dwRequestedUpdateRate) hr = OPC_S_UNSUPPORTEDRATE; UL_NOTICE((LOG_SR("AddGroup(%ls) =%u (%umS (%umS) %g%%) %p"), loWnul(szName), *phServerGroup, (unsigned)RevisedRate, (unsigned)dwRequestedUpdateRate, pPercentDeadband? *pPercentDeadband: 0.0, *ppUnk)); } else { UL_INFO((LOG_SR("AddGroup(%ls) =%s"), loWnul(szName), loStrError(hr))); if (grp) delete grp; } LO_FINISH(); return hr; }
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::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; }
STDMETHODIMP LightOPCGroup::AddItems(DWORD dwCount, OPCITEMDEF *pItemArray, OPCITEMRESULT **ppAddResults, HRESULT **ppErrors) { HRESULT hr; HRESULT *err = 0; OPCITEMRESULT *ir = 0; loTagId *tid = 0; void **acpath; LightOPCItem **oi = 0; DWORD ii; loTagEntry *tags; unsigned act_count; loAA_DECLARE(sizeof(LightOPCItem*) + sizeof(loTagId) + sizeof(void*)); LO_CHECK_STATEz2("AddItems", ppAddResults, ppErrors); if (!ppAddResults) { hr = E_INVALIDARG; goto Return; } ii = dwCount * (sizeof(*oi) + sizeof(*tid) + sizeof(*acpath)); if (0 == ii) { hr = E_INVALIDARG; goto Return; } if (!(oi = (LightOPCItem**)loAA_ALLOC(ii))) { hr = E_OUTOFMEMORY; goto Return; } memset(oi, 0, ii); tid = (loTagId*)&oi[dwCount]; acpath = (void**)&tid[dwCount]; hr = internalValidateItems(dwCount, pItemArray, tid, acpath, &ir, &err); if (FAILED(hr)) goto Return; tags = owner->se->tags; for(ii = 0; ii < dwCount; ii++) if (S_OK == err[ii]) { LightOPCItem *newby; hr = E_OUTOFMEMORY; if (oi[ii] = newby = new LightOPCItem) { OPCITEMDEF *idef = &pItemArray[ii]; loTagAttrib *ta = &tags[tid[ii]].attr; newby->tid = tid[ii]; newby->AcPath = acpath[ii]; newby->hClient = idef->hClient; newby->vtRequestedDataType = idef->vtRequestedDataType; newby->convtype = lo_check_conversion(ta, newby->vtRequestedDataType); hr = S_OK; if ((NULL == newby->AcPath || S_OK == (hr = newby->set_accpath(idef->szAccessPath))) && (!ta->taName || !(ta->taFlags & loTF_CANONAME) && #if 0 wcscmp #else owner->se->wstrcmp #endif (ta->taName, idef->szItemID))) hr = newby->set_itemid(idef->szItemID); newby->Quality = -1; if (0 == (newby->bActive = 0 != idef->bActive)) tid[ii] = 0, newby->Quality = OPC_QUALITY_OUT_OF_SERVICE; // else if (!(OPC_READABLE & tags[tid[ii]].attr.flag)) // newby->bActive = 0; } err[ii] = hr; if (hr != S_OK) UL_NOTICE((LOG_GR("AddItem(%ls)(%ls)%x/%x = %s"), loWnul(pItemArray[ii].szItemID), loWnul(pItemArray[ii].szAccessPath), pItemArray[ii].vtRequestedDataType, ir[ii].vtCanonicalDataType, loStrError(err[ii]))); } act_count = 0; lock_write(); for(ii = 0; ii < dwCount; ii++) if (S_OK == err[ii]) { unsigned idx; if (idx = add(oi[ii])) { act_count += oi[ii]->bActive /* != 0*/; oi[ii] = 0; ir[ii].hServer = (OPCHANDLE)idx; } else { err[ii] = E_OUTOFMEMORY; tid[ii] = 0; hr = S_FALSE; UL_NOTICE((LOG_GR("AddItem:add(%ls)(%ls)%x/%x = %s"), loWnul(pItemArray[ii].szItemID), loWnul(pItemArray[ii].szAccessPath), pItemArray[ii].vtRequestedDataType, ir[ii].vtCanonicalDataType, loStrError(err[ii]))); } } else { tid[ii] = 0; hr = S_FALSE; } /* end of for(;;) */ if (act_count) { active_count += act_count; if (Active) { loChangeActivity(&owner->ctxt.cactx, 1, (unsigned)dwCount, tid); last_trid = 0; /* force callback */ } } unlock(); Return: if (oi) { for(ii = 0; ii < dwCount; ii++) if (oi[ii]) delete oi[ii]; loAA_FREE(oi); } if (FAILED(hr)) { UL_INFO((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr))); } else { *ppAddResults = ir, ir = 0; if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr))); } if (ir) loComFree(ir); if (err) loComFree(err); LO_FINISH(); return hr; }