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.

762 lines
27 KiB

  1. /*
  2. * gennt.c v0.14 May 15, 1996
  3. *
  4. ****************************************************************************
  5. * *
  6. * (C) Copyright 1995 DIGITAL EQUIPMENT CORPORATION *
  7. * *
  8. * This software is an unpublished work protected under the *
  9. * the copyright laws of the United States of America, all *
  10. * rights reserved. *
  11. * *
  12. * In the event this software is licensed for use by the United *
  13. * States Government, all use, duplication or disclosure by the *
  14. * United States Government is subject to restrictions as set *
  15. * forth in either subparagraph (c)(1)(ii) of the Rights in *
  16. * Technical Data And Computer Software Clause at DFARS *
  17. * 252.227-7013, or the Commercial Computer Software Restricted *
  18. * Rights Clause at FAR 52.221-19, whichever is applicable. *
  19. * *
  20. ****************************************************************************
  21. *
  22. * Facility:
  23. *
  24. * SNMP Extension Agent
  25. *
  26. * Abstract:
  27. *
  28. * This module contains the code for dealing with the generic logic for
  29. * processing the SNMP request. It is table driven. No user modification
  30. * should be done.
  31. *
  32. * Functions:
  33. *
  34. * ResolveVarBind()
  35. * FindClass()
  36. * ResolveGetNext()
  37. *
  38. * Author:
  39. * Miriam Amos Nihart, Kathy Faust
  40. *
  41. * Date:
  42. * 2/17/95
  43. *
  44. * Revision History:
  45. * 6/22/95 krw0001 FindClass - modify to stop checking for valid variable - we only care about valid
  46. * class.
  47. * Rewrite ResolveGetNext
  48. * 6/26/95 ags FindClass - stop checking for valid variable
  49. * Rewrite ResolveGetNext
  50. * 7/31/95 ags SNMP_oidfree works with CRTDLL.lib, hence use them.
  51. * 2/14/96 ags v0.11 one fix for the getnext bug found by Cindy
  52. * 3/19/96 kff v0.12 modified for trap support
  53. * 4/19/96 ags v0.13 Modified to get rid of trap.c in case of no traps.
  54. * 5/15/96 cs v0.14 Modified FindClass in the backward walkthru to tighten
  55. * up the verification
  56. */
  57. #include <windows.h>
  58. #include <malloc.h>
  59. #include <stdio.h>
  60. #include <snmp.h>
  61. #include "mib.h"
  62. #include "mib_xtrn.h"
  63. #include "smint.h"
  64. extern DWORD dwTimeZero ;
  65. UINT
  66. SnmpUtilOidMatch(AsnObjectIdentifier *pOid1, AsnObjectIdentifier *pOid2)
  67. {
  68. unsigned long int nScan = min(pOid1->idLength, pOid2->idLength);
  69. unsigned long int i;
  70. for (i = 0; i < nScan; i++)
  71. {
  72. if (pOid1->ids[i] != pOid2->ids[i])
  73. break;
  74. }
  75. return i;
  76. }
  77. /*
  78. * ResolveVarBind
  79. *
  80. * Resolves a single variable binding. Modifies the variable value pair
  81. * on a GET or a GET-NEXT.
  82. *
  83. * Arguments:
  84. *
  85. * VarBind pointer to the variable value pair
  86. * PduAction type of request - get, set, or getnext
  87. *
  88. * Return Codes:
  89. *
  90. * Standard PDU error codes.
  91. *
  92. */
  93. UINT
  94. ResolveVarBind( IN OUT RFC1157VarBind *VarBind , // Variable Binding to resolve
  95. IN UINT PduAction ) // Action specified in PDU
  96. {
  97. unsigned long int cindex ; // index into the class info table
  98. unsigned long int vindex ; // index into the class's var table
  99. UINT instance_array[ MAX_STRING_LEN ] ;
  100. UINT status ;
  101. UINT result ; // SNMP PDU error status
  102. AsnObjectIdentifier instance ;
  103. InstanceName native_instance ;
  104. instance.ids = instance_array ;
  105. // Determine which class the VarBind is for
  106. status = FindClass( VarBind, &cindex ) ;
  107. if ( status )
  108. {
  109. if ( PduAction != MIB_ACTION_GETNEXT )
  110. {
  111. // Check for valid variable as this is a get or set
  112. CHECK_VARIABLE( VarBind, cindex, vindex, status ) ;
  113. if ( !status )
  114. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  115. // Check for valid instance
  116. status = ( *class_info[ cindex ].FindInstance )
  117. ( (ObjectIdentifier *)&(VarBind->name) ,
  118. (ObjectIdentifier *)&instance ) ;
  119. if ( status != SNMP_ERRORSTATUS_NOERROR )
  120. return status ;
  121. // Check for access
  122. CHECK_ACCESS( cindex, vindex, PduAction, status ) ;
  123. if ( !status )
  124. {
  125. if ( PduAction == MIB_ACTION_SET )
  126. return SNMP_ERRORSTATUS_NOTWRITABLE ;
  127. else
  128. return SNMP_ERRORSTATUS_GENERR ;
  129. }
  130. // Ok to do the get or set
  131. if ( PduAction == MIB_ACTION_GET )
  132. {
  133. status = ( *class_info[ cindex ].ConvertInstance )
  134. ( (ObjectIdentifier *)&instance, &native_instance ) ;
  135. if ( status == FAILURE )
  136. return SNMP_ERRORSTATUS_GENERR ;
  137. result = ( *class_info[ cindex ].variable[ vindex].SMIGet )
  138. ( VarBind , cindex, vindex, &native_instance ) ;
  139. }
  140. else
  141. {
  142. if ( VarBind->value.asnType !=
  143. class_info[ cindex ].variable[ vindex ].type )
  144. return SNMP_ERRORSTATUS_BADVALUE ;
  145. status = ( *class_info[ cindex ].ConvertInstance )
  146. ( (ObjectIdentifier *)&instance, &native_instance ) ;
  147. if ( status == FAILURE )
  148. return SNMP_ERRORSTATUS_GENERR ;
  149. result = ( *class_info[ cindex ].variable[ vindex ].SMISet )
  150. ( VarBind, cindex, vindex, &native_instance ) ;
  151. }
  152. }
  153. else // This is a GETNEXT
  154. {
  155. //
  156. // Call ResolveGetNext() to determine which class, variable, and
  157. // instance to do a Get on.
  158. //
  159. status = ResolveGetNext( VarBind, &cindex, &vindex, &instance ) ;
  160. if ( status == SUCCESS )
  161. {
  162. status = ( *class_info[ cindex ].ConvertInstance )
  163. ( (ObjectIdentifier *)&instance, &native_instance ) ;
  164. if ( status == FAILURE )
  165. return SNMP_ERRORSTATUS_GENERR ;
  166. result = ( *class_info[ cindex ].variable[ vindex ].SMIGet )
  167. ( VarBind, cindex, vindex, &native_instance ) ;
  168. }
  169. else
  170. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  171. }
  172. }
  173. else
  174. {
  175. //
  176. // No class found, but its a GETNEXT.. we need to find the class that has the longest
  177. // with the requested oid and forward the request to it
  178. //
  179. if (PduAction == MIB_ACTION_GETNEXT)
  180. {
  181. unsigned long int ci; // index into the class info table
  182. unsigned long int nLongestMatch; // max number of ids that matched between names
  183. unsigned long int nCurrentMatch; // matching number of IDs at the current iteration
  184. // scan the class_info table, relying on the fact that the table is ordered
  185. // ordered ascendingly on the class OID.
  186. for (ci = 0, nLongestMatch = 0; ci < CLASS_TABLE_MAX; ci++)
  187. {
  188. // pick up the number of matching ids between the VarBind and the class name..
  189. nCurrentMatch = SnmpUtilOidMatch(&VarBind->name, class_info[ci].oid);
  190. // store in cindex the first class with the highest match number
  191. if (nCurrentMatch > nLongestMatch)
  192. {
  193. cindex = ci;
  194. nLongestMatch = nCurrentMatch;
  195. }
  196. }
  197. // only if VarBind name is longer than the match number we need to look
  198. // for an even better match
  199. if (VarBind->name.idLength > nLongestMatch)
  200. {
  201. for (;cindex < CLASS_TABLE_MAX; cindex++)
  202. {
  203. // make sure we don't go over the range with the longest Match
  204. if (SnmpUtilOidMatch(&VarBind->name, class_info[cindex].oid) != nLongestMatch)
  205. break;
  206. // if the class matches entirely into the VarBind name, check if the first ID
  207. // that follows in VarBind name is inside the range supported by the class
  208. if (class_info[cindex].oid->idLength == nLongestMatch)
  209. {
  210. // this is a hack - we rely the var_index is always 1 more than number of ids in
  211. // the class_info name. Since VarBind has already a name longer than nLongestMatch
  212. // no buffer overrun happens here.
  213. // if the VarBind name is in the right range, then we found the class - just break the loop
  214. // (don't forget, var_index is '1' based)
  215. if(VarBind->name.ids[class_info[cindex].var_index - 1] <= class_info[cindex].max_index)
  216. break;
  217. }
  218. else
  219. {
  220. // the VarBind name is longer than the IDs that match, the class_info name is the same
  221. // the first ID that follows in both names can't be equal, so we can break the loop if
  222. // the VarBind name is just in front of it.
  223. if (VarBind->name.ids[nLongestMatch] < class_info[cindex].oid->ids[nLongestMatch])
  224. break;
  225. }
  226. }
  227. }
  228. if (cindex < CLASS_TABLE_MAX )
  229. vindex = class_info[cindex].min_index ;
  230. else
  231. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  232. SNMP_oidfree( &VarBind->name ) ;
  233. if (! SNMP_oidcpy( &VarBind->name ,
  234. class_info[ cindex ].variable[ vindex ].oid ) )
  235. {
  236. return SNMP_ERRORSTATUS_GENERR ;
  237. }
  238. status = ResolveGetNext( VarBind, &cindex, &vindex, &instance ) ;
  239. if ( status == SUCCESS )
  240. {
  241. status = ( *class_info[ cindex ].ConvertInstance )
  242. ( (ObjectIdentifier *)&instance, &native_instance ) ;
  243. if ( status == FAILURE )
  244. return SNMP_ERRORSTATUS_GENERR ;
  245. result = ( *class_info[ cindex ].variable[ vindex ].SMIGet )
  246. ( VarBind, cindex, vindex, &native_instance ) ;
  247. }
  248. else
  249. {
  250. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  251. }
  252. }
  253. else
  254. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  255. }
  256. ( *class_info[ cindex ].FreeInstance )( &native_instance ) ;
  257. return result ;
  258. } /* end of ResolveVarBind() */
  259. /*
  260. * FindClass
  261. *
  262. * This routine determines the class by walking the class_info table
  263. * backwards and comparing the class oids. The table is walked
  264. * backwards because it assumes that the classes are listed in
  265. * increasing order. For example,
  266. *
  267. * Group Name Group Identifier
  268. *
  269. * group1 1.3.6.1.4.1.36.2.78
  270. * table1 1.3.6.1.4.1.36.2.78.9
  271. * table2 1.3.6.1.4.1.36.2.78.10
  272. *
  273. * We need to look for the longest exact match on the oid thus we
  274. * walk the table backwards.
  275. *
  276. * Arguments:
  277. *
  278. * VarBind Variable value pair
  279. * class Index into the class_info
  280. *
  281. * Return Codes:
  282. *
  283. * SUCCESS Class is valid, return index into class_info
  284. * FAILURE Invalid class
  285. *
  286. */
  287. UINT
  288. FindClass( IN RFC1157VarBind *VarBind ,
  289. IN OUT UINT *cindex )
  290. {
  291. int index ;
  292. UINT status, vindex ;
  293. UINT length ;
  294. for ( index = CLASS_TABLE_MAX - 1 ; index >= 0 ; index-- )
  295. {
  296. if ( class_info[ index ].table )
  297. // skip over the entry code -- kkf, why?
  298. // length = class_info[ index ].var_index - 2 ;
  299. length = class_info[ index ].var_index - 1 ;
  300. else
  301. length = class_info[ index ].var_index - 1 ;
  302. status = SNMP_oidncmp( &VarBind->name ,
  303. class_info[ index ].oid ,
  304. length ) ;
  305. // if the oid don't match the class or it is shorter than the
  306. // class go on to the next one.
  307. // If the oid requested is shorter than the class we can't stop
  308. // otherwise we'll point to a wrong (longest match) class.
  309. if (status != 0 ||
  310. VarBind->name.idLength < class_info[ index ].var_index)
  311. continue;
  312. vindex = VarBind->name.ids[ class_info[ index ].var_index - 1 ] ;
  313. // cs - added the vindex verification to make sure that the varbind
  314. // oid definitely belongs in this class (fixed partial table oids)
  315. if ( vindex >= class_info[ index ].min_index &&
  316. vindex <= class_info[ index ].max_index)
  317. {
  318. *cindex = index ;
  319. return SUCCESS ;
  320. }
  321. }
  322. // Failed to match by walking list backwards (longest match)
  323. // so OID supplied is shorter than expected (e.g., partial OID supplied)
  324. // Try matching by forward walking...
  325. for (index = 0; index < CLASS_TABLE_MAX; index++ ) {
  326. status = SNMP_oidncmp( &VarBind->name ,
  327. class_info[ index ].oid ,
  328. VarBind->name.idLength ) ;
  329. if ( status == 0 ) {
  330. *cindex = index ;
  331. return SUCCESS ;
  332. }
  333. }
  334. return FAILURE ;
  335. } /* end of FindClass() */
  336. /*
  337. * ResolveGetNext
  338. *
  339. * Determines the class, the variable and the instance that the
  340. * GetNext request is to be performed on. This is a recursive
  341. * routine. The input arguments VarBind and class may be modified
  342. * as part of the resolution.
  343. *
  344. * The rules for getnext are:
  345. * 1. No instance and no variable specified so return the first
  346. * variable for the first instance.
  347. * 2. No instance specified but a variable is specified so return
  348. * the variable for the first instance.
  349. * 3. An instance and a variable are specified
  350. * Follow 3a,4b for Non Tables
  351. * Follow 3b, 4b, 5b for Tables
  352. *
  353. * 3a.Return the next variable for the instance.
  354. * 4a.An instance and a variable are specified but the variable is the
  355. * last variable in the group so return the first variable for the
  356. * next group.
  357. * If there is no next group return FAILURE.
  358. *
  359. * 3b. Return the variable for the next instance ( walk down the column).
  360. * 4b. Reached the bottom of the column, start at the top of next column.
  361. * 5b. An instance and a variable are specified but it is the last
  362. * variable and the last instace so roll to the next group (class).
  363. * If there is no next group return FAILURE.
  364. *
  365. * Arguments:
  366. *
  367. * VarBind Variable value pair
  368. * cindex Index into the class_info
  369. * vindex address to specify variable for the get
  370. *
  371. * Return Codes:
  372. *
  373. * SUCCESS Able to resolve the request to a class, variable
  374. * and instance
  375. * FAILURE Unable to resolve the request within this MIB
  376. *
  377. */
  378. UINT
  379. ResolveGetNext( IN OUT RFC1157VarBind *VarBind ,
  380. IN OUT UINT *cindex ,
  381. IN OUT UINT *vindex ,
  382. OUT AsnObjectIdentifier *instance )
  383. {
  384. UINT status ;
  385. access_mode_t tmpAccess ;
  386. /*
  387. * We've come in with a pointer to the class, to start with
  388. * Do we have a variable specified?
  389. */
  390. *vindex = 0 ;
  391. if (VarBind->name.idLength < class_info[ *cindex ].var_index ) {
  392. /*
  393. * No variable specified. so pick the first variable (if it exists)
  394. * to start the search for a valid variable.
  395. * If not roll over to the next class.
  396. * Instnace is 0 for non Tables, and the first instance for Tables.
  397. */
  398. if ( class_info[ *cindex ].min_index <= class_info[ *cindex ].max_index) {
  399. *vindex = class_info[ *cindex ].min_index ;
  400. goto StartSearchAt;
  401. } else {
  402. goto BumpClass;
  403. }
  404. } else {
  405. /*
  406. * Yes, a variable is specified.
  407. * If it is below min_index, start testing for a valid variable at the min_index.
  408. * If it is ablove max_index roll over to the next class.
  409. * If we change the variable, Instance is reset to the first (or the only) Instance.
  410. */
  411. *vindex = VarBind->name.ids[ class_info[ *cindex ].var_index - 1 ] ;
  412. if ( *vindex < class_info[ *cindex ].min_index) {
  413. *vindex = class_info[ *cindex ].min_index ;
  414. goto StartSearchAt;
  415. }
  416. if ( *vindex > class_info[ *cindex ].max_index)
  417. goto BumpClass;
  418. /*
  419. * A valid variable for this class is specified. Table & NonTable are treated
  420. * differently.
  421. * In case of Non Tables:
  422. * if instance is specified, we start the serach for a valid variable at the
  423. * next variable.
  424. * if no instnace is specified, we start search at the specified variable.
  425. *
  426. * In case of Tables:
  427. * We may have
  428. * a. No Instance start at the 1st Instance
  429. * b. Partial instance start at the 1st Instance
  430. * c. Invalid instance start at the 1st Instance
  431. * d. Valid Instance start at the next Instance
  432. * All these cases will be handled by the FindNextInstance
  433. * Hence first check that access of the given vaiable, if it is readable
  434. * get the Next Instance. If not start the search for a valid variable at the next
  435. * variable.
  436. */
  437. if ( class_info[ *cindex ].table == NON_TABLE ) {
  438. /* test for the Instance */
  439. if ( VarBind->name.idLength > class_info[ *cindex ].var_index)
  440. (*vindex)++ ;
  441. goto StartSearchAt;
  442. } else {
  443. /* Start Table case */
  444. tmpAccess = class_info[ *cindex ].variable[ *vindex ].access_mode ;
  445. if ( ( tmpAccess == NSM_READ_ONLY ) || (tmpAccess == NSM_READ_WRITE) ) {
  446. /*
  447. * readable Variable, walk down the column
  448. */
  449. status = ( *class_info[ *cindex ].FindNextInstance )
  450. ( (ObjectIdentifier *)&(VarBind->name) ,
  451. (ObjectIdentifier *)instance ) ;
  452. if (status == SNMP_ERRORSTATUS_NOERROR) {
  453. SNMP_oidfree ( &VarBind->name ) ;
  454. if (! SNMP_oidcpy ( &VarBind->name,
  455. class_info[*cindex ].variable[*vindex].oid ) )
  456. {
  457. return FAILURE;
  458. }
  459. if (!SNMP_oidappend ( &VarBind->name, instance ))
  460. {
  461. return FAILURE;
  462. }
  463. return SUCCESS ;
  464. /* we are all done */
  465. }
  466. }
  467. /*
  468. * Either at end of the column, or variable specified is non Readable.
  469. * Hence we need to move to the next column,
  470. * This means we start at the 1st instnace.
  471. */
  472. (*vindex)++ ;
  473. goto StartSearchAt;
  474. /* End Table case */
  475. }
  476. /* end of variable specified case */
  477. }
  478. StartSearchAt:
  479. /*
  480. * We have a start variable in *vindex.
  481. * At this point we are moving to the next column in case of a Table
  482. * Hence if we can't find an NextInstance ( empty Table), move to the
  483. * next class.
  484. */
  485. status = FAILURE;
  486. while ( *vindex <= class_info[ *cindex ].max_index) {
  487. tmpAccess = class_info[ *cindex ].variable[ *vindex ].access_mode ;
  488. if ( ( tmpAccess == NSM_READ_ONLY ) || (tmpAccess == NSM_READ_WRITE) ) {
  489. status = SUCCESS;
  490. break;
  491. } else {
  492. (*vindex)++;
  493. }
  494. }
  495. if ( status == SUCCESS) {
  496. /*
  497. * we hava a valid variable, get the instance
  498. */
  499. SNMP_oidfree ( &VarBind->name ) ;
  500. if (!SNMP_oidcpy ( &VarBind->name, class_info[ *cindex ].variable[*vindex ].oid ))
  501. {
  502. return FAILURE;
  503. }
  504. if ( class_info[ *cindex ].table == NON_TABLE) {
  505. instance->ids[ 0 ] = 0 ;
  506. instance->idLength = 1 ;
  507. if (!SNMP_oidappend ( &VarBind->name, instance ))
  508. {
  509. return FAILURE;
  510. }
  511. return SUCCESS ;
  512. } else {
  513. status = ( *class_info[ *cindex ].FindNextInstance )
  514. ( (ObjectIdentifier *)&(VarBind->name) ,
  515. (ObjectIdentifier *)instance ) ;
  516. if (status == SNMP_ERRORSTATUS_NOERROR) {
  517. if (!SNMP_oidappend ( &VarBind->name, instance ))
  518. {
  519. return FAILURE;
  520. }
  521. return SUCCESS ;
  522. }
  523. }
  524. }
  525. /*
  526. * Come here to move on to the next class
  527. */
  528. BumpClass:
  529. {
  530. (*cindex)++ ;
  531. if ( *cindex >= CLASS_TABLE_MAX)
  532. return FAILURE ;
  533. SNMP_oidfree( &VarBind->name );
  534. if (!SNMP_oidcpy ( &VarBind->name, class_info[ *cindex ].oid ))
  535. {
  536. return FAILURE;
  537. }
  538. status = ResolveGetNext( VarBind, cindex, vindex, instance) ;
  539. return status ;
  540. }
  541. // This oughtn't to happen
  542. return FAILURE ;
  543. } /* end of ResolveGetNext() */
  544. #ifndef TRAPS
  545. //
  546. // If there are no traps, TrapInit() is still needed.
  547. // If there are traps, all this code appears in
  548. // generated file trap.c
  549. //
  550. UINT number_of_traps = 0 ;
  551. trap_t
  552. trap_info[] = {
  553. { NULL, 0, 0, 0, NULL }
  554. } ;
  555. extern
  556. trap_t trap_info[] ;
  557. extern
  558. UINT number_of_traps ;
  559. extern HANDLE hEnabledTraps ;
  560. extern HANDLE hTrapQMutex ;
  561. /*
  562. * TrapInit
  563. *
  564. * This routine initializes the trap handle.
  565. *
  566. * Arguments:
  567. *
  568. * hPollForTrapEvent handle for traps - this is used to coordinate
  569. * between the Extendible Agent and this Extension
  570. * Agent.
  571. * - NULL indicates no traps
  572. * - value from CreateEvent() indicates traps
  573. * are implemented and the Extendible agent
  574. * must poll for them
  575. *
  576. * Return Code:
  577. *
  578. * SUCCESS Successful initialization
  579. * FAILURE Unable to initialize
  580. *
  581. |=========================================================================
  582. | There are no Traps associated with the HostMIB. Consequently this
  583. | routine is taken over and used to create a handle to a timer rather
  584. | than an event.
  585. |
  586. | We want to be entered at "SnmpExtensionTrap()" (in "HOSTMIB.C") on
  587. | a periodic interval. When entered, we won't really do any trap processing,
  588. | instead we'll refresh the cached information associated with SNMP
  589. | attribute "hrProcessorLoad" (in "HRPROCES.C") thru a call to function
  590. | "hrProcessLoad_Refresh()" (also in "HRPROCES.C").
  591. |
  592. | So the contents of this standard function is replaced. (Note that the
  593. | "hTrapQMutex" is no longer created).
  594. */
  595. VOID
  596. TrapInit( IN OUT HANDLE *hPollForTrapEvent )
  597. {
  598. #if 0
  599. // The default value for traps is NULL indicating NO traps.
  600. *hPollForTrapEvent = NULL ;
  601. hTrapQMutex = NULL ;
  602. // Call to CreateEvent uses the default security descriptor (therefore
  603. // the handle is not inheritable), flags auto reset (no call to ResetEvent()
  604. // required), flags no signal to be sent at the initial state, and does
  605. // not specify a name for this event.
  606. //
  607. // If the CreateEvent() fails the value returned is NULL so traps
  608. // are not enabled. Otherwise the setting of this event with will cause
  609. // the Extendible Agent to call this Extension Agent's SnmpExtensionTrap
  610. // routine to collect any traps.
  611. *hPollForTrapEvent = CreateEvent( NULL , // Address of security attrib
  612. FALSE , // Flag for manual-reset event
  613. FALSE , // Flag for initial state
  614. NULL ) ; // Address of event-object name
  615. //
  616. // Save the handle in a global variable for use later in setting a trap.
  617. //
  618. hEnabledTraps = *hPollForTrapEvent ;
  619. //
  620. // Create Mutex for assuring single thread access to enque/dequeue on trap_q
  621. hTrapQMutex = CreateMutex( NULL, // Address of security attrib
  622. FALSE, // Mutex is not initially owned
  623. NULL ) ; // Mutex is unnamed
  624. return ;
  625. #endif
  626. /*
  627. |========================
  628. | Special HostMIB code:
  629. */
  630. LARGE_INTEGER due_time; /* When the timer first goes off */
  631. LONG period; /* Frequency: every minute */
  632. BOOL waitable; /* Status from SetWaitable() */
  633. *hPollForTrapEvent = NULL ;
  634. /* Attempt the creation of a waitable timer . . . */
  635. *hPollForTrapEvent = CreateWaitableTimer(NULL, // Security
  636. FALSE, // = Auto-resetting
  637. NULL // = No name
  638. );
  639. /*
  640. | Set a negative due time to mean "relative": We want it to go off
  641. | in 30 seconds. Ticks are 100 ns or 1/10th of a millionth of a second.
  642. |
  643. */
  644. due_time.QuadPart = 10000000 * (-30);
  645. /*
  646. | Set the period in milliseconds to 1 minute.
  647. */
  648. period = 1000 * 60;
  649. /* If we actually managed to create it, start it */
  650. if (*hPollForTrapEvent != NULL) {
  651. waitable =
  652. SetWaitableTimer(*hPollForTrapEvent, // Handle to timer
  653. &due_time, // "Due Time" to go off
  654. period, // Length of period in ms.
  655. NULL, // no completion routine
  656. NULL, // no arg to comp. routine
  657. FALSE // no power-resume in NT
  658. );
  659. }
  660. } /* end of TrapInit() */
  661. #endif /* #ifndef TRAPS */