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; }
void loSearchIID(IUnknown *punk) { DWORD indx; HKEY key; char buf[256], *tbuf; UL_TRACE((LOGID, "Iface: %p", punk)); if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, "Interface", &key)) { UL_ERROR((LOGID, "%!L RegOpenKey(Interface)")); return; } strcpy(buf, "Interface\\"); tbuf = buf + strlen(buf); for(indx = 0; ERROR_SUCCESS == RegEnumKey( key, indx, tbuf, buf + sizeof(buf) - tbuf); indx++) { GUID iid; HRESULT hr; IUnknown *qi; LONG cb; char name[256]; name[0] = 0; cb = sizeof(name); RegQueryValue(key, tbuf, name, &cb); StrToIID(&iid, tbuf); if (S_OK == (hr = punk->QueryInterface(iid, (LPVOID*)&qi))) { UL_TRACE((LOGID, "Ok %s %p", name, qi)); qi->Release(); } /* else if (hr != E_NOINTERFACE) { UL_DEBUG((LOGID, "%!l %s -> %s", hr, name, tbuf)); } */ } RegCloseKey(key); }
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; }
int loServiceDestroy(loService *se) { UL_TRACE((LOGID, "loServiceDestroy(%p)...", se)); if (!loIS_VALID(se)) return EBADF; if ((se->initphase & (ifLKLIST|ifLKSEC)) == (ifLKLIST|ifLKSEC)) { lw_mutex_lock(&se->lkList); if (se->shutdown) { lw_mutex_unlock(&se->lkList); UL_ERROR((LOGID, "loServiceDestroy(%p) shutdown started again", se)); return EBADF; } if (se->servlist) { LightOPCServer *los = (LightOPCServer*)se->servlist; se->shutdown = 1; while(los) { los->set_state(loOP_SHUTDOWN|loOP_STOP|loOP_DISCONNECT, 0, 0); los = los->serv_next; } lw_mutex_unlock(&se->lkList); UL_NOTICE((LOGID, "loServiceDestroy(%p) shutdown started", se)); return EBUSY; } se->shutdown = -1; lw_mutex_unlock(&se->lkList); #if 0 loThrControl_stop(&se->update_pipe); #endif lw_condb_broadcast_continious(&se->lkTridWait, &se->update_pipe.lk); } return loInternalServiceDestroy(se); }
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; }
int loServerRegister(const GUID *CLSID_Svr, const char *ProgID, const char *Name, const char *exPath, const char *Model /* 0=exe, ""=STA dll, "Both", "Free" ...*/) { HKEY hKey; HKEY hKeyAux; char sStr[260]; char sIID [40]; const char *srvtype = "InprocServer32"; LONG ec = ERROR_INVALID_PARAMETER; if (!ProgID /*|| !exPath*/) goto SetErr; if (exPath && !*exPath) exPath = NULL; UL_TRACE((LOGID, "loServerRegister(%s)", ProgID)); if (0 == Model) srvtype = "LocalServer32"; /* { char *ext; if (0 > extype || (ext = strrchr(exPath, '.')) && !stricmp(ext, ".exe")) srvtype = "LocalServer32"; }*/ IIDtoStr (sIID, CLSID_Svr); if (ERROR_SUCCESS != (ec = RegCreateKey(HKEY_CLASSES_ROOT, ProgID, &hKey))) goto SetErr; if (Name) RegSetValue(hKey, NULL, REG_SZ, Name, strlen(Name)+1); if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, "CLSID", &hKeyAux))) goto Fail; ec = RegSetValue(hKeyAux, NULL, REG_SZ, sIID, strlen(sIID)+1); RegCloseKey(hKeyAux); if (ERROR_SUCCESS != ec) goto Fail; if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, "OPC", &hKeyAux))) goto Fail; { HKEY vendor; /* RegSetValue (hKeyAux, NULL, REG_SZ, sIID, strlen(sIID)+1); */ /* Should "vendor" be a subkey or a named value? */ if (ERROR_SUCCESS == RegCreateKey(hKeyAux, "Vendor", &vendor)) { RegSetValue(vendor, NULL, REG_SZ, "ConnectSpot", sizeof("ConnectSpot")); RegCloseKey(vendor); } RegCloseKey(hKeyAux); } RegCloseKey(hKey); sprintf (sStr, "AppID\\%s", sIID); if (ERROR_SUCCESS != (ec = RegCreateKey(HKEY_CLASSES_ROOT, sStr, &hKey))) goto UnReg; if (Name) RegSetValue(hKey, NULL, REG_SZ, Name, strlen(Name)+1); /* DllSurrogate="" RunAs="Interactive User" RemoteServerName= */ RegCloseKey(hKey); sprintf (sStr, "CLSID\\%s", sIID); if (ERROR_SUCCESS != (ec = RegCreateKey(HKEY_CLASSES_ROOT, sStr, &hKey))) goto UnReg; if (Name) RegSetValue(hKey, NULL, REG_SZ, Name, strlen(Name)+1); if (exPath) { if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, srvtype, &hKeyAux))) goto Fail; ec = RegSetValue(hKeyAux, NULL, REG_SZ, exPath, strlen(exPath)+1); if (Model && *Model) /* dll */ RegSetValueEx(hKeyAux, "ThreadingModel", 0, REG_SZ, (const BYTE*)Model, strlen(Model)+1); RegCloseKey(hKeyAux); if (ERROR_SUCCESS != ec) goto Fail; } // The NAIL for DCOMcnfg !!! // RegSetValueEx(hKeyAux, NULL, 0, REG_EXPAND_SZ, exPath, strlen(exPath)+1); RegSetValueEx(hKey, "AppID", 0, REG_SZ, (const BYTE*)sIID, strlen(sIID)+1); // RegSetValue(hKey, "AppID", REG_SZ, sIID, strlen(sIID)+1); if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, "ProgID", &hKeyAux))) goto Fail; ec = RegSetValue(hKeyAux, NULL, REG_SZ, ProgID, strlen(ProgID)+1); RegCloseKey(hKeyAux); if (ERROR_SUCCESS != ec) goto Fail; if (FAILED(manageOPCDAcat(CLSID_Svr, 0))) { IIDtoStr(sIID, &CATID_OPCDAServer10); sprintf (sStr, "Implemented Categories\\%s", sIID); if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, sStr, &hKeyAux))) goto Fail; RegCloseKey(hKeyAux); IIDtoStr (sIID, &CATID_OPCDAServer20); sprintf (sStr, "Implemented Categories\\%s", sIID); if (ERROR_SUCCESS != (ec = RegCreateKey(hKey, sStr, &hKeyAux))) goto Fail; RegCloseKey(hKeyAux); } RegCloseKey(hKey); return 0; Fail: RegCloseKey(hKey); UnReg: loServerUnregister(CLSID_Svr, Name); SetErr: SetLastError(ec); UL_ERROR((LOGID, "%!l loServerRegister(%s) FAILED", ec, ProgID? ProgID: "<null>")); return -1; }
int loServerUnregister(const GUID *CLSID_Svr, const char *ProgID) { char sStr[256]; char sIID [40]; int offs; LONG errs = ERROR_INVALID_PARAMETER, ec = 0; IIDtoStr (sIID, CLSID_Svr); if (!ProgID || !*ProgID) goto SetErr; UL_TRACE((LOGID, "loUnRegisterServer(%s)", ProgID)); manageOPCDAcat(CLSID_Svr, -1); offs = sprintf(sStr, "%s\\", ProgID); strcpy(sStr + offs, "CurrentVersion"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "OPC\\Vendor"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "OPC"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "CLSID"); errs = RegDeleteKey (HKEY_CLASSES_ROOT, sStr); if (ERROR_SUCCESS != (ec = RegDeleteKey (HKEY_CLASSES_ROOT, ProgID))) { if (ERROR_SUCCESS == errs) errs = ec; UL_NOTICE((LOGID, "loUnRegisterServer(%s) can't remove HKCR:%s", ProgID, ProgID)); } offs = sprintf(sStr, "AppID\\%s\\", sIID); strcpy(sStr + offs, "LocalService"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "ServiceParameters"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); sStr[offs - 1] = 0; if (ERROR_SUCCESS != (ec = RegDeleteKey (HKEY_CLASSES_ROOT, sStr))) { if (ERROR_SUCCESS == errs) errs = ec; UL_NOTICE((LOGID, "loUnRegisterServer(%s) can't remove %s", ProgID, sStr)); } offs = sprintf(sStr, "CLSID\\%s\\", sIID); IIDtoStr(sIID, &CATID_OPCDAServer10); sprintf(sStr + offs, "Implemented Categories\\%s", sIID); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); IIDtoStr(sIID, &CATID_OPCDAServer20); sprintf(sStr + offs, "Implemented Categories\\%s", sIID); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "Implemented Categories"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "InprocServer32\\ThreadingModel"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "InprocServer32"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "LocalServer32"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "InprocHandler32"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "ProgID"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); strcpy(sStr + offs, "AppID"); RegDeleteKey (HKEY_CLASSES_ROOT, sStr); sStr[offs - 1] = 0; if (ERROR_SUCCESS != (ec = RegDeleteKey (HKEY_CLASSES_ROOT, sStr))) { if (ERROR_SUCCESS == errs) errs = ec; UL_NOTICE((LOGID, "loUnRegisterServer(%s) can't remove %s", ProgID, sStr)); } SetErr: if (ERROR_SUCCESS != errs) { SetLastError(errs); UL_ERROR((LOGID, "%!l loServerUnRegister(%s) FAILED", errs, ProgID? ProgID: "<null>")); return -1; } return 0; }
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; }
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 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; }
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 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; }
lw_thrrettype loUpdatePipe(void *vse) { loService *se = (loService *)vse; if (!loIS_VALID(se)) { UL_ERROR((LOGID, "loUpdatePipe() prematurely terminated")); lw_RETURN; } UL_TRACE((LOGID, "loUpdatePipe() started...")); loThrControl_accept(&se->update_pipe); lw_mutex_lock(&se->update_pipe.lk); for(;; lw_conds_wait(&se->update_pipe.cond, &se->update_pipe.lk)) if (0 != se->update_pipe.tstate) { if (0 > se->update_pipe.tstate) break; /* terminate thread */ lw_mutex_unlock(&se->update_pipe.lk); lw_rw_wrlock(&se->lkPrim); lw_mutex_lock(&se->update_pipe.lk); if (0 > se->update_pipe.tstate) { lw_rw_unlock(&se->lkPrim); break; }/* terminate thread */ { /* do actual update here */ unsigned ii = se->lastused; loTagEntry *te = se->tags; loTagValue *ts = se->secondary; loTrid prim_changed = se->sec_trid; while(ii--) { te++; ts++; if (ts->tvTi) { if (ts->tvTi == loCH_TIMESTAMP) te->prim.tsTime = ts->tvState.tsTime; else { te->primChanged = prim_changed; te->prim = ts->tvState; #if LO_KEEP_OLD_CACHE { HRESULT hr; if (S_OK != (hr = VariantCopy(&te->primValue, &ts->tvValue))) { LO_E_BADTYPE_QUAL(hr, te->prim.tsError, te->prim.tsQuality); UL_WARNING((LOGID, "%!l loUpdatePipe(VariantCopy())", hr)); } } #else VariantClear(&te->primValue); te->primValue = ts->tvValue; VARIANTINIT(&ts->tvValue); #endif } ts->tvTi = 0; } } } se->prim_trid = se->sec_trid; #if 0 != LO_EV_TIMESTAMP if (se->ts_prim != se->ts_sec) { freeX(se->ts_prim); se->ts_prim = se->ts_sec; } memcpy(se->ts_prim, se->ts_prim + se->ts_size, se->ts_size * sizeof(FILETIME)); #endif lw_rw_unlock(&se->lkPrim); se->update_pipe.tstate = 0; lw_condb_broadcast(&se->lkTridWait); } loThrControl_finish(&se->update_pipe); lw_mutex_unlock(&se->update_pipe.lk); UL_NOTICE((LOGID, "loUpdatePipe() finished")); lw_RETURN; }
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; }
loEnumIface<BASE,ITEM,IFACE>::~loEnumIface() { UL_TRACE((LOGID, "loEnumIface::~%p", this)); destroy_list(); }
int loInternalServiceDestroy(loService *se) { int rv0, rv; unilog *log; UL_TRACE((LOGID, "loInternalServiceDestroy(%p)...", se)); if (!loIS_VALID(se)) { UL_ERROR((LOGID, "loInternalServiceDestroy(%p) illegal pointer", se)); return EBADF; } se->iam = 0; log = (unilog*)se->log; se->log = 0; rv = 0; if ((se->initphase & ifLKSEC) && (rv0 = loThrControl_destroy(&se->update_pipe)) && !rv) rv = rv0; if ((se->initphase & ifLKMGMT) && (rv0 = lw_rwlock_destroy(&se->lkMgmt)) && !rv) rv = rv0; if ((se->initphase & ifLKPRIM) && (rv0 = lw_rwlock_destroy(&se->lkPrim)) && !rv) rv = rv0; if ((se->initphase & ifLKDR) && (rv0 = lw_mutex_destroy(&se->lkDr)) && !rv) rv = rv0; if ((se->initphase & ifLKLIST) && (rv0 = lw_mutex_destroy(&se->lkList)) && !rv) rv = rv0; if ((se->initphase & ifTRWAIT) && (rv0 = lw_condb_destroy(&se->lkTridWait)) && !rv) rv = rv0; se->initphase = 0; /* cleanup the CACHE & ATTRIB */ if (se->secondary) loTagValue_clear(se->secondary, se->tag_count); if (se->tags) loTagEntry_clear(se->tags, se->tag_count); se->tag_count = 0; lo_proplist_clear(se); se->ts_size = 0; if (se->ts_prim != se->ts_sec && se->ts_sec) freeX(se->ts_sec); se->ts_sec = 0; if (se->ts_prim) freeX(se->ts_prim); se->ts_prim = 0; freeX(se); if (rv) UL_WARNING((LOGID, "%!e loDelete() finished", rv)); else UL_TRACE((LOGID, "loDelete() finished = %u", rv)); { #if 0 != LO_USE_MALLOCX // extern long mallocX_count; UL_WARNING((LOGID, "loDelete()::mallocX = %ld xobjref = %ld", mallocX_count, lo_X_objcount)); #endif mallocX_trap(); } if (log) unilog_Delete(log); return rv; }
int lo_rio_requests(LightOPCServer *cli) { loRequest *rq; loService *se = cli->se; while(rq = cli->q_req.req) { int operation = rq->operation; loTrid trid; if (loThrControl_outof01(&cli->async)) return -1; cli->q_req.req = rq->rq_next; if (operation & loRQ_OPER_IO) cli->q_req.metric_overload = 0; lw_mutex_unlock(&cli->async.lk); UL_TRACE((LOGID, "REQUEST Retreived %x / %x", operation, rq->upl.trqid)); switch(operation & (loRQ_OPER_MASK | loRQ_DEVICE)) { #if LO_USE_BOTHMODEL case loRQ_OP_ADVISE: { void *aconn = 0; if (rq->conn_stream) { rq->upl.master_err = CoGetInterfaceAndReleaseStream(rq->conn_stream, *rq->conn_iface, &aconn); rq->conn_stream = 0; } else rq->upl.master_err = S_OK; if (SUCCEEDED(rq->upl.master_err)) rq->upl.master_err = cli->sync_advise(operation, &aconn, rq->group_key); if (aconn) ((IUnknown*)aconn)->Release(); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else lo_req_free(rq); } break; case loRQ_OP_REMOVE_GROUP: rq->upl.master_err = cli->internalRemoveGroup(rq->group_key, operation & loRQ_OF_REMOVE_FORCE); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else lo_req_free(rq); break; #endif /********************************************/ case loRQ_OP_WRITE|loRQ_DEVICE: if (se->driver.ldWriteTags) { int rv; loLOCK_DRIVER(se); rv = se->driver.ldWriteTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, rq->upl.variant, rq->upl.errors, &rq->upl.master_err, rq->upl.rctx.cta.vc_lcid); loUNLOCK_DRIVER(se); if (rv == loDW_ALLDONE) { if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; } } // UL_ERROR((LOGID, "DEV WRITE failed")); case loRQ_OP_WRITE: rio_cache_write(se, &rq->upl); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; /********************************************/ case loRQ_OP_READ|loRQ_DEVICE: if (se->driver.ldReadTags /*&& !(cli->access_mode & (loAM_NOREAD_DEV | loAM_ERREAD_DEV))*/) { HRESULT m_err = rq->upl.master_err, m_qual = rq->upl.master_qual; loLOCK_DRIVER(se); trid = se->driver.ldReadTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, rq->upl.variant, rq->upl.quality, rq->upl.timestamp, rq->upl.errors, &m_err, &m_qual, rq->upl.vartype, rq->upl.rctx.cta.vc_lcid); loUNLOCK_DRIVER(se); if (loDR_STORED == trid) { if (S_OK != m_err) rq->upl.master_err = S_FALSE; if (S_OK != m_qual) rq->upl.master_qual = S_FALSE; if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; } else if (loDR_CACHED != trid) loTridWait(se, trid); } case loRQ_OP_READ: rio_cache_read(se, &rq->upl); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; /********************************************/ case loRQ_OP_REFRESH|loRQ_DEVICE: if (se->driver.ldReadTags /*&& !(cli->access_mode & (loAM_NOREAD_DEV | loAM_ERREAD_DEV))*/) { loLOCK_DRIVER(se); trid = se->driver.ldReadTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, 0, 0, 0, 0, 0, 0, 0, 0 /*rq->upl.variant, rq->upl.quality, rq->upl.timestamp, rq->upl.errors, &master_err, &master_qual, rq->upl.vartype, rq->upl.gr_lcid*/); loUNLOCK_DRIVER(se); if (loDR_CACHED != trid) loTridWait(se, trid); } case loRQ_OP_REFRESH: if (operation & loRQ_SYNC) UL_ERROR((LOGID, "SYNC REFRESH is invalid %x / %x", rq->operation, rq->upl.trqid)); rio_refresh(cli, rq); break; /********************************************/ case loRQ_OP_CANCEL: cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); break; /********************************************/ default: UL_ERROR((LOGID, "BAD REQUEST %x / %x", rq->operation, rq->upl.trqid)); lo_req_free(rq); break; } #if 0 if (rq) /*??*/ { if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { if (operation & loRQ_OPER_IO) cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } } #endif lw_mutex_lock(&cli->async.lk); } return 0; }
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::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::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; }