PageRenderTime 64ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 0ms

/LightOPC/src/itemprop.cpp

https://gitlab.com/fheinemann/opc_ads
C++ | 326 lines | 263 code | 45 blank | 18 comment | 74 complexity | 72af48d1c9a69f7f78d45b3b0c651add MD5 | raw file
  1. /**************************************************************************
  2. * *
  3. * Light OPC Server development library *
  4. * *
  5. * Copyright (c) 2001 Timofei Bondarenko *
  6. *
  7. ItemProperties support
  8. **************************************************************************/
  9. #include "privopc.h"
  10. #include "proplist.h"
  11. #include <opcerror.h>
  12. /***************************/
  13. static HRESULT lo_basic_props(int *lockst, loClient *cli, loTagEntry *te, DWORD propid, VARIANT *var)
  14. {
  15. HRESULT hr = S_OK;
  16. if (VT_EMPTY != V_VT(var)) VariantClear(var);
  17. if (VT_EMPTY == taVTYPE(&te->attr)) return OPC_E_INVALID_PID;
  18. switch(propid)
  19. {
  20. case 1: /* "Item Canonical DataType" */
  21. V_I2(var) = taVTYPE(&te->attr);
  22. V_VT(var) = VT_I2;
  23. break;
  24. case 5: /* "Item Access Rights" */
  25. V_I4(var) = te->attr.taRights &
  26. ((cli->access_mode & loAM_RDONLY_BROWSE)? (loOPC_RIGHTS & ~OPC_WRITEABLE)
  27. : loOPC_RIGHTS);
  28. V_VT(var) = VT_I4;
  29. break;
  30. case 6: /* "Server Scan Rate" */
  31. V_R4(var) = (float)cli->se->driver.ldRefreshRate_min;
  32. V_VT(var) = VT_R4;
  33. break;
  34. case 7: /* "Item EU Type" */
  35. V_I4(var) = te->attr.taDetail->tdEUtype;
  36. V_VT(var) = VT_I4;V_I4(var) = 2;
  37. break;
  38. case 8: /* "Item EU Info" */
  39. if ((te->attr.taFlags & loTF_CONVERT) &&
  40. te->attr.taDetail->tdEUtype == OPC_ENUMERATED)
  41. hr = lo_conv_enum(&cli->ctxt, var, &te->attr, NULL);
  42. else hr = VariantCopy(var, &te->attr.taDetail->tdEUinfo);
  43. break;
  44. case 2: /* "Item Value" */
  45. case 3: /* "Item Quality" */
  46. case 4: /* "Item Timestamp" */
  47. if (!lockst) lw_rw_rdlock(&cli->se->lkPrim);
  48. else if (!*lockst) *lockst = 1, lw_rw_rdlock(&cli->se->lkPrim);
  49. switch(propid)
  50. {
  51. case 2: /* "Item Value" */
  52. hr = (te->attr.taRights & OPC_READABLE)? VariantCopy(var, &te->primValue)
  53. : OPC_E_BADRIGHTS;
  54. break;
  55. case 3: /* "Item Quality" */
  56. V_I2(var) = (WORD)te->prim.tsQuality;
  57. V_VT(var) = VT_I2;
  58. break;
  59. case 4: /* "Item Timestamp" */
  60. V_DATE(var) = lo_filetime_to_variant(&te->prim.tsTime);
  61. V_VT(var) = VT_DATE;
  62. /* Anyway more accurate than SystemTimeToVariantTime(); */
  63. break;
  64. }
  65. if (!lockst) lw_rw_unlock(&cli->se->lkPrim);
  66. break;
  67. default:
  68. hr = OPC_E_INVALID_PID;
  69. }
  70. return hr;
  71. }
  72. /*************************************************************************/
  73. STDMETHODIMP LightOPCServer::GetItemProperties(
  74. /* [in] */ LPWSTR szItemID,
  75. /* [in] */ DWORD dwCount,
  76. /* [size_is][in] */ DWORD *pdwPropertyIDs,
  77. /* [size_is][size_is][out] */ VARIANT **ppvData,
  78. /* [size_is][size_is][out] */ HRESULT **ppErrors)
  79. {
  80. HRESULT hr = S_OK;
  81. HRESULT *errs = 0;
  82. VARIANT *vdata = 0;
  83. loTagPair tgp;
  84. LO_CHECK_STATEz2("GetItemProperties", ppvData, ppErrors);
  85. if (!szItemID || !dwCount || !pdwPropertyIDs || !ppvData || !ppErrors)
  86. { hr = E_INVALIDARG; goto Return; }
  87. if (!(errs = (HRESULT*)loComAlloc(sizeof(HRESULT) * dwCount)) ||
  88. !(vdata = (VARIANT*)loComAlloc(sizeof(VARIANT) * dwCount)))
  89. { hr = E_OUTOFMEMORY; goto Return; }
  90. loVariant_init(vdata, dwCount);
  91. // memset(errs, 0, sizeof(HRESULT) * dwCount);
  92. memset(&tgp, 0, sizeof(tgp));
  93. lw_rw_rdlock(&se->lkMgmt);
  94. if (tgp.tpTi = loFindItemID(se, &ctxt.cactx, 1, szItemID, 0,
  95. VT_EMPTY, loDAIG_IPROPGET, 0, &hr))
  96. {
  97. unsigned ii;
  98. int unlk = 0;
  99. loTagEntry *te = &se->tags[tgp.tpTi];
  100. loRelName rn;
  101. rn.se = se;
  102. rn.cactx = &ctxt.cactx;
  103. rn.locked = 1;
  104. loStringBuf_init(&rn.sb);
  105. loBaseName_init(&rn.bn, &te->attr, se->branch_sep);
  106. // tgp.tpTi = ti;
  107. tgp.tpRt = te->attr.taRt;
  108. for(ii = 0; ii < dwCount; ii++)
  109. {
  110. HRESULT lhr = OPC_E_INVALID_PID;
  111. unsigned pli;
  112. for(pli = 0; pli < loPROPLIST_MAX; pli++)
  113. {
  114. loProperty **prr;
  115. if (prr = lo_prop_find(&se->proplist[te->attr.taPropList[pli]],
  116. pdwPropertyIDs[ii]))
  117. {
  118. loProperty *pr = *prr;
  119. if (VT_EMPTY != V_VT(&pr->prValue))
  120. {
  121. lhr = VariantCopy(&vdata[ii], &pr->prValue);
  122. }
  123. else if (pr->prPath && *pr->prPath)
  124. {
  125. loTagId tti = lo_relative_tag(&rn, pr->prPath, loDAIG_IPROPRGET);
  126. lhr = rn.err;
  127. if (tti)
  128. {
  129. if (!unlk) { unlk = 1; lw_rw_rdlock(&se->lkPrim); }
  130. #if 0
  131. if (!(se->tags[tti].attr.taRights & OPC_READABLE)) lhr = OPC_E_BADRIGHTS;
  132. else
  133. #endif
  134. lhr = VariantCopy(&vdata[ii], &se->tags[tti].primValue);
  135. }
  136. else if (E_OUTOFMEMORY != lhr) lhr = E_FAIL;
  137. }
  138. else lhr = OPC_E_INVALID_PID;
  139. goto Cont;
  140. }
  141. }/* end of for(pli...) */
  142. lhr = lo_basic_props(&unlk, this, te, pdwPropertyIDs[ii], &vdata[ii]);
  143. Cont:
  144. if (S_OK != (errs[ii] = lhr)) hr = S_FALSE;
  145. } /* end of for(...dwCount) */
  146. if (unlk) lw_rw_unlock(&se->lkPrim);
  147. loStringBuf_clear(&rn.sb);
  148. }
  149. lw_rw_unlock(&se->lkMgmt);
  150. if (se->driver.ldGetItemProperties && ( SUCCEEDED(hr)
  151. || OPC_E_UNKNOWNITEMID == hr
  152. || OPC_E_INVALIDITEMID == hr) )
  153. {
  154. LCID locale = 0;
  155. GetLocaleID(&locale);
  156. hr = se->driver.ldGetItemProperties(&ctxt.cactx, &tgp,
  157. szItemID, dwCount, pdwPropertyIDs, &vdata, &errs, locale);
  158. }
  159. Return:
  160. if (FAILED(hr))
  161. {
  162. if (errs)
  163. { loComFree(errs); errs = 0; }
  164. if (vdata)
  165. {
  166. loVariant_clear(vdata, dwCount);
  167. loComFree(vdata); vdata = 0;
  168. }
  169. UL_INFO((LOG_SR("GetItemProperties(%ls, %u) = %s"),
  170. loWnul(szItemID), dwCount, loStrError(hr)));
  171. }
  172. else
  173. {
  174. *ppErrors = errs, errs = 0;
  175. *ppvData = vdata, vdata = 0;
  176. UL_NOTICE((LOG_SR("GetItemProperties(%ls, %u) ti:%u = Ok"),
  177. loWnul(szItemID), dwCount, tgp.tpTi));
  178. }
  179. LO_FINISH();
  180. return hr;
  181. }
  182. /***********************************************************************************/
  183. STDMETHODIMP LightOPCServer::LookupItemIDs(
  184. /* [in] */ LPWSTR szItemID,
  185. /* [in] */ DWORD dwCount,
  186. /* [size_is][in] */ DWORD *pdwPropertyIDs,
  187. /* [size_is][size_is][string][out] */ LPWSTR **ppszNewItemIDs,
  188. /* [size_is][size_is][out] */ HRESULT **ppErrors)
  189. {
  190. HRESULT hr = S_OK;
  191. HRESULT *errs = 0;
  192. LPWSTR *itemids = 0;
  193. loTagPair tgp;
  194. LO_CHECK_STATEz2("LookupItemIDs", ppszNewItemIDs, ppErrors);
  195. if (!szItemID || !dwCount || !pdwPropertyIDs || !ppszNewItemIDs || !ppErrors)
  196. { hr = E_INVALIDARG; goto Return; }
  197. if (!(errs = (HRESULT*)loComAlloc(sizeof(HRESULT) * dwCount)) ||
  198. !(itemids = (LPWSTR*)loComAlloc(sizeof(LPWSTR) * dwCount)))
  199. { hr = E_OUTOFMEMORY; goto Return; }
  200. memset(itemids, 0, sizeof(HRESULT) * dwCount);
  201. // memset(errs, 0, sizeof(HRESULT) * dwCount);
  202. memset(&tgp, 0, sizeof(tgp));
  203. lw_rw_rdlock(&se->lkMgmt);
  204. if (tgp.tpTi = loFindItemID(se, &ctxt.cactx, 1, szItemID, 0,
  205. VT_EMPTY, loDAIG_IPROPLOOKUP, 0, &hr))
  206. {
  207. unsigned ii;
  208. loTagAttrib *ta = &se->tags[tgp.tpTi].attr;
  209. loBaseName base;
  210. loStringBuf sb;
  211. loStringBuf_init(&sb);
  212. loBaseName_init(&base, ta, se->branch_sep);
  213. tgp.tpRt = ta->taRt;
  214. for(ii = 0; ii < dwCount; ii++)
  215. {
  216. const loWchar *itid = L""; /* no NULL pointers */
  217. HRESULT lhr = OPC_E_INVALID_PID;
  218. unsigned pli;
  219. for(pli = 0; pli < loPROPLIST_MAX; pli++)
  220. {
  221. loProperty **prr;
  222. if (prr = lo_prop_find(&se->proplist[ta->taPropList[pli]],
  223. pdwPropertyIDs[ii]))
  224. {
  225. loProperty *pr = *prr;
  226. if (!pr->prPath || !*pr->prPath)
  227. {
  228. hr = S_FALSE;
  229. lhr = VT_EMPTY == V_VT(&pr->prValue)? OPC_E_INVALID_PID: E_FAIL;
  230. /* A disabled property / No ItemID defined */
  231. }
  232. else
  233. {
  234. itid = lo_relative_name(&sb, &base, pr->prPath);
  235. lhr = S_OK;
  236. }
  237. goto Cont;
  238. }
  239. }
  240. hr = S_FALSE;
  241. #if 0
  242. /* What's exactly required by the standard? */
  243. if (pdwPropertyIDs[ii] >= 1 && pdwPropertyIDs[ii] <= 6 &&
  244. VT_EMPTY != taVTYPE(&te->attr)) lhr = E_FAIL;
  245. #endif
  246. Cont:
  247. errs[ii] = lhr;
  248. if (!itid || !(itemids[ii] = loComWstrdup(itid)))
  249. {
  250. hr = E_OUTOFMEMORY;
  251. break;
  252. }
  253. } /* end of for(pli...) */
  254. loStringBuf_clear(&sb);
  255. }
  256. lw_rw_unlock(&se->lkMgmt);
  257. if (se->driver.ldLookupItemIDs && (SUCCEEDED(hr)
  258. || OPC_E_UNKNOWNITEMID == hr
  259. || OPC_E_INVALIDITEMID == hr) )
  260. hr = se->driver.ldLookupItemIDs(&ctxt.cactx, &tgp,
  261. szItemID, dwCount, pdwPropertyIDs, &itemids, &errs);
  262. Return:
  263. if (FAILED(hr))
  264. {
  265. if (errs) loComFree(errs), errs = 0;
  266. if (itemids) loComFree_LPWSTR(itemids, dwCount), itemids = 0;
  267. UL_INFO((LOG_SR("LookupItemIDs(%ls, %u) = %s"),
  268. loWnul(szItemID), dwCount, loStrError(hr)));
  269. }
  270. else
  271. {
  272. if (ppErrors) *ppErrors = errs, errs = 0;
  273. else loComFree(errs);
  274. *ppszNewItemIDs = itemids, itemids = 0;
  275. UL_NOTICE((LOG_SR("LookupItemIDs(%ls, %u) ti:%u = Ok"),
  276. loWnul(szItemID), dwCount, tgp.tpTi));
  277. }
  278. LO_FINISH();
  279. return hr;
  280. }
  281. /* end of itemprop.cpp */