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::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; }
static void rio_refresh(LightOPCServer *cli, loRequest *rq) { LightOPCGroup *grp; unsigned group_key = rq->group_key; int operation = rq->operation; loRqid trqid = rq->upl.trqid; DWORD transid = rq->upl.transaction_id; loUpdList upl; lo_upl_init(&upl, loUPL_variant | loUPL_timestamp | loUPL_quality | loUPL_errors | loUPL_opchandle); upl.trqid = trqid; upl.transaction_id = transid; lo_req_free(rq); cli->lock_read(); if ((grp = cli->by_handle_g(group_key)) && (grp->advise_present & operation & loRQ_CONN_DATA)) { lo_refresh_items(cli->se, &upl, grp); cli->send_callback(grp, 0, &upl, operation); } else { cli->unlock(); UL_INFO((LOGID, "Refresh(%x) Aborted: No such group or connection", trqid)); } lo_upl_clear(&upl); }
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::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 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; }
HRESULT MyClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) { ATLASSERT(ppvObj); if (NULL == ppvObj) { return E_INVALIDARG; } *ppvObj = NULL; HRESULT hr = S_OK; IUnknown *server = NULL; IUnknown *inner = NULL; if (NULL == DataService::Instance()) { return E_POINTER; } if (loClientCreate_agg(DataService::Instance().get(), (loClient**)&server, pUnkOuter, &inner, 0, &vendor, a_server_finished, NULL/*cuserid*/)) { // server remove UL_ERROR((Log::Instance().get(), 0, "myClassFactory::loClientCreate_agg() failed")); hr = E_OUTOFMEMORY; } else if (pUnkOuter) { *ppvObj = (void*)inner; // aggregation requested } else // no aggregation { hr = server->QueryInterface(riid, ppvObj); // Then 2 (if success) server->Release(); // Then 1 (on behalf of client) or 0 (if QI failed) } if (SUCCEEDED(hr)) { loSetState(DataService::Instance().get(), (loClient*)server, loOP_OPERATE, (int)OPC_STATUS_RUNNING, "Finished by client"); UL_INFO((Log::Instance().get(), 0, "OPC service is started.")); } #ifdef __EVAL__ boost::shared_ptr<boost::thread> licThread(new boost::thread(LicenseTimeout)); #endif 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::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 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 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; }
loTrid loCacheUpdate(loService *se, unsigned count, loTagValue taglist[], FILETIME *timestamp) { unsigned ii; loTagValue *ts; #if 0 != LO_FILL_TIMESTAMP FILETIME ft; #endif // UL_DEBUG((LOGID, "loCacheUpdate(%p %u %p)", se, count, taglist)); if (!loSERVICE_OK(se)) return 0;//EBADF; /*ERROR:EARG*/ if (!timestamp && (0 >= count || !taglist)) return 0; #if 0 != LO_FILL_TIMESTAMP #if 1 == LO_FILL_TIMESTAMP se->driver.ldCurrentTime(&se->cactx, &ft); #else if (timestamp) ft = *timestamp; else memset(&ft, 0, sizeof(ft)); #endif #endif if (!(ts = loCacheLock(se))) { UL_INFO((LOGID, "loCacheUpdate() lock failed")); return 0;//-1; /*ERROR:out-of-service*/ } for(ii = 0; ii < count; ii++, taglist++) { loTagId ti; if (0 == (ti = taglist->tvTi)) continue; else if (ti < 1 || ti > se->lastused/*tag_count*/) { /*rv = -1;*//*ERROR:BAD ti*/ UL_INFO((LOGID, "loCacheUpdate(BAD ti:%u)", ii)); continue; } else { HRESULT hr; loTagValue *tv = &ts[ti]; tv->tvState = taglist->tvState; #if 0 != LO_FILL_TIMESTAMP if (!IsFILETIME(tv->tvState.tsTime)) tv->tvState.tsTime = ft; #endif /* hr = (V_ISBYREF(&taglist->tvValue)? VariantCopyInd(&tv->tvValue, &taglist->tvValue): VariantCopy(&tv->tvValue, &taglist->tvValue)); */ hr = VariantCopy(&tv->tvValue, &taglist->tvValue); if (S_OK != hr) { LO_E_BADTYPE_QUAL(hr, tv->tvState.tsError, tv->tvState.tsQuality); /*rv = -1;*//*ERROR:BAD VALUE*/ UL_WARNING((LOGID, "%!l loCacheUpdate(VariantCopy())", hr)); } tv->tvTi = ti; } } return loCacheUnlock(se, timestamp); /* return rv; */ }
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; }
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; }
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; }
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; }
int loServiceCreate(loService **result, const loDriver *drv, unsigned tagcount) { int rv = 0; size_t size; loService *se; if (!result) return EINVAL; *result = 0; if (!drv || 0 >= tagcount || 0 >= ++tagcount) return EINVAL; UL_DEBUG((LOGID, "structs: tE=%u tA=%u tD=%u tV=%u tS=%u tP=%u", sizeof(loTagEntry), sizeof(loTagAttrib), sizeof(loTagDetail), sizeof(loTagValue), sizeof(loTagState), sizeof(loTagPair))); size = sizeof(loService) + (sizeof(loTagEntry) + sizeof(loTagValue) + sizeof(lo_hash)) * tagcount; UL_TRACE((LOGID, "loCreate(%u) requested size = %u", tagcount - 1, size)); se = (loService*)mallocX(size); if (!se) { UL_ERROR((LOGID, "loCreate(%u) requested size = %ud FAILED", tagcount, size)); return ENOMEM; } se->iam = se; se->servlist = 0; se->serv_key = 0; se->shutdown = 0; se->initphase = 0; se->tag_count = 0; se->firstfree = 1; /* first entry is not used */ se->lastused = 0; se->lastnamed = 0; se->proplist = 0; se->proplist_count = 0; se->driver = *drv; se->cactx.ca_se = se; se->cactx.ca_se_arg = se->driver.ldDriverArg; se->cactx.ca_cli = 0; se->cactx.ca_cli_arg = 0; se->ts_prim = se->ts_sec = 0; se->ts_size = 0; se->log = 0; #if 0 <= USE_LOG if (!lolog) { lolog = (unilog*)(se->log = INIT_LOG()); UL_INFO((LOGID, "UNILOG initialization missed...")); UL_TRACE((LOGID, "loCreate(%u) requested size = %u", tagcount - 1, size)); } #endif se->ts_prim = se->ts_sec = (FILETIME*)mallocX(2 * sizeof(FILETIME)); if (!se->ts_prim) { rv = ENOMEM; UL_ERROR((LOGID, "ts_prim init() FAILED")); goto Fail; } memset(se->ts_prim, 0, 2 * sizeof(FILETIME)); se->ts_size = 1; if (rv = lo_proplist_init(se)) { UL_ERROR((LOGID, "lo_proplist_init() FAILED")); goto Fail; } lo_setup_clock(); if (se->driver.ldRefreshRate < 1) { se->driver.ldRefreshRate = lo_default_timegran( se->driver.ldRefreshRate_min < 1 ? &se->driver.ldRefreshRate_min : 0); if (se->driver.ldRefreshRate/*_min*/ < 1) se->driver.ldRefreshRate/*_min*/ = 16; } if (se->driver.ldRefreshRate_min < se->driver.ldRefreshRate) se->driver.ldRefreshRate_min = se->driver.ldRefreshRate; if (se->driver.ldQueueMax < 1) se->driver.ldQueueMax = 4; /* DEFAULT */ if ((se->driver.ldFlags & loDf_EE_SFALSE) == loDf_EE_SFALSE) se->driver.ldFlags &= ~loDf_EE_SFALSE; se->wstrcmp = (se->driver.ldFlags & loDF_IGNCASE)? _wcsicmp: wcscmp; se->wstrncmp = (se->driver.ldFlags & loDF_IGNCASE)? _wcsnicmp: wcsncmp; se->wstrhash = (se->driver.ldFlags & loDF_IGNCASE)? lo_wcsihash: lo_wcshash; #if 0 se->wstrnhash = (se->driver.ldFlags & loDF_IGNCASE)? lo_wcsnihash: lo_wcsnhash; #endif if (!se->driver.ldCurrentTime) se->driver.ldCurrentTime = ld_current_time; if (!se->driver.ldBranchSep || 0 >= mbtowc(&se->branch_sep, &se->driver.ldBranchSep, 1)) se->branch_sep = 0; UL_TRACE((LOGID, "Branch Separator = \\x%02X <%lc>\\x%02X", se->driver.ldBranchSep, se->branch_sep, se->branch_sep)); se->tags = (loTagEntry*)(&se[1]); loTagEntry_init(se->tags, tagcount); se->secondary = (loTagValue*)(&se->tags[tagcount]); loTagValue_init(se->secondary, tagcount); se->tag_count = tagcount; se->name_hash = (lo_hash*)(&se->secondary[tagcount]); memset(se->name_hash, 0, sizeof(lo_hash) * tagcount); /* we assume VT_EMPTY === 0 */ se->sec_trid = se->prim_trid = 0; /* se->prim_changed = 0; */ se->tags[0].attr.taDetail = (loTagDetail*)mallocX(sizeof(loTagDetail)); if (!se->tags[0].attr.taDetail) { UL_ERROR((LOGID, "loCreate(%u) taDetail FAILED", tagcount)); rv = ENOMEM; goto Fail; } loTagDetail_init(se->tags[0].attr.taDetail); se->tags[0].attr.taFlags = loTt_DETAILS | loTF_EMPTY; se->tags[0].attr.taDetail->tdName[0] = 0; se->tags[0].attr.taRangecent = 0.0; if (rv = lw_rwlock_init(&se->lkMgmt, 0)) { UL_ERROR((LOGID, "loCreate()::lkMgmt FAILED")); goto Fail; } se->initphase |= ifLKMGMT; if (rv = lw_rwlock_init(&se->lkPrim, 0)) { UL_ERROR((LOGID, "loCreate()::lkPrim FAILED")); goto Fail; } se->initphase |= ifLKPRIM; if (rv = lw_mutex_init(&se->lkList, 0)) { UL_ERROR((LOGID, "loCreate()::lkList FAILED")); goto Fail; } se->initphase |= ifLKLIST; if (rv = lw_mutex_init(&se->lkDr, 0)) { UL_ERROR((LOGID, "loCreate()::lkDr FAILED")); goto Fail; } se->initphase |= ifLKDR; if (rv = lw_condb_init(&se->lkTridWait, 0)) { UL_ERROR((LOGID, "loCreate()::lkTridWait FAILED")); goto Fail; } se->initphase |= ifTRWAIT; if (rv = loThrControl_init(&se->update_pipe)) { UL_ERROR((LOGID, "loCreate()::loThr_init FAILED")); goto Fail; } se->initphase |= ifLKSEC; if (rv = loThrControl_start(&se->update_pipe, 0, loUpdatePipe, se)) { UL_ERROR((LOGID, "loCreate()::loThr_start FAILED")); goto Fail; } se->cform_dataonly = RegisterClipboardFormat("OPCSTMFORMATDATA"); se->cform_datatime = RegisterClipboardFormat("OPCSTMFORMATDATATIME"); se->cform_writecompl = RegisterClipboardFormat("OPCSTMFORMATWRITECOMPLETE"); *result = se; return 0; Fail: UL_WARNING((LOGID, "%!e loCreate(%u) failed", rv, tagcount)); loServiceDestroy(se); return rv; }
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::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 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::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::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; }
HRESULT manageOPCDAcat(const GUID *service, int remove) { HRESULT hr, hri; ICatRegister *pcr; hri = CoInitialize(0); hr = CoCreateInstance( #ifndef __cplusplus & #endif CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, #ifndef __cplusplus & #endif IID_ICatRegister, (void **)&pcr ); if (FAILED(hr)) { UL_INFO((LOGID, "%!l FAILED to get ICatRegister", hr)); } else { CATID catid[2]; if (0 == remove) { CATEGORYINFO catinf[2]; catinf[0].catid = CATID_OPCDAServer10; wcscpy(catinf[0].szDescription, L"OPC Data Access Servers Version 1.0"); catinf[0].lcid = 0x0409; catinf[1].catid = CATID_OPCDAServer20; wcscpy(catinf[1].szDescription, L"OPC Data Access Servers Version 2.0"); catinf[1].lcid = 0x0409; #ifdef __cplusplus hr = pcr->RegisterCategories(2, catinf); #else hr = pcr->lpVtbl->RegisterCategories(pcr, 2, catinf); #endif if (FAILED(hr)) UL_INFO((LOGID, "%!l FAILED ICatRegister::RegisterCategories()", hr)); } catid[0] = CATID_OPCDAServer10; catid[1] = CATID_OPCDAServer20; #ifdef __cplusplus hr = remove? pcr->UnRegisterClassImplCategories(*service, 2, catid): pcr->RegisterClassImplCategories(*service, 2, catid); pcr->Release(); #else hr = remove? pcr->lpVtbl->UnRegisterClassImplCategories(pcr, service, 2, catid): pcr->lpVtbl->RegisterClassImplCategories(pcr, service, 2, catid); pcr->lpVtbl->Release(pcr); #endif if (FAILED(hr)) UL_INFO((LOGID, "%!l FAILED ICatRegister::%sRegisterClassImplCategories()", hr, remove? "Un": "")); } if (SUCCEEDED(hri)) CoUninitialize(); UL_DEBUG((LOGID, "%!l ICatRegister::%sRegister", hr, remove? "Un": "")); return hr; }