static void gmem_free(HGLOBAL *hg) { if (*hg && GlobalFree(*hg)) { UL_ERROR((LOGID, "%!L gmem_free(%X) FAILED", *hg)); } *hg = 0; }
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; }
static void StrToIID(GUID* iid, const char* str) { int data[8]; sscanf(str, "{%08X-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}", &iid->Data1, &iid->Data2, &iid->Data3, &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]); iid->Data4[0] = data[0]; iid->Data4[1] = data[1]; iid->Data4[2] = data[2]; iid->Data4[3] = data[3]; iid->Data4[4] = data[4]; iid->Data4[5] = data[5]; iid->Data4[6] = data[6]; iid->Data4[7] = data[7]; char b2[80]; IIDtoStr(b2, iid); if (stricmp(b2, str)) UL_ERROR((LOGID, "IID_CONV: %s -> %s", str, b2)); }
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); }
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); }
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; }
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 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; }
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 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; }
int lo_OnDataChange1(loUpdList *upl, OPCHANDLE hClient, unsigned cform, int with_time, IAdviseSink *ias, HGLOBAL *gmem, unsigned *hint_dsize) { HGLOBAL fakegmem = 0; unsigned hdrsize, totalsize, ihdr_size, datasize; unsigned ii, itcount = upl->used; loUpdList lup = *upl; ihdr_size = with_time? sizeof(OPCITEMHEADER1): sizeof(OPCITEMHEADER2); hdrsize = sizeof(OPCGROUPHEADER) + itcount * ihdr_size; datasize = 0; if (hint_dsize && *hint_dsize) datasize = *hint_dsize; else { for(ii = itcount; ii--;) { datasize += loVariantSize(&lup.variant[ii]); } if (hint_dsize) *hint_dsize = datasize; } totalsize = hdrsize + datasize; if (!gmem) gmem = &fakegmem; if (!gmem_realloc(gmem, totalsize)) { itcount = 0; hdrsize = sizeof(OPCGROUPHEADER); if (!gmem_realloc(gmem, hdrsize)) { UL_ERROR((LOGID, "%!L Trasaction %X ABORTED due gmem_alloc(%u)", lup.trqid, totalsize)); return -1; } UL_WARNING((LOGID, "%!L Trasaction %X Failed due gmem_alloc(%u)", lup.trqid, totalsize)); totalsize = hdrsize; lup.master_err = E_OUTOFMEMORY; } { char *glob, *glob0, *ihdr; OPCGROUPHEADER *gh; FILETIME faketime, *timest = &faketime; unsigned timest_inc = 0; glob = glob0 = (char*)GlobalLock(*gmem); gh = (OPCGROUPHEADER*)glob; ihdr = (char*)&gh[1]; glob += hdrsize; if (with_time) timest_inc = sizeof(OPCITEMHEADER1), timest = &((OPCITEMHEADER1*)ihdr)->ftTimeStampItem; gh->dwSize = totalsize; gh->dwItemCount = itcount; gh->hClientGroup = hClient; gh->dwTransactionID = lup.trqid; for(ii = 0; ii < itcount; ii++) { ((OPCITEMHEADER1*)ihdr)->wReserved = 0; ((OPCITEMHEADER1*)ihdr)->dwValueOffset = glob - glob0; ((OPCITEMHEADER1*)ihdr)->hClient = lup.opchandle[ii]; ((OPCITEMHEADER1*)ihdr)->wQuality = lup.quality[ii]; loVariantPack((void**)&glob, &lup.variant[ii]); *timest = lup.timestamp[ii]; timest = (FILETIME*)(((char*)timest) + timest_inc); ihdr += ihdr_size; } gh->hrStatus = lup.master_err != S_OK? lup.master_err: lup.master_qual; if ((unsigned)(glob - glob0) != totalsize) { UL_ERROR((LOGID, "Transaction:%X datasize mismatch %u %u", lup.trqid, glob - glob0, totalsize)); } GlobalUnlock(*gmem); } { STGMEDIUM stgm; FORMATETC form; form.cfFormat = cform; form.dwAspect = DVASPECT_CONTENT; form.ptd = NULL; form.tymed = TYMED_HGLOBAL; form.lindex = -1; stgm.tymed = TYMED_HGLOBAL; stgm.STGM_hGlobal = *gmem; stgm.pUnkForRelease = DUMMY_UNKNOWN; UL_DEBUG((LOGID, "OnDataChange1:%s-time(%u)...%p{ %X", with_time? "with": "without", itcount, ias, *gmem)); ias->OnDataChange(&form, &stgm); UL_DEBUG((LOGID, "OnDataChange()...}")); } gmem_free(&fakegmem); return FAILED(lup.master_err)? -1: 0; }
int lo_OnWriteComplete1(loUpdList *upl, OPCHANDLE hClient, unsigned cform, IAdviseSink *ias, HGLOBAL *gmem) { HGLOBAL fakegmem = 0; unsigned datasize; unsigned ii, itcount = upl->used; loUpdList lup = *upl; datasize = sizeof(OPCGROUPHEADERWRITE) + itcount * sizeof(OPCITEMHEADERWRITE); if (!gmem) gmem = &fakegmem; if (!gmem_realloc(gmem, datasize)) { itcount = 0; datasize = sizeof(OPCGROUPHEADERWRITE); if (!gmem_realloc(gmem, datasize)) { UL_ERROR((LOGID, "%!L Trasaction %X ABORTED due gmem_alloc(%u)", lup.trqid, datasize)); return -1; } UL_WARNING((LOGID, "%!L Trasaction %X Failed due gmem_alloc(%u)", lup.trqid, datasize)); lup.master_err = E_OUTOFMEMORY; } { OPCGROUPHEADERWRITE *gh; OPCITEMHEADERWRITE *ihdr; gh = (OPCGROUPHEADERWRITE*)GlobalLock(*gmem); ihdr = (OPCITEMHEADERWRITE*)&gh[1]; gh->dwItemCount = itcount; gh->hClientGroup = hClient; gh->dwTransactionID = lup.trqid; gh->hrStatus = lup.master_err; for(ii = 0; ii < itcount; ii++, ihdr++) { ihdr->hClient = lup.opchandle[ii]; ihdr->dwError = lup.errors[ii]; // UL_DEBUG((LOGID, "OnWriteComplete(%u : %X/%X)", itcount, ihdr->dwError, gh->hrStatus)); } if ((unsigned)((char*)ihdr - (char*)gh) != datasize) { UL_ERROR((LOGID, "Transaction:%X datasize mismatch %u %u", lup.trqid, (char*)ihdr - (char*)gh, datasize)); } UL_DEBUG((LOGID, "OnWriteComplete(%u : %X/%X)", itcount, gh->hrStatus, lup.master_err)); GlobalUnlock(*gmem); } { STGMEDIUM stgm; FORMATETC form; form.cfFormat = cform; form.dwAspect = DVASPECT_CONTENT; form.ptd = NULL; form.tymed = TYMED_HGLOBAL; form.lindex = -1; stgm.tymed = TYMED_HGLOBAL; stgm.STGM_hGlobal = *gmem; stgm.pUnkForRelease = DUMMY_UNKNOWN; ias->OnDataChange(&form, &stgm); UL_DEBUG((LOGID, "OnWriteComplete()...}")); } gmem_free(&fakegmem); return FAILED(lup.master_err)? -1: 0; }
int ZSDriver::WriteTags(const loCaller *ca, unsigned count, loTagPair taglist[], VARIANT values[], HRESULT error[], HRESULT *master, LCID lcid) { // A guard but unsafe if (!isKeepRunning || NULL == dataService) { return loDW_ALLDONE; } const ZSSerialProtocol::DataSetDef& dataDef = protocol->GetDataSetInfo(); unsigned fixed = dataDef.size(); const std::vector<ZSSerialSetting>& ports = protocol->GetPortSetting(); std::vector<unsigned> segments; segments.push_back(0); for (std::size_t i = 0; i < ports.size(); ++i) { unsigned temp = ports.at(i).stations.size() * fixed; segments.push_back(temp + segments.at(i)); } for (unsigned i = 0; i < count; ++i) { std::size_t whichPort = 0; unsigned drvIndex = reinterpret_cast<unsigned>(taglist[i].tpRt); for (; whichPort < segments.size() - 1; ++whichPort) { if (drvIndex < segments.at(whichPort + 1)) { break; // the port is matched } } if (segments.size() - 1 == whichPort) { continue; // no port is matched. Go to the next tag } unsigned short whichStation = (drvIndex - segments.at(whichPort)) / fixed; unsigned short index = (drvIndex - segments.at(whichPort)) % fixed; ZSSerialProtocol::DataSetDef::const_iterator iter = dataDef.begin(); std::advance(iter, index); _ASSERTE(iter != dataDef.end()); if (iter == dataDef.end()) { continue; // error, we do nothing, add log here. } // check whether the stations is enabled if (ZSSerialProtocol::ZS_DEV_DISABLED == ports.at(whichPort).stations.at(whichStation).second && protocol->GetFaultSignalDataIndex() != index) { continue; // the station is disabled, jump to the next tag. } HRESULT hr; CComVariant var = values[i]; { // write data or command boost::upgrade_lock<boost::shared_mutex> upLock(*rwMutex); boost::upgrade_to_unique_lock<boost::shared_mutex> uniLock(upLock); try { if (iter->first < ZSDRV_COMMON_CMD_START) // write data { ZSDataItem dataItem; dataItem.index = iter->first; if (iter->second.get<ZSSerialProtocol::ZS_DATA_TYPE_INDEX>()) { hr = var.ChangeType(VT_R8); _ASSERTE(S_OK == hr); if (S_OK != hr) { continue; // add log here } dataItem.variant = var.dblVal; } else { hr = var.ChangeType(VT_UI4); _ASSERTE(S_OK == hr); if (S_OK != hr) { continue; // add log here } dataItem.variant = var.uintVal; } serials->at(whichPort)->WriteData(dataItem, ports.at(whichPort).stations.at(whichStation).first); } else if (protocol->GetFaultSignalDataIndex() != index)// write the common command { hr = var.ChangeType(VT_UI4); _ASSERTE(S_OK == hr); if (S_OK != hr) { continue; // add log here } if (var.uintVal > 0) { serials->at(whichPort)->WriteCommand(iter->first, ports.at(whichPort).stations.at(whichStation).first); } else { continue; } } else // check whether the restore the device healthy status is set. { hr = var.ChangeType(VT_UI4); _ASSERTE(S_OK == hr); if (S_OK == hr && 0 == var.uintVal) { protocol->UpdateStationStatus(whichPort, whichStation, ZSSerialProtocol::ZS_DEV_OK); } else { continue; } } } catch (timeout_exception& e) { UL_ERROR((Log::Instance().get(), 0, "WriteData() error: %s", e.what())); } catch (boost::system::system_error& e) { UL_ERROR((Log::Instance().get(), 0, "WriteData() error: %s", e.what())); } } FILETIME ft; GetSystemTimeAsFileTime(&ft); tags->at(drvIndex).tvState.tsTime = ft; tags->at(drvIndex).tvState.tsQuality = OPC_QUALITY_GOOD; tags->at(drvIndex).tvValue = var; { boost::lock_guard<boost::mutex> guard(*mutex); loCacheUpdate(dataService.get(), 1, &(tags->at(drvIndex)), 0); } } return loDW_ALLDONE; }
// Refresh data worker function void ZSDriver::RefreshDataTask(boost::shared_ptr<loService> service, unsigned serialIndex) { boost::shared_ptr<ZSSerial> serial = serials->at(serialIndex); const std::vector<std::pair<unsigned char, unsigned short> >& stations = protocol->GetPortSetting().at(serialIndex).stations; std::string devName = protocol->GetPortSetting().at(serialIndex).devName; std::size_t gpOneCount = protocol->GetReadDataCmd().at(0).info.size(); std::size_t gpTwoCount = protocol->GetReadDataCmd().at(1).info.size(); std::size_t dataTotalCount = protocol->GetDataSetInfo().size(); unsigned refreshBase = protocol->GetReadDataCmd().at(ZSDRV_READ_DATA_GROUP_I).refresh; refreshBase = (0 == refreshBase) ? REFRESH_MIN : refreshBase; // at lease REFRESH_MIN unsigned interval = protocol->GetReadDataCmd().at(ZSDRV_READ_DATA_GROUP_II).refresh / refreshBase; interval = // at least ZSDRV_READDATA_GROUP_SWITCH_INTERVAL (interval < ZSDRV_READDATA_GROUP_SWITCH_INTERVAL) ? ZSDRV_READDATA_GROUP_SWITCH_INTERVAL : interval; std::size_t grpStartOffset = 0; for (std::size_t i = 0; i < serialIndex; i++) { grpStartOffset += dataTotalCount * protocol->GetPortSetting().at(i).stations.size(); } while (isKeepRunning) { for (std::size_t i = 0; i < stations.size(); ++i) { // the station is disabled if (ZSSerialProtocol::ZS_DEV_DISABLED == stations.at(i).second) { ::Sleep(REFRESH_MIN); continue; } unsigned dataGroup; if (interval > 0) { dataGroup = ZSDRV_READ_DATA_GROUP_I; } else { dataGroup = ZSDRV_READ_DATA_GROUP_II; } try // refresh data { RefreshDataSubJob(service, serial, stations.at(i).first, dataGroup, grpStartOffset + i * dataTotalCount); ::Sleep(refreshBase); protocol->UpdateStationStatus(serialIndex, i, ZSSerialProtocol::ZS_DEV_OK); // restore } catch (timeout_exception& e) { NotifyDevFault(service, serialIndex, i, grpStartOffset + i * dataTotalCount); UL_ERROR((Log::Instance().get(), 0, "ReadData error: %s - %s", devName.c_str(), e.what() )); } catch (boost::system::system_error& e) { NotifyDevFault(service, serialIndex, i, grpStartOffset + i * dataTotalCount); UL_ERROR((Log::Instance().get(), 0, "ReadData error: %s - %s", devName.c_str(), e.what() )); } } if (0 == interval) { interval = ZSDRV_READDATA_GROUP_SWITCH_INTERVAL; } else { interval--; } } }