Leaked source code of windows server 2003
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.

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