Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1220 lines
35 KiB

  1. /*****************************************************************************\
  2. * MODULE: olesnmp.cpp
  3. *
  4. * PURPOSE: Implementation of COM interface for SNMP
  5. *
  6. * Copyright (C) 1997-1998 Microsoft Corporation
  7. *
  8. * History:
  9. *
  10. * 08/16/97 paulmo Created
  11. * 09/12/97 weihaic Moved to oleprn.dll
  12. *
  13. \*****************************************************************************/
  14. #include "stdafx.h"
  15. #include "oleprn.h"
  16. #include "olesnmp.h"
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CSNMP
  19. CSNMP::
  20. CSNMP(
  21. VOID
  22. )
  23. {
  24. m_SNMPSession = NULL;
  25. }
  26. CSNMP::
  27. ~CSNMP(
  28. VOID
  29. )
  30. {
  31. if (m_SNMPSession != NULL) SnmpMgrClose(m_SNMPSession);
  32. }
  33. /*****************************************************************************\
  34. * Function: Open
  35. *
  36. * PURPOSE: COM wrapper for SnmpMgrOpen
  37. *
  38. * ARGUMENTS:
  39. *
  40. * bstrHost: Host name or Server Name
  41. * bstrCommunity: Community Name
  42. * varRetry: Retry times [optional in VB]
  43. * varTimeOut: Time out Value (in millisecond) [optional in VB]
  44. *
  45. * RETURN VALUE:
  46. * S_OK: If succeed.
  47. * E_INVALIDARG: Invalid argument. It occurs when either varRetry or varTimeOut
  48. * can not be converted to a short integer.
  49. * E_FAIL: If SNMPMgrOpen fails
  50. *
  51. *
  52. \*****************************************************************************/
  53. STDMETHODIMP
  54. CSNMP::
  55. Open(
  56. IN BSTR bstrHost,
  57. IN BSTR bstrCommunity,
  58. IN VARIANT varRetry,
  59. IN VARIANT varTimeOut
  60. )
  61. {
  62. const INT iDefaultRetry = 5;
  63. const INT iDefaultTimeOut = 5000;
  64. INT iRetry;
  65. INT iTimeOut;
  66. LPSTR pAnsiHost = NULL;
  67. LPSTR pAnsiCommunity = NULL;
  68. HRESULT hr = E_FAIL;
  69. // To prevent a second open
  70. if (m_SNMPSession != NULL){
  71. SnmpMgrClose(m_SNMPSession);
  72. m_SNMPSession = NULL;
  73. }
  74. if (varRetry.vt == VT_ERROR) {
  75. iRetry = iDefaultRetry;
  76. }
  77. else {
  78. VARIANT varTemp;
  79. VariantInit (&varTemp);
  80. hr = VariantChangeType (&varTemp, &varRetry, 0, VT_I2);
  81. if (FAILED (hr))
  82. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  83. iRetry = varTemp.iVal;
  84. }
  85. if (varTimeOut.vt == VT_ERROR) {
  86. iTimeOut = iDefaultTimeOut;
  87. }
  88. else {
  89. VARIANT varTemp;
  90. VariantInit (&varTemp);
  91. hr = VariantChangeType (&varTemp, &varTimeOut, 0, VT_I2);
  92. if (FAILED (hr))
  93. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  94. iTimeOut = varTemp.iVal;
  95. }
  96. pAnsiHost = MakeNarrow(bstrHost);
  97. pAnsiCommunity = MakeNarrow(bstrCommunity);
  98. if (pAnsiHost && pAnsiCommunity) {
  99. __try {
  100. m_SNMPSession = SnmpMgrOpen(pAnsiHost, pAnsiCommunity, iTimeOut, iRetry);
  101. } __except(1) {
  102. hr = E_FAIL;
  103. }
  104. }
  105. LocalFree(pAnsiHost);
  106. LocalFree(pAnsiCommunity);
  107. if (m_SNMPSession == NULL)
  108. return Error(IDS_FAILED_OPEN_SNMP, IID_ISNMP, E_FAIL);
  109. return S_OK;
  110. }
  111. /*****************************************************************************\
  112. * Function: Get
  113. *
  114. * PURPOSE: Get a value of a SNMP oid
  115. *
  116. * ARGUMENTS:
  117. *
  118. * bstrOID: The SNMP Oid in BSTR
  119. * pvarValue: The return value for the corresponding Oid
  120. *
  121. * RETURN VALUE:
  122. * S_OK: If succeed.
  123. * E_INVALIDARG: Invalid oid.
  124. * E_FAIL: If Open method has not been called before
  125. * E_OUTOFMEMORY: Out of memory
  126. * other: Returns the last error set by SnmpMgrRequest
  127. *
  128. \*****************************************************************************/
  129. STDMETHODIMP
  130. CSNMP::
  131. Get(
  132. IN BSTR bstrOID,
  133. OUT VARIANT *pvarValue
  134. )
  135. {
  136. RFC1157VarBindList rfcVarList = {NULL, 0};
  137. AsnInteger asniErrorStatus;
  138. AsnInteger asniErrorIndex;
  139. HRESULT hr = E_FAIL;
  140. if (m_SNMPSession == NULL)
  141. return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
  142. if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList))){
  143. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  144. goto Cleanup;
  145. }
  146. if (!SnmpMgrRequest(m_SNMPSession,
  147. ASN_RFC1157_GETREQUEST,
  148. &rfcVarList,
  149. &asniErrorStatus,
  150. &asniErrorIndex)) {
  151. hr = SetWinSnmpApiError (GetLastError ());
  152. goto Cleanup;
  153. }
  154. if (asniErrorStatus > 0) {
  155. hr = SetSnmpScriptError(asniErrorStatus);
  156. goto Cleanup;
  157. }
  158. hr = RFC1157ToVariant(pvarValue, &rfcVarList.list[0]);
  159. Cleanup:
  160. SnmpUtilVarBindListFree(&rfcVarList);
  161. return hr;
  162. }
  163. /*****************************************************************************\
  164. * Function: GetAsByte
  165. *
  166. * PURPOSE: Get a value of a SNMP oid as an integer
  167. *
  168. * ARGUMENTS:
  169. *
  170. * bstrOID: The SNMP Oid in BSTR
  171. * puValue: The return value for the corresponding Oid
  172. *
  173. * RETURN VALUE:
  174. * S_OK: If succeed.
  175. * E_INVALIDARG: Invalid oid.
  176. * E_FAIL: If Open method has not been called before
  177. * E_OUTOFMEMORY: Out of memory
  178. * other: Returns the last error set by SnmpMgrRequest
  179. *
  180. \*****************************************************************************/
  181. STDMETHODIMP
  182. CSNMP::
  183. GetAsByte(
  184. IN BSTR bstrOID,
  185. OUT PUINT puValue
  186. )
  187. {
  188. RFC1157VarBindList rfcVarList = {NULL, 0};
  189. AsnInteger asniErrorStatus;
  190. AsnInteger asniErrorIndex;
  191. HRESULT hr = E_FAIL;
  192. if (m_SNMPSession == NULL)
  193. return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
  194. if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList))){
  195. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  196. goto Cleanup;
  197. }
  198. if (!SnmpMgrRequest(m_SNMPSession,
  199. ASN_RFC1157_GETREQUEST,
  200. &rfcVarList,
  201. &asniErrorStatus,
  202. &asniErrorIndex)) {
  203. hr = SetWinSnmpApiError (GetLastError ());
  204. goto Cleanup;
  205. }
  206. if (asniErrorStatus > 0) {
  207. hr = SetSnmpScriptError(asniErrorStatus);
  208. goto Cleanup;
  209. }
  210. hr = RFC1157ToUInt(puValue, &rfcVarList.list[0]);
  211. Cleanup:
  212. SnmpUtilVarBindListFree(&rfcVarList);
  213. return hr;
  214. }
  215. /*****************************************************************************\
  216. * Function: GetList
  217. *
  218. * PURPOSE: Get a list of a SNMP oids
  219. *
  220. * ARGUMENTS:
  221. *
  222. * pvarList: The array of SNMP Oids. The type must be a 1D array of BSTRs
  223. * pvarValue: The return value for the corresponding Oids, it is 1D array
  224. * of Variants
  225. *
  226. * RETURN VALUE:
  227. * S_OK: If succeed.
  228. * E_INVALIDARG: Invalid oid or the type of the variant is not a 1D array
  229. * E_FAIL: If Open method has not been called before
  230. * E_OUTOFMEMORY: Out of memory
  231. * other: Returns the last error set by SnmpMgrRequest
  232. *
  233. \*****************************************************************************/
  234. STDMETHODIMP
  235. CSNMP::
  236. GetList(
  237. IN VARIANT *pvarList,
  238. OUT VARIANT *pvarValue
  239. )
  240. {
  241. RFC1157VarBindList rfcVarList = {NULL, 0};
  242. AsnInteger asniErrorStatus;
  243. AsnInteger asniErrorIndex;
  244. HRESULT hr = E_FAIL;
  245. SAFEARRAY *psa,*psaOut = NULL;
  246. SAFEARRAYBOUND rgsabound[1];
  247. long lbound, ubound, half, step;
  248. VARIANT var;
  249. BOOL bFound;
  250. BOOL bTooBig;
  251. // Check if Open Method has been called
  252. if (m_SNMPSession == NULL)
  253. return (Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL));
  254. // Validate the input variable
  255. if (!(pvarList->vt & VT_ARRAY))
  256. return (Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG));
  257. if (pvarList->vt & VT_BYREF)
  258. psa = *(pvarList->pparray);
  259. else
  260. psa = pvarList->parray;
  261. if (SafeArrayGetDim(psa)!=1)
  262. return (Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG));
  263. // Get the array boundary
  264. SafeArrayGetLBound(psa, 1, &lbound);
  265. SafeArrayGetUBound(psa, 1, &ubound);
  266. VariantInit(pvarValue);
  267. VariantInit(&var);
  268. // Alloc the destination array
  269. rgsabound[0].lLbound = 0;
  270. rgsabound[0].cElements = ubound - lbound + 1;
  271. if (! (psaOut = SafeArrayCreate(VT_VARIANT, 1, rgsabound))) {
  272. hr = Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  273. goto Cleanup;
  274. }
  275. // Try to determine the size of data we can put into one call
  276. half = ubound;
  277. bFound = FALSE;
  278. while (!bFound) {
  279. bTooBig = FALSE;
  280. // Convert items of the array to rfcVarList
  281. hr = VarToRfcVarList (lbound, half, psa, &rfcVarList);
  282. if (FAILED (hr))
  283. goto Cleanup;
  284. if (! SnmpMgrRequest(m_SNMPSession,
  285. ASN_RFC1157_GETREQUEST,
  286. &rfcVarList,
  287. &asniErrorStatus,
  288. &asniErrorIndex)) {
  289. if (GetLastError() != ERROR_NOT_ENOUGH_MEMORY)
  290. {
  291. // SNMP call fails. Setup error and return
  292. hr = SetWinSnmpApiError (GetLastError ());
  293. goto Cleanup;
  294. }
  295. else
  296. bTooBig = TRUE;
  297. }
  298. if (asniErrorStatus > 0) {
  299. // SNMP call succeeds but the returned status if wrong
  300. if (asniErrorStatus != SNMP_ERRORSTATUS_TOOBIG) {
  301. // Other errors occur in the call, setup error and return
  302. hr = SetSnmpScriptError(asniErrorStatus);
  303. goto Cleanup;
  304. }
  305. else
  306. bTooBig = TRUE;
  307. }
  308. if (bTooBig){
  309. // The size of input is too big, reduce it again
  310. if (half - lbound < 2) {
  311. // Something must be wrong, quit
  312. hr = SetSnmpScriptError(asniErrorStatus);
  313. goto Cleanup;
  314. }
  315. else {
  316. // Divdie the size by 2
  317. half = (lbound + half) / 2;
  318. }
  319. }
  320. else {
  321. // We've found the proper steps and also got the first portion
  322. // Save them to the destination safe array psaout
  323. hr = RfcToVarList (lbound, &rfcVarList, psaOut);
  324. if (FAILED (hr))
  325. goto Cleanup;
  326. bFound = TRUE;
  327. }
  328. SnmpUtilVarBindListFree(&rfcVarList);
  329. rfcVarList.list = NULL;
  330. rfcVarList.len = 0;
  331. }
  332. step = half - lbound;
  333. for (lbound = half + 1; lbound <= ubound; lbound += step) {
  334. half = lbound + step;
  335. if (half > ubound)
  336. half = ubound;
  337. hr = VarToRfcVarList (lbound, half, psa, &rfcVarList);
  338. if (FAILED (hr))
  339. goto Cleanup;
  340. if (! SnmpMgrRequest(m_SNMPSession,
  341. ASN_RFC1157_GETREQUEST,
  342. &rfcVarList,
  343. &asniErrorStatus,
  344. &asniErrorIndex)) {
  345. // SNMP call fails. Setup error and return
  346. hr = SetWinSnmpApiError (GetLastError ());
  347. goto Cleanup;
  348. }
  349. if (asniErrorStatus > 0) {
  350. // SNMP call succeeds but the returned status if wrong
  351. hr = SetSnmpScriptError(asniErrorStatus);
  352. goto Cleanup;
  353. }
  354. // Everything is OK
  355. hr = RfcToVarList (lbound, &rfcVarList, psaOut);
  356. if (FAILED (hr))
  357. goto Cleanup;
  358. SnmpUtilVarBindListFree(&rfcVarList);
  359. rfcVarList.list = NULL;
  360. rfcVarList.len = 0;
  361. }
  362. VariantInit(pvarValue);
  363. pvarValue->vt = VT_ARRAY|VT_VARIANT;
  364. pvarValue->parray = psaOut;
  365. hr = S_OK;
  366. return hr;
  367. Cleanup:
  368. if (rfcVarList.len > 0)
  369. SnmpUtilVarBindListFree(&rfcVarList);
  370. if (psaOut)
  371. SafeArrayDestroy (psaOut);
  372. return hr;
  373. }
  374. /*****************************************************************************\
  375. * Function: GetTree
  376. *
  377. * PURPOSE: It walks through SNMP oids
  378. *
  379. * ARGUMENTS:
  380. *
  381. * bstrTree: The array of SNMP Oids. The type must be a 1D array of BSTRs
  382. * pvarValue: The return value for the corresponding Oids, it is 1D array
  383. * of Variants
  384. *
  385. * RETURN VALUE:
  386. * S_OK: If succeed.
  387. * E_INVALIDARG: Invalid oid.
  388. * E_FAIL: If Open method has not been called before
  389. * E_OUTOFMEMORY: Out of memory
  390. * other: Returns the last error set by SnmpMgrRequest
  391. *
  392. \*****************************************************************************/
  393. STDMETHODIMP
  394. CSNMP::
  395. GetTree(
  396. IN BSTR bstrTree,
  397. OUT VARIANT *pvarValue
  398. )
  399. {
  400. RFC1157VarBindList rfcVarList = {NULL, 0};
  401. VARIANT v;
  402. AsnInteger asniErrorStatus;
  403. AsnInteger asniErrorIndex;
  404. AsnObjectIdentifier asnRootOid;
  405. AsnObjectIdentifier asnTmpOid;
  406. HRESULT hr = E_FAIL;
  407. SAFEARRAY *psa = NULL;
  408. SAFEARRAYBOUND rgsabound[2];
  409. long ix[2];
  410. LPSTR pszStr;
  411. if (m_SNMPSession == NULL)
  412. return (Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL));
  413. rgsabound[0].lLbound = 0;
  414. rgsabound[0].cElements = 2;
  415. rgsabound[1].lLbound = 0;
  416. rgsabound[1].cElements = 0;
  417. if (! (psa = SafeArrayCreate(VT_VARIANT, 2, rgsabound)))
  418. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  419. hr = VarListAdd(bstrTree, &rfcVarList);
  420. if (FAILED (hr))
  421. {
  422. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  423. goto Cleanup2;
  424. }
  425. if (!SnmpUtilOidCpy(&asnRootOid, &rfcVarList.list[0].name)){
  426. hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  427. goto Cleanup2;
  428. }
  429. while(1){
  430. if (!SnmpMgrRequest(m_SNMPSession,
  431. ASN_RFC1157_GETNEXTREQUEST,
  432. &rfcVarList,
  433. &asniErrorStatus,
  434. &asniErrorIndex)) {
  435. hr = SetWinSnmpApiError (GetLastError ());
  436. goto Cleanup;
  437. }
  438. if (asniErrorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ||
  439. SnmpUtilOidNCmp(&rfcVarList.list[0].name, &asnRootOid, asnRootOid.idLength))
  440. break;
  441. if (asniErrorStatus > 0) {
  442. hr = SetSnmpScriptError(asniErrorStatus);
  443. goto Cleanup;
  444. }
  445. rgsabound[1].cElements++;
  446. ix[1] = rgsabound[1].cElements - 1;
  447. hr = SafeArrayRedim(psa, &rgsabound[1]);
  448. if (FAILED (hr))
  449. {
  450. Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  451. goto Cleanup;
  452. }
  453. // put a pszStr version of the OID in the result array
  454. pszStr = NULL;
  455. if (!SnmpMgrOidToStr(&rfcVarList.list[0].name, &pszStr)){
  456. hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  457. goto Cleanup;
  458. }
  459. ix[0] = 0;
  460. hr = PutString(psa, ix, pszStr);
  461. if (FAILED (hr))
  462. goto Cleanup;
  463. SnmpUtilMemFree(pszStr);
  464. // Put the value variant in the result array
  465. hr = RFC1157ToVariant(&v, &rfcVarList.list[0]);
  466. if (FAILED (hr)) goto Cleanup;
  467. ix[0] = 1;
  468. hr = SafeArrayPutElement(psa, ix, &v);
  469. if (FAILED (hr))
  470. {
  471. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  472. goto Cleanup;
  473. }
  474. VariantClear(&v);
  475. if (! SnmpUtilOidCpy(&asnTmpOid, &rfcVarList.list[0].name)) {
  476. hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  477. goto Cleanup;
  478. }
  479. SnmpUtilVarBindFree(&rfcVarList.list[0]);
  480. if (! SnmpUtilOidCpy(&rfcVarList.list[0].name, &asnTmpOid)) {
  481. hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  482. SnmpUtilOidFree(&asnTmpOid);
  483. goto Cleanup;
  484. }
  485. rfcVarList.list[0].value.asnType = ASN_NULL;
  486. SnmpUtilOidFree(&asnTmpOid);
  487. }
  488. SnmpUtilOidFree(&asnRootOid);
  489. SnmpUtilVarBindListFree(&rfcVarList);
  490. VariantInit(pvarValue);
  491. pvarValue->vt = VT_ARRAY|VT_VARIANT;
  492. pvarValue->parray = psa;
  493. return S_OK;
  494. Cleanup:
  495. SnmpUtilOidFree(&asnRootOid);
  496. Cleanup2:
  497. SnmpUtilVarBindListFree(&rfcVarList);
  498. if (psa)
  499. SafeArrayDestroy(psa);
  500. return hr;
  501. }
  502. /*****************************************************************************\
  503. * Function: Close
  504. *
  505. * PURPOSE: A Com Wrapper for SnmpMgrClose()
  506. *
  507. * ARGUMENTS:
  508. *
  509. * RETURN VALUE:
  510. * S_OK: always.
  511. *
  512. \*****************************************************************************/
  513. STDMETHODIMP
  514. CSNMP::
  515. Close(
  516. VOID
  517. )
  518. {
  519. if (m_SNMPSession)
  520. SnmpMgrClose(m_SNMPSession);
  521. m_SNMPSession = NULL;
  522. return S_OK;
  523. }
  524. STDMETHODIMP
  525. CSNMP::
  526. OIDFromString(
  527. BSTR bstrOID,
  528. VARIANT *pvarOID
  529. )
  530. {
  531. SAFEARRAY *psaOID;
  532. SAFEARRAYBOUND rgsaOID[1];
  533. long ixOID[1];
  534. LPSTR pszOID;
  535. BOOL bResult;
  536. VARIANT v;
  537. AsnObjectIdentifier asnReqObject;
  538. HRESULT hr;
  539. VariantInit(&v);
  540. if (! (pszOID = MakeNarrow(bstrOID)))
  541. return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  542. bResult = SnmpMgrStrToOid(pszOID, &asnReqObject);
  543. LocalFree(pszOID);
  544. if (!bResult )
  545. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  546. // put a numeric array of the pvarOID in the result array
  547. rgsaOID[0].lLbound = 0;
  548. rgsaOID[0].cElements = asnReqObject.idLength;
  549. psaOID = SafeArrayCreate(VT_VARIANT, 1, rgsaOID);
  550. if (psaOID == NULL)
  551. goto out;
  552. for (ixOID[0] = 0; ixOID[0] < (long)rgsaOID[0].cElements ; ixOID[0]++){
  553. hr = VariantClear(&v);
  554. _ASSERTE (SUCCEEDED (hr));
  555. v.vt = VT_I4;
  556. v.lVal = asnReqObject.ids[ixOID[0]];
  557. hr = SafeArrayPutElement(psaOID, ixOID, &v);
  558. if (FAILED(hr))
  559. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  560. //SafeArrayPutElement(psaOID, ixOID, &(asnReqObject.ids[ixOID[0]]));
  561. }
  562. hr = VariantClear(pvarOID);
  563. _ASSERTE(hr);
  564. pvarOID->vt = VT_ARRAY|VT_VARIANT;
  565. pvarOID->parray = psaOID;
  566. SnmpUtilOidFree(&asnReqObject);
  567. return S_OK;
  568. out:
  569. SnmpUtilOidFree(&asnReqObject);
  570. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  571. }
  572. HRESULT
  573. CSNMP::
  574. VariantToRFC1157(
  575. RFC1157VarBind * prfcvbValue,
  576. VARIANT * pvarValue
  577. )
  578. {
  579. HRESULT hr = S_OK;
  580. if (!pvarValue) {
  581. prfcvbValue->value.asnType = ASN_NULL;
  582. } else
  583. if (pvarValue->vt == VT_BSTR){
  584. prfcvbValue->value.asnType = ASN_OCTETSTRING;
  585. LPSTR pStr = MakeNarrow (pvarValue->bstrVal);
  586. if (pStr) {
  587. DWORD dwLen = strlen (pStr);
  588. if (! (prfcvbValue->value.asnValue.string.stream = (BYTE *) SnmpUtilMemAlloc (dwLen + 1))) {
  589. LocalFree (pStr);
  590. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  591. }
  592. memcpy (prfcvbValue->value.asnValue.string.stream, pStr, dwLen + 1);
  593. prfcvbValue->value.asnValue.string.length = dwLen;
  594. prfcvbValue->value.asnValue.string.dynamic = TRUE;
  595. LocalFree (pStr);
  596. }
  597. else
  598. hr = Error( IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY );
  599. }
  600. else {
  601. VARIANT varTemp;
  602. VariantInit (&varTemp);
  603. hr = VariantChangeType (&varTemp, pvarValue, 0, VT_I4);
  604. if (FAILED (hr))
  605. hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  606. else {
  607. prfcvbValue->value.asnType = ASN_INTEGER;
  608. prfcvbValue->value.asnValue.number = pvarValue->lVal;
  609. }
  610. }
  611. return hr;
  612. }
  613. // ----------------------------------------------------
  614. // Place a returned SNMP value in a variant
  615. //
  616. HRESULT
  617. CSNMP::
  618. RFC1157ToVariant(
  619. VARIANT * pvarValue,
  620. RFC1157VarBind * prfcvbValue
  621. )
  622. {
  623. VariantInit(pvarValue);
  624. switch (prfcvbValue->value.asnType){
  625. case ASN_RFC1155_TIMETICKS:
  626. case ASN_RFC1155_COUNTER:
  627. case ASN_RFC1155_GAUGE:
  628. case ASN_INTEGER:
  629. case ASN_UNSIGNED32:
  630. pvarValue->vt= VT_I4;
  631. pvarValue->lVal = prfcvbValue->value.asnValue.number;
  632. break;
  633. case ASN_RFC1155_IPADDRESS:
  634. case ASN_RFC1155_OPAQUE:
  635. case ASN_BITS:
  636. case ASN_SEQUENCE:
  637. case ASN_OCTETSTRING:
  638. pvarValue->vt = VT_BSTR;
  639. LPWSTR pszUnicodeStr;
  640. if (prfcvbValue->value.asnValue.string.length > 0 ){
  641. LPSTR pszAnsiStr;
  642. if (! (pszAnsiStr = (LPSTR )LocalAlloc(LPTR,
  643. prfcvbValue->value.asnValue.string.length + 1)))
  644. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  645. memcpy(pszAnsiStr, (LPSTR )prfcvbValue->value.asnValue.string.stream,
  646. prfcvbValue->value.asnValue.string.length);
  647. pszAnsiStr[prfcvbValue->value.asnValue.string.length] = 0;
  648. pszUnicodeStr = MakeWide(pszAnsiStr);
  649. LocalFree(pszAnsiStr);
  650. }
  651. else{
  652. pszUnicodeStr = MakeWide("");
  653. }
  654. if (pszUnicodeStr == NULL)
  655. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  656. pvarValue->bstrVal = SysAllocString(pszUnicodeStr);
  657. LocalFree(pszUnicodeStr);
  658. if (pvarValue->bstrVal == NULL) {
  659. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  660. }
  661. break;
  662. case ASN_OBJECTIDENTIFIER:
  663. LPSTR pszAnsiOid;
  664. pszAnsiOid = NULL;
  665. if (SnmpMgrOidToStr(& (prfcvbValue->value.asnValue.object), &pszAnsiOid)) {
  666. LPWSTR pszUnicodeOid = MakeWide (pszAnsiOid);
  667. SnmpUtilMemFree (pszAnsiOid);
  668. if (pszUnicodeOid) {
  669. pvarValue->vt = VT_BSTR;
  670. pvarValue->bstrVal = SysAllocString(pszUnicodeOid);
  671. LocalFree (pszUnicodeOid);
  672. }
  673. else
  674. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  675. }
  676. else
  677. return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  678. break;
  679. default:
  680. pvarValue->vt = VT_EMPTY;
  681. }
  682. return S_OK;
  683. }
  684. // ----------------------------------------------------
  685. // Place a returned SNMP value in a uint
  686. //
  687. HRESULT
  688. CSNMP::
  689. RFC1157ToUInt(
  690. PUINT puValue,
  691. RFC1157VarBind * prfcvbValue
  692. )
  693. {
  694. switch (prfcvbValue->value.asnType){
  695. case ASN_RFC1155_TIMETICKS:
  696. case ASN_RFC1155_COUNTER:
  697. case ASN_RFC1155_GAUGE:
  698. case ASN_INTEGER:
  699. case ASN_UNSIGNED32:
  700. *puValue = prfcvbValue->value.asnValue.number;
  701. break;
  702. case ASN_RFC1155_OPAQUE:
  703. case ASN_BITS:
  704. case ASN_SEQUENCE:
  705. case ASN_OCTETSTRING:
  706. if (prfcvbValue->value.asnValue.string.length == 1 ){
  707. *puValue = prfcvbValue->value.asnValue.string.stream[0];
  708. }
  709. else{
  710. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  711. }
  712. break;
  713. default:
  714. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  715. }
  716. return S_OK;
  717. }
  718. // -----------------------------------------------------
  719. // Add an OID to an SNMP get list
  720. //
  721. // Convert the UNICODE string to ANSI
  722. // Convert it to a real OID (numbers)
  723. // Add to the Array
  724. HRESULT
  725. CSNMP::
  726. VarListAdd(
  727. BSTR bstrOID,
  728. RFC1157VarBindList * prfcList,
  729. VARIANT *pvarValue
  730. )
  731. {
  732. LPSTR pszOID;
  733. BOOL bResult;
  734. AsnObjectIdentifier asnReqObject;
  735. if (! (pszOID = MakeNarrow(bstrOID)))
  736. return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
  737. bResult = SnmpMgrStrToOid(pszOID, &asnReqObject);
  738. LocalFree(pszOID);
  739. if (!bResult)
  740. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  741. prfcList->len++;
  742. if (! (prfcList->list = (RFC1157VarBind *) SNMP_realloc (prfcList->list,
  743. sizeof(RFC1157VarBind) * prfcList->len)))
  744. return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
  745. prfcList->list[prfcList->len - 1].name = asnReqObject;
  746. return VariantToRFC1157(& (prfcList->list[prfcList->len -1]), pvarValue);
  747. }
  748. /*****************************************************************************\
  749. * Function: Set
  750. *
  751. * PURPOSE: Set a value of a SNMP oid
  752. *
  753. * ARGUMENTS:
  754. *
  755. * bstrOID: The SNMP Oid in BSTR
  756. * varValue: The corresponding Oid
  757. *
  758. * RETURN VALUE:
  759. * S_OK: If succeed.
  760. * E_INVALIDARG: Invalid oid.
  761. * E_FAIL: If Open method has not been called before
  762. * E_OUTOFMEMORY: Out of memory
  763. * other: Returns the last error set by SnmpMgrRequest
  764. *
  765. \*****************************************************************************/
  766. STDMETHODIMP
  767. CSNMP::
  768. Set(
  769. IN BSTR bstrOID,
  770. IN VARIANT varValue
  771. )
  772. {
  773. RFC1157VarBindList rfcVarList = {NULL, 0};
  774. AsnInteger asniErrorStatus;
  775. AsnInteger asniErrorIndex;
  776. HRESULT hr = E_FAIL;
  777. if (m_SNMPSession == NULL)
  778. return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
  779. if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList)))
  780. {
  781. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  782. goto Cleanup;
  783. }
  784. hr = VariantToRFC1157(&rfcVarList.list[0], &varValue);
  785. if (FAILED (hr))
  786. goto Cleanup;
  787. if (!SnmpMgrRequest(m_SNMPSession,
  788. ASN_RFC1157_SETREQUEST,
  789. &rfcVarList,
  790. &asniErrorStatus,
  791. &asniErrorIndex)) {
  792. hr = SetWinSnmpApiError (GetLastError ());
  793. goto Cleanup;
  794. }
  795. if (asniErrorStatus > 0) {
  796. hr = SetSnmpScriptError(asniErrorStatus);
  797. goto Cleanup;
  798. }
  799. hr = S_OK;
  800. Cleanup:
  801. SnmpUtilVarBindListFree(&rfcVarList);
  802. return hr;
  803. }
  804. /*****************************************************************************\
  805. * Function: SetList
  806. *
  807. * PURPOSE: Set a list of a SNMP oids
  808. *
  809. * ARGUMENTS:
  810. *
  811. * pvarList: The array of SNMP Oids. The type must be a 1D array of BSTRs
  812. * pvarValue: The corresponding Oids, it must also b a 1D array of Variants
  813. *
  814. * RETURN VALUE:
  815. * S_OK: If succeed.
  816. * E_INVALIDARG: Invalid oid or the type of the variant is not a 1D array
  817. * E_FAIL: If Open method has not been called before
  818. * E_OUTOFMEMORY: Out of memory
  819. * other: Returns the last error set by SnmpMgrRequest
  820. *
  821. \*****************************************************************************/
  822. STDMETHODIMP
  823. CSNMP::
  824. SetList(
  825. IN VARIANT * varName,
  826. IN VARIANT * varValue
  827. )
  828. {
  829. RFC1157VarBindList rfcVarList = {NULL, 0};
  830. AsnInteger asniErrorStatus;
  831. AsnInteger asniErrorIndex;
  832. HRESULT hr = E_FAIL;
  833. SAFEARRAY *psaName, *psaValue;
  834. long lLowBound, lUpperBound;
  835. long ix[1];
  836. if (m_SNMPSession == NULL)
  837. return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
  838. if (!(varName->vt & VT_ARRAY) || !(varValue->vt & VT_ARRAY))
  839. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  840. if (varName->vt & VT_BYREF)
  841. psaName = *(varName->pparray);
  842. else
  843. psaName = varName->parray;
  844. if (varValue->vt & VT_BYREF)
  845. psaValue = *(varValue->pparray);
  846. else
  847. psaValue = varValue->parray;
  848. if (SafeArrayGetDim(psaName) != 1 || SafeArrayGetDim(psaValue) != 1)
  849. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  850. SafeArrayGetLBound(psaName, 1, &lLowBound);
  851. SafeArrayGetUBound(psaName, 1, &lUpperBound);
  852. long lVal;
  853. SafeArrayGetLBound(psaValue, 1, &lVal);
  854. if (lVal != lLowBound)
  855. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  856. SafeArrayGetUBound(psaValue, 1, &lVal);
  857. if (lVal != lUpperBound)
  858. return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  859. for (ix[0] = lLowBound; ix[0] <= lUpperBound; ix[0]++) {
  860. VARIANT varArgName, varArgValue;
  861. VariantClear(&varArgName);
  862. VariantClear(&varArgValue);
  863. hr = SafeArrayGetElement(psaName, ix, &varArgName);
  864. if (FAILED (hr)) {
  865. hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  866. goto Cleanup;
  867. }
  868. if (varArgName.vt != VT_BSTR) {
  869. hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  870. goto Cleanup;
  871. }
  872. hr = SafeArrayGetElement(psaValue, ix, &varArgValue);
  873. if (FAILED (hr))
  874. goto Cleanup;
  875. if (FAILED (hr = VarListAdd(varArgName.bstrVal, &rfcVarList, &varArgValue)))
  876. goto Cleanup;
  877. }
  878. if (! SnmpMgrRequest(m_SNMPSession,
  879. ASN_RFC1157_SETREQUEST,
  880. &rfcVarList,
  881. &asniErrorStatus,
  882. &asniErrorIndex))
  883. {
  884. hr = SetWinSnmpApiError (GetLastError ());
  885. goto Cleanup;
  886. }
  887. if (asniErrorStatus > 0) {
  888. hr = SetSnmpScriptError(asniErrorStatus);
  889. goto Cleanup;
  890. }
  891. hr = S_OK;
  892. Cleanup:
  893. SnmpUtilVarBindListFree(&rfcVarList);
  894. return hr;
  895. }
  896. HRESULT
  897. CSNMP::
  898. SetSnmpScriptError(
  899. IN DWORD dwError
  900. )
  901. {
  902. static DWORD SnmpErrorMapping [] = {
  903. IDS_SNMP_ERRORSTATUS_NOERROR,
  904. IDS_SNMP_ERRORSTATUS_TOOBIG,
  905. IDS_SNMP_ERRORSTATUS_NOSUCHNAME,
  906. IDS_SNMP_ERRORSTATUS_BADVALUE,
  907. IDS_SNMP_ERRORSTATUS_READONLY,
  908. IDS_SNMP_ERRORSTATUS_GENERR,
  909. IDS_SNMP_ERRORSTATUS_NOACCESS,
  910. IDS_SNMP_ERRORSTATUS_WRONGTYPE,
  911. IDS_SNMP_ERRORSTATUS_WRONGLENGTH,
  912. IDS_SNMP_ERRORSTATUS_WRONGENCODING,
  913. IDS_SNMP_ERRORSTATUS_WRONGVALUE,
  914. IDS_SNMP_ERRORSTATUS_NOCREATION,
  915. IDS_SNMP_ERRORSTATUS_INCONSISTENTVALUE,
  916. IDS_SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE,
  917. IDS_SNMP_ERRORSTATUS_COMMITFAILED,
  918. IDS_SNMP_ERRORSTATUS_UNDOFAILED,
  919. IDS_SNMP_ERRORSTATUS_AUTHORIZATIONERROR,
  920. IDS_SNMP_ERRORSTATUS_NOTWRITABLE,
  921. IDS_SNMP_ERRORSTATUS_INCONSISTENTNAME};
  922. if ((int)dwError < 0 || dwError > sizeof (SnmpErrorMapping) / sizeof (DWORD))
  923. dwError = SNMP_ERRORSTATUS_GENERR;
  924. return Error(SnmpErrorMapping[dwError], IID_ISNMP, E_FAIL);
  925. }
  926. HRESULT
  927. CSNMP::
  928. SetWinSnmpApiError(
  929. IN DWORD dwError
  930. )
  931. {
  932. static DWORD WinSnmpApiErrorMapping [] = {
  933. IDS_SNMPAPI_ALLOC_ERROR,
  934. IDS_SNMPAPI_CONTEXT_INVALID,
  935. IDS_SNMPAPI_CONTEXT_UNKNOWN,
  936. IDS_SNMPAPI_ENTITY_INVALID,
  937. IDS_SNMPAPI_ENTITY_UNKNOWN,
  938. IDS_SNMPAPI_INDEX_INVALID,
  939. IDS_SNMPAPI_NOOP,
  940. IDS_SNMPAPI_OID_INVALID,
  941. IDS_SNMPAPI_OPERATION_INVALID,
  942. IDS_SNMPAPI_OUTPUT_TRUNCATED,
  943. IDS_SNMPAPI_PDU_INVALID,
  944. IDS_SNMPAPI_SESSION_INVALID,
  945. IDS_SNMPAPI_SYNTAX_INVALID,
  946. IDS_SNMPAPI_VBL_INVALID,
  947. IDS_SNMPAPI_MODE_INVALID,
  948. IDS_SNMPAPI_SIZE_INVALID,
  949. IDS_SNMPAPI_NOT_INITIALIZED,
  950. IDS_SNMPAPI_MESSAGE_INVALID,
  951. IDS_SNMPAPI_HWND_INVALID,
  952. IDS_SNMPAPI_OTHER_ERROR,
  953. IDS_SNMPAPI_TL_NOT_INITIALIZED,
  954. IDS_SNMPAPI_TL_NOT_SUPPORTED,
  955. IDS_SNMPAPI_TL_NOT_AVAILABLE,
  956. IDS_SNMPAPI_TL_RESOURCE_ERROR,
  957. IDS_SNMPAPI_TL_UNDELIVERABLE,
  958. IDS_SNMPAPI_TL_SRC_INVALID,
  959. IDS_SNMPAPI_TL_INVALID_PARAM,
  960. IDS_SNMPAPI_TL_IN_USE,
  961. IDS_SNMPAPI_TL_TIMEOUT,
  962. IDS_SNMPAPI_TL_PDU_TOO_BIG,
  963. IDS_SNMPAPI_TL_OTHER
  964. };
  965. static DWORD WinSnmpApiError [] = {
  966. SNMPAPI_ALLOC_ERROR,
  967. SNMPAPI_CONTEXT_INVALID,
  968. SNMPAPI_CONTEXT_UNKNOWN,
  969. SNMPAPI_ENTITY_INVALID,
  970. SNMPAPI_ENTITY_UNKNOWN,
  971. SNMPAPI_INDEX_INVALID,
  972. SNMPAPI_NOOP,
  973. SNMPAPI_OID_INVALID,
  974. SNMPAPI_OPERATION_INVALID,
  975. SNMPAPI_OUTPUT_TRUNCATED,
  976. SNMPAPI_PDU_INVALID,
  977. SNMPAPI_SESSION_INVALID,
  978. SNMPAPI_SYNTAX_INVALID,
  979. SNMPAPI_VBL_INVALID,
  980. SNMPAPI_MODE_INVALID,
  981. SNMPAPI_SIZE_INVALID,
  982. SNMPAPI_NOT_INITIALIZED,
  983. SNMPAPI_MESSAGE_INVALID,
  984. SNMPAPI_HWND_INVALID,
  985. SNMPAPI_OTHER_ERROR,
  986. SNMPAPI_TL_NOT_INITIALIZED,
  987. SNMPAPI_TL_NOT_SUPPORTED,
  988. SNMPAPI_TL_NOT_AVAILABLE,
  989. SNMPAPI_TL_RESOURCE_ERROR,
  990. SNMPAPI_TL_UNDELIVERABLE,
  991. SNMPAPI_TL_SRC_INVALID,
  992. SNMPAPI_TL_INVALID_PARAM,
  993. SNMPAPI_TL_IN_USE,
  994. SNMPAPI_TL_TIMEOUT,
  995. SNMPAPI_TL_PDU_TOO_BIG,
  996. SNMPAPI_TL_OTHER
  997. };
  998. for (int i = 0; i < sizeof (WinSnmpApiError); i++) {
  999. if (dwError == WinSnmpApiError[i]) {
  1000. dwError = WinSnmpApiErrorMapping[i];
  1001. break;
  1002. }
  1003. }
  1004. return Error(dwError, IID_ISNMP, E_FAIL);
  1005. }
  1006. // Convert part of the the variant array to
  1007. // RFC1157VarBindList used in SnmpMgrRequest call
  1008. HRESULT
  1009. CSNMP::
  1010. VarToRfcVarList(
  1011. long lbound,
  1012. long ubound,
  1013. SAFEARRAY *psa,
  1014. RFC1157VarBindList * prfcVarList
  1015. )
  1016. {
  1017. long ix[1];
  1018. VARIANT var;
  1019. HRESULT hr = S_OK;
  1020. for (ix[0] = lbound; ix[0] <= ubound; ix[0]++) {
  1021. VariantClear(&var);
  1022. hr = SafeArrayGetElement(psa, ix, &var);
  1023. if (FAILED (hr) || var.vt != VT_BSTR) {
  1024. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  1025. break;
  1026. }
  1027. hr = VarListAdd(var.bstrVal, prfcVarList);
  1028. if (FAILED (hr)) {
  1029. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  1030. break;
  1031. }
  1032. }
  1033. return hr;
  1034. }
  1035. // Append RFC1157VarBindList used in SnmpMgrRequest call at the
  1036. // end of the variant array
  1037. HRESULT
  1038. CSNMP::
  1039. RfcToVarList(
  1040. long lbound,
  1041. RFC1157VarBindList *prfcVarList,
  1042. SAFEARRAY * psaOut
  1043. )
  1044. {
  1045. long ix[1];
  1046. DWORD i;
  1047. VARIANT var;
  1048. HRESULT hr = S_OK;
  1049. for(ix[0] = lbound, i = 0; i < prfcVarList->len; i++, ix[0]++) {
  1050. hr = RFC1157ToVariant(&var, & prfcVarList->list[i]);
  1051. if (FAILED (hr))
  1052. break;
  1053. hr = SafeArrayPutElement(psaOut, ix, &var);
  1054. if (FAILED (hr)) {
  1055. Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
  1056. break;
  1057. }
  1058. }
  1059. return hr;
  1060. }