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.

459 lines
14 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. winsmibm.c
  5. Abstract:
  6. Sample SNMP Extension Agent for Windows NT.
  7. These files (winsdll.c, winsmib.c, and winsmib.h) provide an example of
  8. how to structure an Extension Agent DLL which works in conjunction with
  9. the SNMP Extendible Agent for Windows NT.
  10. Extensive comments have been included to describe its structure and
  11. operation. See also "Microsoft Windows/NT SNMP Programmer's Reference".
  12. Created:
  13. 28-Jun-1991
  14. Revision History:
  15. --*/
  16. static char *vcsid = "@(#) $Logfile: N:/xtest/vcs/winsdll.c_v $ $Revision: 1.6 $";
  17. #ifdef UNICODE
  18. #undef UNICODE
  19. #endif
  20. // General notes:
  21. //
  22. // Microsoft's Extendible Agent for Windows NT is implemented by dynamically
  23. // linking to Extension Agent DLLs that implement portions of the MIB. These
  24. // Extension Agents are configured in the Windows NT Registration Database.
  25. // When the Extendible Agent Service is started, it queries the registry to
  26. // determine which Extension Agent DLLs have been installed and need to be
  27. // loaded and initialized. The Extendible Agent invokes various DLL entry
  28. // points (examples follow in this file) to request MIB queries and obtain
  29. // Extension Agent generated traps.
  30. // Necessary includes.
  31. #include <windows.h>
  32. #include <malloc.h>
  33. #include <tchar.h>
  34. #include <snmp.h>
  35. // Contains definitions for the table structure describing the MIB. This
  36. // is used in conjunction with winsmib.c where the MIB requests are resolved.
  37. #include "winsmib.h"
  38. // Extension Agent DLLs need access to elapsed time agent has been active.
  39. // This is implemented by initializing the Extension Agent with a time zero
  40. // reference, and allowing the agent to compute elapsed time by subtracting
  41. // the time zero reference from the current system time. This example
  42. // Extension Agent implements this reference with dwTimeZero.
  43. DWORD dwTimeZero = 0;
  44. // Extension Agent DLLs that generate traps must create a Win32 Event object
  45. // to communicate occurence of traps to the Extendible Agent. The event
  46. // handle is given to the Extendible Agent when the Extension Agent is
  47. // initialized, it should be NULL if traps will not be generated. This
  48. // example Extension Agent simulates the occurance of traps with hSimulateTrap.
  49. HANDLE hSimulateTrap = NULL;
  50. // The following variables are needed in order to figure out if the WINS service
  51. // is installed and running on the box. If this is not true, the subagent should
  52. // return SNMP_ERRORSTATUS_NOSUCHNAME for any query, instead of failing later with
  53. // SNMP_ERRORSTATUS_GENERR.
  54. #define WINS_SVC_NAME _T("WINS")
  55. SC_HANDLE hSvcController = NULL;
  56. SC_HANDLE hWinsSvc = NULL;
  57. // This call returns true if the WINS service is installed and running and
  58. // false otherwise. If WINS is not running, the subagent should fail with
  59. // SNMP_ERRORSTATUS_NOSUCHNAME or should return the first OID out of the MIB view
  60. // instead of an SNMP_ERRORSTATUS_GENERR.
  61. BOOL CheckWinsServiceUp(
  62. OUT AsnInteger *errorStatus)
  63. {
  64. SERVICE_STATUS winsSvcStatus;
  65. // at first request, open the service controller handle
  66. if (hSvcController == NULL)
  67. {
  68. hSvcController = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
  69. // if unsuccessful this is a real genErr case (any app should be able to do so)
  70. if (hSvcController == NULL)
  71. {
  72. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  73. return FALSE;
  74. }
  75. }
  76. // at first request, open the Wins service handle
  77. if (hWinsSvc == NULL)
  78. {
  79. hWinsSvc = OpenService(hSvcController, WINS_SVC_NAME, SERVICE_QUERY_STATUS);
  80. // if unsuccessful it might be that the service is not installed. In this case,
  81. // return noSuchName, otherwise there is a genErr case
  82. if (hWinsSvc == NULL)
  83. {
  84. *errorStatus = (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) ?
  85. SNMP_ERRORSTATUS_NOSUCHNAME :
  86. SNMP_ERRORSTATUS_GENERR;
  87. return FALSE;
  88. }
  89. }
  90. // we have both the service controller and the wins service handle, just query for the status
  91. if (!QueryServiceStatus(hWinsSvc, &winsSvcStatus))
  92. {
  93. // if querying the status of the service failed, this is a case of genErr
  94. *errorStatus = SNMP_ERRORSTATUS_GENERR;
  95. return FALSE;
  96. }
  97. // if WINS is in any other state than 'running', will handle as the service is stopped
  98. // and return NOSUCHNAME (allowing a possible MIB walk to continue)
  99. if (winsSvcStatus.dwCurrentState != SERVICE_RUNNING)
  100. {
  101. *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
  102. return FALSE;
  103. }
  104. // at this point the service is up and running
  105. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  106. return TRUE;
  107. }
  108. // This call returns true if the WINSMIB is allowed to run (via registry setting)
  109. // and FALSE otherwise. If FALSE, the errorStatus is set to SNMP_ERRORSTATUS_NOSUCHNAME.
  110. BOOL CheckWinsMibAllowed(
  111. OUT AsnInteger *errorStatus)
  112. {
  113. BOOL bRetCode = FALSE;
  114. HKEY hKey = NULL;
  115. RegOpenKey(
  116. HKEY_LOCAL_MACHINE,
  117. _T("System\\CurrentControlSet\\Services\\WINS\\Parameters"),
  118. &hKey);
  119. if (hKey != NULL)
  120. {
  121. DWORD dwDataSize = sizeof(BOOL);
  122. DWORD dwDataType = 0;
  123. if ((RegQueryValueEx(
  124. hKey,
  125. _T("AllowMIB"),
  126. NULL,
  127. &dwDataType,
  128. (LPBYTE)&bRetCode,
  129. &dwDataSize) == ERROR_SUCCESS) &&
  130. (dwDataType == REG_DWORD)
  131. )
  132. {
  133. // normalize the return value to a boolean
  134. bRetCode = (bRetCode != 0);
  135. }
  136. }
  137. if (hKey != NULL)
  138. RegCloseKey(hKey);
  139. *errorStatus = bRetCode ? SNMP_ERRORSTATUS_NOSUCHNAME : SNMP_ERRORSTATUS_NOERROR;
  140. return bRetCode;
  141. }
  142. // This is a standard Win32 DLL entry point. See the Win32 SDK for more
  143. // information on its arguments and their meanings. This example DLL does
  144. // not perform any special actions using this mechanism.
  145. BOOL WINAPI DllMain(
  146. HANDLE hDll,
  147. DWORD dwReason,
  148. LPVOID lpReserved)
  149. {
  150. switch(dwReason)
  151. {
  152. case DLL_PROCESS_ATTACH:
  153. case DLL_PROCESS_DETACH:
  154. case DLL_THREAD_ATTACH:
  155. case DLL_THREAD_DETACH:
  156. default:
  157. break;
  158. } // end switch()
  159. return TRUE;
  160. } // end DllEntryPoint()
  161. // Extension Agent DLLs provide the following entry point to coordinate the
  162. // initializations of the Extension Agent and the Extendible Agent. The
  163. // Extendible Agent provides the Extension Agent with a time zero reference;
  164. // and the Extension Agent provides the Extendible Agent with an Event handle
  165. // for communicating occurence of traps, and an object identifier representing
  166. // the root of the MIB subtree that the Extension Agent supports.
  167. BOOL SnmpExtensionInit(
  168. IN DWORD dwTimeZeroReference,
  169. OUT HANDLE *hPollForTrapEvent,
  170. OUT AsnObjectIdentifier *supportedView)
  171. {
  172. // Record the time reference provided by the Extendible Agent.
  173. dwTimeZero = dwTimeZeroReference;
  174. // Create an Event that will be used to communicate the occurence of traps
  175. // to the Extendible Agent. The Extension Agent will assert this Event
  176. // when a trap has occured. This is explained further later in this file.
  177. if ((*hPollForTrapEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
  178. {
  179. // Indicate error?, be sure that NULL is returned to Extendible Agent.
  180. }
  181. // Indicate the MIB view supported by this Extension Agent, an object
  182. // identifier representing the sub root of the MIB that is supported.
  183. *supportedView = MIB_OidPrefix; // NOTE! structure copy
  184. // Record the trap Event. This example Extension Agent simulates traps by
  185. // generating a trap after every given number of processed requests.
  186. hSimulateTrap = *hPollForTrapEvent;
  187. WinsMibInit();
  188. // Indicate that Extension Agent initialization was sucessfull.
  189. return TRUE;
  190. } // end SnmpExtensionInit()
  191. // Extension Agent DLLs provide the following entry point to communcate traps
  192. // to the Extendible Agent. The Extendible Agent will query this entry point
  193. // when the trap Event (supplied at initialization time) is asserted, which
  194. // indicates that zero or more traps may have occured. The Extendible Agent
  195. // will repetedly call this entry point until FALSE is returned, indicating
  196. // that all outstanding traps have been processed.
  197. BOOL SnmpExtensionTrap(
  198. OUT AsnObjectIdentifier *enterprise,
  199. OUT AsnInteger *genericTrap,
  200. OUT AsnInteger *specificTrap,
  201. OUT AsnTimeticks *timeStamp,
  202. OUT RFC1157VarBindList *variableBindings)
  203. {
  204. // The body of this routine is an extremely simple example/simulation of
  205. // the trap functionality. A real implementation will be more complex.
  206. // The following define data inserted into the trap below. The Lan Manager
  207. // bytesAvailAlert from the Lan Manager Alerts-2 MIB is generated with an
  208. // empty variable bindings list.
  209. static UINT OidList[] = { 1, 3, 6, 1, 4, 1, 311, 1, 2 };
  210. static UINT OidListLen = 9;
  211. // The following variable is used for the simulation, it allows a single
  212. // trap to be generated and then causes FALSE to be returned indicating
  213. // no more traps.
  214. static whichTime = 0;
  215. // The following if/else support the simulation.
  216. if (whichTime == 0)
  217. {
  218. whichTime = 1; // Supports the simulation.
  219. // Communicate the trap data to the Extendible Agent.
  220. enterprise->idLength = OidListLen;
  221. enterprise->ids = (UINT *)SNMP_malloc(sizeof(UINT) * OidListLen);
  222. memcpy(enterprise->ids, OidList, sizeof(UINT) * OidListLen);
  223. *genericTrap = SNMP_GENERICTRAP_ENTERSPECIFIC;
  224. *specificTrap = 1; // the bytesAvailAlert trap
  225. *timeStamp = GetCurrentTime() - dwTimeZero;
  226. variableBindings->list = NULL;
  227. variableBindings->len = 0;
  228. // Indicate that valid trap data exists in the parameters.
  229. return TRUE;
  230. }
  231. else
  232. {
  233. whichTime = 0; // Supports the simulation.
  234. // Indicate that no more traps are available and parameters do not
  235. // refer to any valid data.
  236. return FALSE;
  237. }
  238. } // end SnmpExtensionTrap()
  239. // Extension Agent DLLs provide the following entry point to resolve queries
  240. // for MIB variables in their supported MIB view (supplied at initialization
  241. // time). The requestType is Get/GetNext/Set.
  242. BOOL SnmpExtensionQuery(
  243. IN BYTE requestType,
  244. IN OUT RFC1157VarBindList *variableBindings,
  245. OUT AsnInteger *errorStatus,
  246. OUT AsnInteger *errorIndex)
  247. {
  248. static unsigned long requestCount = 0; // Supports the trap simulation.
  249. UINT I;
  250. // EnterCriticalSection(&WinsMibCrtSec);
  251. try {
  252. //
  253. // Iterate through the variable bindings list to resolve individual
  254. // variable bindings.
  255. //
  256. fWinsMibWinsStatusCnfCalled = FALSE;
  257. fWinsMibWinsStatusStatCalled = FALSE;
  258. for ( I=0;I < variableBindings->len;I++ )
  259. {
  260. // resolve the variables only if WINS is up and running.
  261. if (CheckWinsServiceUp(errorStatus) &&
  262. CheckWinsMibAllowed(errorStatus))
  263. {
  264. *errorStatus = ResolveVarBind( &variableBindings->list[I],
  265. requestType );
  266. }
  267. //
  268. // Test and handle case where Get Next past end of MIB view supported
  269. // by this Extension Agent occurs. Special processing is required to
  270. // communicate this situation to the Extendible Agent so it can take
  271. // appropriate action, possibly querying other Extension Agents.
  272. //
  273. if ( *errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME &&
  274. requestType == MIB_GETNEXT )
  275. {
  276. *errorStatus = SNMP_ERRORSTATUS_NOERROR;
  277. // Modify variable binding of such variables so the OID points
  278. // just outside the MIB view supported by this Extension Agent.
  279. // The Extendible Agent tests for this, and takes appropriate
  280. // action.
  281. SNMP_oidfree( &variableBindings->list[I].name );
  282. SNMP_oidcpy( &variableBindings->list[I].name, &MIB_OidPrefix );
  283. variableBindings->list[I].name.ids[MIB_PREFIX_LEN-1] ++;
  284. }
  285. // If an error was indicated, communicate error status and error
  286. // index to the Extendible Agent. The Extendible Agent will ensure
  287. // that the origional variable bindings are returned in the response
  288. // packet.
  289. if ( *errorStatus != SNMP_ERRORSTATUS_NOERROR )
  290. {
  291. *errorIndex = I+1;
  292. // goto Exit;
  293. }
  294. else
  295. {
  296. *errorIndex = 0;
  297. }
  298. }
  299. } // end of try
  300. except(EXCEPTION_EXECUTE_HANDLER) {
  301. //
  302. // for now do nothing
  303. //
  304. }
  305. // LeaveCriticalSection(&WinsMibCrtSec);
  306. #if 0
  307. // Supports the trap simulation.
  308. if (++requestCount % 3 == 0 && hSimulateTrap != NULL)
  309. SetEvent(hSimulateTrap);
  310. // Indicate that Extension Agent processing was sucessfull.
  311. #if 0
  312. if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
  313. {
  314. return(FALSE);
  315. }
  316. return TRUE;
  317. #endif
  318. #endif
  319. if (fWinsMibWinsKeyOpen)
  320. {
  321. RegCloseKey(WinsMibWinsKey);
  322. fWinsMibWinsKeyOpen = FALSE;
  323. }
  324. return SNMPAPI_NOERROR;
  325. } // end SnmpExtensionQuery()
  326. VOID
  327. SnmpExtensionClose()
  328. {
  329. // close the Wins service handle if it was previously opened
  330. if (hWinsSvc != NULL)
  331. {
  332. CloseServiceHandle(hWinsSvc);
  333. }
  334. // close the service controller handle if it was previously opened
  335. if (hSvcController != NULL)
  336. {
  337. CloseServiceHandle(hSvcController);
  338. }
  339. }
  340. //-------------------------------- END --------------------------------------