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.

1783 lines
55 KiB

  1. /*
  2. * HrStorageEntry.c v0.10
  3. * Generated in conjunction with Management Factory scripts:
  4. * script version: SNMPv1, 0.16, Apr 25, 1996
  5. * project: D:\TEMP\EXAMPLE\HOSTMIB
  6. ****************************************************************************
  7. * *
  8. * (C) Copyright 1995 DIGITAL EQUIPMENT CORPORATION *
  9. * *
  10. * This software is an unpublished work protected under the *
  11. * the copyright laws of the United States of America, all *
  12. * rights reserved. *
  13. * *
  14. * In the event this software is licensed for use by the United *
  15. * States Government, all use, duplication or disclosure by the *
  16. * United States Government is subject to restrictions as set *
  17. * forth in either subparagraph (c)(1)(ii) of the Rights in *
  18. * Technical Data And Computer Software Clause at DFARS *
  19. * 252.227-7013, or the Commercial Computer Software Restricted *
  20. * Rights Clause at FAR 52.221-19, whichever is applicable. *
  21. * *
  22. ****************************************************************************
  23. *
  24. * Facility:
  25. *
  26. * Windows NT SNMP Extension Agent
  27. *
  28. * Abstract:
  29. *
  30. * This module contains the code for dealing with the get, set, and
  31. * instance name routines for the HrStorageEntry.
  32. * Actual instrumentation code is supplied by the developer.
  33. *
  34. * Functions:
  35. *
  36. * A get and set routine for each attribute in the class.
  37. *
  38. * The routines for instances within the class, plus the cache
  39. * initialization function "Gen_Hrstorage_Cache()".
  40. *
  41. * Author:
  42. *
  43. * D. D. Burns @ Webenable Inc
  44. *
  45. * Revision History:
  46. *
  47. * V1.00 - 04/17/97 D. D. Burns Genned: Thu Nov 07 16:40:22 1996
  48. * V1.01 - 05/15/97 D. D. Burns Move Disk Label/Size acquisitions
  49. * to cache from real-time
  50. * V1.02 - 06/18/97 D. D. Burns Add spt to scan event log for
  51. * allocation failures
  52. *
  53. */
  54. #include <nt.h>
  55. #include <ntrtl.h>
  56. #include <nturtl.h>
  57. #include <windows.h>
  58. #include <malloc.h>
  59. #include <snmp.h>
  60. #include "mib.h"
  61. #include "smint.h"
  62. #include "hostmsmi.h"
  63. #include "user.h" /* Developer supplied include file */
  64. #include "HMCACHE.H" /* Cache-related definitions */
  65. #include "string.h" /* For string manipulation in "Gen_Hrstorage_Cache"*/
  66. #include "stdio.h" /* For sprintf */
  67. /*
  68. |==============================================================================
  69. | Function prototypes for this module.
  70. |
  71. */
  72. /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */
  73. static UINT
  74. ScanLog_Failures(
  75. CHAR *device
  76. );
  77. #if defined(CACHE_DUMP)
  78. /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */
  79. static void
  80. debug_print_hrstorage(
  81. CACHEROW *row /* Row in hrstorage table */
  82. );
  83. #endif
  84. /*
  85. |==============================================================================
  86. | Cache Refresh Time
  87. |
  88. | The cache for the hrStorage and hrFSTable tables are refreshed automatically
  89. | when a request arrives at the hrStorage --AND-- the cache is older than
  90. | CACHE_MAX_AGE in seconds.
  91. |
  92. */
  93. static
  94. LARGE_INTEGER cache_time; // 100ns Timestamp of cache (when last refreshed)
  95. #define CACHE_MAX_AGE 120 // Maximum age in seconds
  96. /*
  97. |==============================================================================
  98. | Create the list-head for the HrStorage table cache.
  99. |
  100. | This list-head is globally accessible so the logic that loads hrFSTable
  101. | can scan this cache for matches (among other reasons).
  102. |
  103. | (This macro is defined in "HMCACHE.H").
  104. */
  105. CACHEHEAD_INSTANCE(hrStorage_cache, debug_print_hrstorage);
  106. /*
  107. |==============================================================================
  108. | Local string for this kind of "storage".
  109. */
  110. #define VM "Virtual Memory"
  111. /*
  112. * ============================================================================
  113. * GetHrStorageIndex
  114. * A unique value for each logical storage are contained by the host.
  115. *
  116. * Gets the value for HrStorageIndex.
  117. *
  118. * Arguments:
  119. *
  120. * outvalue address to return variable value
  121. * accesss Reserved for future security use
  122. * instance address of instance name as ordered native
  123. * data type(s)
  124. *
  125. * Return Codes:
  126. *
  127. * Standard PDU error codes.
  128. *
  129. * SNMP_ERRORSTATUS_NOERROR Successful get
  130. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  131. * mibtget.c v0.10
  132. *
  133. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  134. | hrStorageIndex
  135. |
  136. | ACCESS SYNTAX
  137. | read-only INTEGER (1..2147483647)
  138. |
  139. | "A unique value for each logical storage area contained by the host."
  140. |
  141. | DISCUSSION:
  142. |
  143. | The value of this attribute is always the number of drives reported by
  144. | "GetLogicalDrives" (excepting network drives) plus one (for reporting on
  145. | "Virtual Memory").
  146. |
  147. |============================================================================
  148. | 1.3.6.1.2.1.25.2.3.1.1.<instance>
  149. | | | | |
  150. | | | | *hrStorageIndex
  151. | | | *hrStorageEntry
  152. | | *-hrStorageTable
  153. | *-hrStorage
  154. */
  155. UINT
  156. GetHrStorageIndex(
  157. OUT Integer *outvalue ,
  158. IN Access_Credential *access ,
  159. IN InstanceName *instance )
  160. {
  161. ULONG index; /* As fetched from instance structure */
  162. CACHEROW *row; /* Row entry fetched from cache */
  163. /*
  164. | Grab the instance information
  165. */
  166. index = GET_INSTANCE(0);
  167. /*
  168. | Use it to find the right entry in the cache
  169. */
  170. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  171. return SNMP_ERRORSTATUS_GENERR;
  172. }
  173. /*
  174. | Return the "hrStorageIndex" value from this entry
  175. */
  176. *outvalue = row->attrib_list[HRST_INDEX].u.unumber_value;
  177. return SNMP_ERRORSTATUS_NOERROR ;
  178. } /* end of GetHrStorageIndex() */
  179. /*
  180. * ============================================================================
  181. * GetHrStorageType
  182. * The type of strage represented by this entry.
  183. *
  184. * Gets the value for HrStorageType.
  185. *
  186. * Arguments:
  187. *
  188. * outvalue address to return variable value
  189. * accesss Reserved for future security use
  190. * instance address of instance name as ordered native
  191. * data type(s)
  192. *
  193. * Return Codes:
  194. *
  195. * Standard PDU error codes.
  196. *
  197. * SNMP_ERRORSTATUS_NOERROR Successful get
  198. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  199. * mibtget.c v0.10
  200. *
  201. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  202. | hrStorageType
  203. |
  204. | ACCESS SYNTAX
  205. | read-only OBJECT IDENTIFIER
  206. |
  207. | "The type of storage represented by this entry."
  208. |
  209. | -- Registration for some storage types, for use with hrStorageType
  210. |
  211. | hrStorageOther OBJECT IDENTIFIER ::= { hrStorageTypes 1 }
  212. | hrStorageRam OBJECT IDENTIFIER ::= { hrStorageTypes 2 }
  213. | -- hrStorageVirtualMemory is temporary storage of swapped
  214. | -- or paged memory
  215. | hrStorageVirtualMemory OBJECT IDENTIFIER ::= { hrStorageTypes 3 }
  216. | hrStorageFixedDisk OBJECT IDENTIFIER ::= { hrStorageTypes 4 }
  217. | hrStorageRemovableDisk OBJECT IDENTIFIER ::= { hrStorageTypes 5 }
  218. | hrStorageFloppyDisk OBJECT IDENTIFIER ::= { hrStorageTypes 6 }
  219. | hrStorageCompactDisc OBJECT IDENTIFIER ::= { hrStorageTypes 7 }
  220. | hrStorageRamDisk OBJECT IDENTIFIER ::= { hrStorageTypes 8 }
  221. |
  222. | DISCUSSION:
  223. |
  224. | The value returned for this attribute is determined by indications from
  225. | "GetDriveType" for disks. For the "Virtual Memory" entry, the OID for
  226. | "hrStorageVirtualMemory" is returned.
  227. |
  228. |============================================================================
  229. | 1.3.6.1.2.1.25.2.3.1.2.<instance>
  230. | | | | |
  231. | | | | *hrStorageType
  232. | | | *hrStorageEntry
  233. | | *-hrStorageTable
  234. | *-hrStorage
  235. */
  236. UINT
  237. GetHrStorageType(
  238. OUT ObjectIdentifier *outvalue ,
  239. IN Access_Credential *access ,
  240. IN InstanceName *instance )
  241. {
  242. ULONG index; /* As fetched from instance structure */
  243. CACHEROW *row; /* Row entry fetched from cache */
  244. /*
  245. | Grab the instance information
  246. */
  247. index = GET_INSTANCE(0);
  248. /*
  249. | Use it to find the right entry in the cache
  250. */
  251. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  252. return SNMP_ERRORSTATUS_GENERR;
  253. }
  254. /*
  255. | By convention with the cache-building function "Gen_Hrstorage_Cache()",
  256. | the cached value is the right-most arc we must return as the value.
  257. |
  258. | Hence whatever cache entry we retrieve, we tack the number retrieved
  259. | from the cache for this attribute onto { hrStorageTypes ... }.
  260. */
  261. if ( (outvalue->ids = SNMP_malloc(10 * sizeof( UINT ))) == NULL) {
  262. return SNMP_ERRORSTATUS_GENERR;
  263. }
  264. outvalue->idLength = 10;
  265. /*
  266. | Load in the full hrStorageType OID:
  267. |
  268. | 1.3.6.1.2.1.25.2.1.n
  269. | | | |
  270. | | | *-Type indicator
  271. | | *-hrStorageTypes (OIDs specifying storage types)
  272. | *-hrStorage
  273. |
  274. */
  275. outvalue->ids[0] = 1;
  276. outvalue->ids[1] = 3;
  277. outvalue->ids[2] = 6;
  278. outvalue->ids[3] = 1;
  279. outvalue->ids[4] = 2;
  280. outvalue->ids[5] = 1;
  281. outvalue->ids[6] = 25;
  282. outvalue->ids[7] = 2;
  283. outvalue->ids[8] = 1;
  284. /* Cached Type indicator */
  285. outvalue->ids[9] = row->attrib_list[HRST_TYPE].u.unumber_value;
  286. return SNMP_ERRORSTATUS_NOERROR ;
  287. } /* end of GetHrStorageType() */
  288. /*
  289. * GetHrStorageDesc
  290. * A description of the type and instance of the storage described by this
  291. * entry.
  292. *
  293. * Gets the value for HrStorageDesc.
  294. *
  295. * Arguments:
  296. *
  297. * outvalue address to return variable value
  298. * accesss Reserved for future security use
  299. * instance address of instance name as ordered native
  300. * data type(s)
  301. *
  302. * Return Codes:
  303. *
  304. * Standard PDU error codes.
  305. *
  306. * SNMP_ERRORSTATUS_NOERROR Successful get
  307. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  308. * mibtget.c v0.10
  309. *
  310. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  311. | hrStorageDescr
  312. |
  313. | ACCESS SYNTAX
  314. | read-only DisplayString
  315. |
  316. | "A description of the type and instance of the storage described by this
  317. | entry."
  318. |
  319. | DISCUSSION:
  320. |
  321. | For the Virtual Memory entry, the string "Virtual Memory" is returned.
  322. |
  323. | For disks, a string composed of:
  324. | + the logical drive letter followed by
  325. | + the Volume Identification (for drives containing a volume)
  326. | in double quotes
  327. | + the Volume Serial Number
  328. |
  329. | For instance, the value of this variable for drive C might be
  330. | C: Label="Main Disk" Serial #=0030-34FE
  331. |
  332. | For speed, the label acquisition is done at cache-build time, and
  333. | as a consequence the removable drives are sampled only once.
  334. | ===========================================================================
  335. | 1.3.6.1.2.1.25.2.3.1.3.<instance>
  336. | | | | |
  337. | | | | *hrStorageDescr
  338. | | | *hrStorageEntry
  339. | | *-hrStorageTable
  340. | *-hrStorage
  341. */
  342. UINT
  343. GetHrStorageDesc(
  344. OUT Simple_DisplayString *outvalue ,
  345. IN Access_Credential *access ,
  346. IN InstanceName *instance )
  347. {
  348. ULONG index; /* As fetched from instance structure */
  349. CACHEROW *row; /* Row entry fetched from cache */
  350. /*
  351. | Grab the instance information
  352. */
  353. index = GET_INSTANCE(0);
  354. /*
  355. | Use it to find the right entry in the cache
  356. */
  357. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  358. return SNMP_ERRORSTATUS_GENERR;
  359. }
  360. /* Return the description that was computed at cache-build time */
  361. outvalue->length = strlen(row->attrib_list[HRST_DESCR].u.string_value);
  362. outvalue->string = row->attrib_list[HRST_DESCR].u.string_value;
  363. return SNMP_ERRORSTATUS_NOERROR ;
  364. } /* end of GetHrStorageDesc() */
  365. /*
  366. * GetHrStorageAllocationUnits
  367. * The size, in bytes, of the data objects allocated from this pool. If
  368. * this entry is monitoring sectors, blocks, buffers, or pack
  369. *
  370. * Gets the value for HrStorageAllocationUnits.
  371. *
  372. * Arguments:
  373. *
  374. * outvalue address to return variable value
  375. * accesss Reserved for future security use
  376. * instance address of instance name as ordered native
  377. * data type(s)
  378. *
  379. * Return Codes:
  380. *
  381. * Standard PDU error codes.
  382. *
  383. * SNMP_ERRORSTATUS_NOERROR Successful get
  384. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  385. * mibtget.c v0.10
  386. *
  387. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  388. | hrStorageAllocationUnits
  389. |
  390. | ACCESS SYNTAX
  391. | read-only INTEGER (1..2147483647)
  392. |
  393. | "The size, in bytes, of the data objects allocated from this pool. If this
  394. | entry is monitoring sectors, blocks, buffers, or packets, for example, this
  395. | number will commonly be greater than one. Otherwise this number will
  396. | typically be one."
  397. |
  398. | DISCUSSION:
  399. |
  400. | For Virtual Memory, the value returned is that provided as
  401. | "AllocationGranularity" after a call to "GetSystemInfo".
  402. |
  403. | For disks, the size of the "hrStorageAllocationUnits" value is computed as
  404. | the quantity "BytesPerSector * SectorsPerCluster" as returned by Win32 API
  405. | function "GetDiskFreeSpace".
  406. |
  407. | =============================================================================
  408. | 1.3.6.1.2.1.25.2.3.1.4.<instance>
  409. | | | | |
  410. | | | | *hrStorageAllocationUnits
  411. | | | *hrStorageEntry
  412. | | *-hrStorageTable
  413. | *-hrStorage
  414. */
  415. UINT
  416. GetHrStorageAllocationUnits(
  417. OUT Integer *outvalue ,
  418. IN Access_Credential *access ,
  419. IN InstanceName *instance )
  420. {
  421. ULONG index; /* As fetched from instance structure */
  422. CACHEROW *row; /* Row entry fetched from cache */
  423. /*
  424. | Grab the instance information
  425. */
  426. index = GET_INSTANCE(0);
  427. /*
  428. | Use it to find the right entry in the cache
  429. */
  430. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  431. return SNMP_ERRORSTATUS_GENERR;
  432. }
  433. *outvalue = row->attrib_list[HRST_ALLOC].u.number_value;
  434. return ( SNMP_ERRORSTATUS_NOERROR );
  435. } /* end of GetHrStorageAllocationUnits() */
  436. /*
  437. * GetHrStorageSize
  438. * The size of the storage represented by this entry, in units of
  439. * hrStorageAllocationUnits.
  440. *
  441. * Gets the value for HrStorageSize.
  442. *
  443. * Arguments:
  444. *
  445. * outvalue address to return variable value
  446. * accesss Reserved for future security use
  447. * instance address of instance name as ordered native
  448. * data type(s)
  449. *
  450. * Return Codes:
  451. *
  452. * Standard PDU error codes.
  453. *
  454. * SNMP_ERRORSTATUS_NOERROR Successful get
  455. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  456. * mibtget.c v0.10
  457. *
  458. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  459. | hrStorageSize
  460. |
  461. | ACCESS SYNTAX
  462. | read-write INTEGER (0..2147483647)
  463. |
  464. | "The size of the storage represented by this entry, in units of
  465. | hrStorageAllocationUnits."
  466. |
  467. | DISCUSSION:
  468. |
  469. | For Virtual Memory, the value returned is computed as "TotalPageFile" (as
  470. | returned by "GlobalMemoryStatus") divided by "AllocationGranularity" from
  471. | "GetSystemInfo".
  472. |
  473. | For disks, the "hrStorageSize" value is the value of "TotalNumberOfClusters"
  474. | as returned by Win32 API function "GetDiskFreeSpace".
  475. |
  476. | <POA-4> This variable is marked as ACCESS="read-write". It is unclear to me
  477. | what effect can be expected from a SET operation on this variable. I propose
  478. | making a SET operation have no effect.
  479. |
  480. | RESOLVED >>>>>>>
  481. | <POA-4> Leaving this read-only is fine.
  482. | RESOLVED >>>>>>>
  483. |
  484. | =============================================================================
  485. | 1.3.6.1.2.1.25.2.3.1.5.<instance>
  486. | | | | |
  487. | | | | *hrStorageSize
  488. | | | *hrStorageEntry
  489. | | *-hrStorageTable
  490. | *-hrStorage
  491. */
  492. UINT
  493. GetHrStorageSize(
  494. OUT Integer *outvalue ,
  495. IN Access_Credential *access ,
  496. IN InstanceName *instance )
  497. {
  498. ULONG index; /* As fetched from instance structure */
  499. CACHEROW *row; /* Row entry fetched from cache */
  500. /*
  501. | Grab the instance information
  502. */
  503. index = GET_INSTANCE(0);
  504. /*
  505. | Use it to find the right entry in the cache
  506. */
  507. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  508. return SNMP_ERRORSTATUS_GENERR;
  509. }
  510. *outvalue = row->attrib_list[HRST_SIZE].u.number_value;
  511. return ( SNMP_ERRORSTATUS_NOERROR ) ;
  512. } /* end of GetHrStorageSize() */
  513. /*
  514. * SetHrStorageSize
  515. * The size of the storage represented by this entry, in units of
  516. * hrStorageAllocationUnits.
  517. *
  518. * Sets the HrStorageSize value.
  519. *
  520. * Arguments:
  521. *
  522. * invalue address of value to set the variable
  523. * outvalue address to return the set variable value
  524. * access Reserved for future security use
  525. * instance address of instance name as ordered native
  526. * data type(s)
  527. *
  528. * Return Codes:
  529. *
  530. * Standard PDU error codes.
  531. *
  532. * SNMP_ERRORSTATUS_NOERROR Successful get
  533. * SNMP_ERRORSTATUS_BADVALUE Set value not in range
  534. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  535. * mibtset.ntc v0.10
  536. *
  537. | =============================================================================
  538. | 1.3.6.1.2.1.25.2.3.1.5.<instance>
  539. | | | | |
  540. | | | | *hrStorageSize
  541. | | | *hrStorageEntry
  542. | | *-hrStorageTable
  543. | *-hrStorage
  544. */
  545. UINT
  546. SetHrStorageSize(
  547. IN Integer *invalue ,
  548. OUT Integer *outvalue ,
  549. IN Access_Credential *access ,
  550. IN InstanceName *instance )
  551. {
  552. #if 0
  553. //debug debug debug debug debug
  554. static int x=0;
  555. if (x==0) {
  556. /*
  557. | If it is invoked here, the invocation
  558. | of it in mib.c must be removed.
  559. */
  560. Gen_HrDevice_Cache();
  561. x =1;
  562. }
  563. //debug debug debug debug debug
  564. #endif
  565. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  566. } /* end of SetHrStorageSize() */
  567. /*
  568. * GetHrStorageUsed
  569. * The amount of the storage represented by this entry that is allocated,
  570. * in units of hrStorageAllocationUnits.
  571. *
  572. * Gets the value for HrStorageUsed.
  573. *
  574. * Arguments:
  575. *
  576. * outvalue address to return variable value
  577. * accesss Reserved for future security use
  578. * instance address of instance name as ordered native
  579. * data type(s)
  580. *
  581. * Return Codes:
  582. *
  583. * Standard PDU error codes.
  584. *
  585. * SNMP_ERRORSTATUS_NOERROR Successful get
  586. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  587. * mibtget.c v0.10
  588. *
  589. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  590. | hrStorageUsed
  591. |
  592. | ACCESS SYNTAX
  593. | read-only INTEGER (0..2147483647)
  594. |
  595. | "The amount of the storage represented by this entry that is allocated, in
  596. | units of hrStorageAllocationUnits."
  597. |
  598. | DISCUSSION:
  599. |
  600. | For Virtual Memory, the value returned is computed as the quantity
  601. | "TotalPageFile" less "AvailPageFile" (as returned by "GlobalMemoryStatus")
  602. | divided by "AllocationGranularity" (as returned by "GetSystemInfo".
  603. |
  604. | For disks, the "hrStorageUsed" value is computed as the quantity
  605. | "TotalNumberOfClusters - NumberOfFreeClusters" as returned by Win32 API
  606. | function "GetDiskFreeSpace".
  607. |
  608. | ===========================================================================
  609. | 1.3.6.1.2.1.25.2.3.1.6.<instance>
  610. | | | | |
  611. | | | | *hrStorageUsed
  612. | | | *hrStorageEntry
  613. | | *-hrStorageTable
  614. | *-hrStorage
  615. */
  616. UINT
  617. GetHrStorageUsed(
  618. OUT Integer *outvalue ,
  619. IN Access_Credential *access ,
  620. IN InstanceName *instance )
  621. {
  622. ULONG index; /* As fetched from instance structure */
  623. CACHEROW *row; /* Row entry fetched from cache */
  624. /*
  625. | Grab the instance information
  626. */
  627. index = GET_INSTANCE(0);
  628. /*
  629. | Use it to find the right entry in the cache
  630. */
  631. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  632. return SNMP_ERRORSTATUS_GENERR;
  633. }
  634. *outvalue = row->attrib_list[HRST_USED].u.number_value;
  635. return ( SNMP_ERRORSTATUS_NOERROR ) ;
  636. } /* end of GetHrStorageUsed() */
  637. /*
  638. * GetHrStorageAllocationFailures
  639. * The number of requests for storage represented by this entry that could
  640. * not be honored due to not enough storage. It should be
  641. *
  642. * Gets the value for HrStorageAllocationFailures.
  643. *
  644. * Arguments:
  645. *
  646. * outvalue address to return variable value
  647. * accesss Reserved for future security use
  648. * instance address of instance name as ordered native
  649. * data type(s)
  650. *
  651. * Return Codes:
  652. *
  653. * Standard PDU error codes.
  654. *
  655. * SNMP_ERRORSTATUS_NOERROR Successful get
  656. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  657. * mibtget.c v0.10
  658. *
  659. |=============================================================================
  660. |hrStorageAllocationFailures
  661. |
  662. | ACCESS SYNTAX
  663. | read-only Counter
  664. |
  665. |"The number of requests for storage represented by this entry that could not
  666. |be honored due to not enough storage. It should be noted that as this object
  667. |has a SYNTAX of Counter, that it does not have a defined initial value.
  668. |However, it is recommended that this object be initialized to zero."
  669. |
  670. |DISCUSSION:
  671. |
  672. |<POA-5> This value as very problematical for both Virtual Memory and Disk
  673. |storage. There appear to be no Win32 APIs that report allocation failures for
  674. |either virtual memory or disk storage. I presume there may be performance
  675. |monitoring counters stored in the registry, however I'm not able to find the
  676. |documentation that describes where such information might be stored. For
  677. |disks, we need to be able to map whatever counters are stored into logical
  678. |drives (as that is how this table is organized).
  679. |
  680. |RESOLVED >>>>>>>
  681. |<POA-5> You would have to scan to event log looking for the out of virtual
  682. |memory and out of disk space events and count them.
  683. |RESOLVED >>>>>>>
  684. |=============================================================================
  685. | 1.3.6.1.2.1.25.2.3.1.7.<instance>
  686. | | | | |
  687. | | | | *hrStorageAllocationFailures
  688. | | | *hrStorageEntry
  689. | | *-hrStorageTable
  690. | *-hrStorage
  691. */
  692. UINT
  693. GetHrStorageAllocationFailures(
  694. OUT Counter *outvalue ,
  695. IN Access_Credential *access ,
  696. IN InstanceName *instance )
  697. {
  698. CHAR device[3]; /* Device Name build-buffer */
  699. ULONG index; /* As fetched from instance structure */
  700. CACHEROW *row; /* Row entry fetched from cache */
  701. /*
  702. | Grab the instance information
  703. */
  704. index = GET_INSTANCE(0);
  705. /*
  706. | Use it to find the right entry in the cache
  707. */
  708. if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) {
  709. return SNMP_ERRORSTATUS_GENERR;
  710. }
  711. /*
  712. | Load the "device[]" array with two characters, either something like "C:"
  713. | (indicating we're interested in allocation failures for "C:") or "VM"
  714. | if we want VM storage allocation failures.... from the HRST_DESCR string.
  715. */
  716. if (strcmp(row->attrib_list[HRST_DESCR].u.string_value, VM) == 0) {
  717. /* Storage is really "Virtual Memory" */
  718. device[0] = 'V';
  719. device[1] = 'M';
  720. }
  721. else {
  722. device[0] = row->attrib_list[HRST_DESCR].u.string_value[0];
  723. device[1] = row->attrib_list[HRST_DESCR].u.string_value[1];
  724. }
  725. device[2] = '\0'; /* Null-terminate */
  726. /* Riffle thru the Event Log looking for this device's failures */
  727. *outvalue = ScanLog_Failures( device );
  728. return SNMP_ERRORSTATUS_NOERROR ;
  729. } /* end of GetHrStorageAllocationFailures() */
  730. /*
  731. * HrStorageEntryFindInstance
  732. *
  733. * This routine is used to verify that the specified instance is
  734. * valid.
  735. *
  736. * Arguments:
  737. *
  738. * FullOid Address for the full oid - group, variable,
  739. * and instance information
  740. * instance Address for instance specification as an oid
  741. *
  742. * Return Codes:
  743. *
  744. * SNMP_ERRORSTATUS_NOERROR Instance found and valid
  745. * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance
  746. *
  747. */
  748. UINT
  749. HrStorageEntryFindInstance( IN ObjectIdentifier *FullOid ,
  750. IN OUT ObjectIdentifier *instance )
  751. {
  752. UINT tmp_instance ;
  753. //
  754. // Developer instrumentation code to find appropriate instance goes here.
  755. // For non-tables, it is not necessary to modify this routine. However, if
  756. // there is any context that needs to be set, it can be done here.
  757. //
  758. if ( FullOid->idLength <= HRSTORAGEENTRY_VAR_INDEX )
  759. // No instance was specified
  760. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  761. else if ( FullOid->idLength != HRSTORAGEENTRY_VAR_INDEX + 1 )
  762. // Instance length is more than 1
  763. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  764. else
  765. // The only valid instance for a non-table are instance 0. If this
  766. // is a non-table, the following code validates the instances. If this
  767. // is a table, developer modification is necessary below.
  768. tmp_instance = FullOid->ids[ HRSTORAGEENTRY_VAR_INDEX ] ;
  769. /*
  770. | Check for age-out and possibly refresh the entire cache for the
  771. | hrStorage table and hrFSTable before we check to see if the
  772. | instance is there.
  773. */
  774. if (hrStorageCache_hrFSTableCache_Refresh() == FALSE) {
  775. return SNMP_ERRORSTATUS_GENERR;
  776. }
  777. /*
  778. | For hrStorage, the instance arc(s) is a single arc, and it must
  779. | correctly select an entry in the hrStorageTable cache.
  780. | Check that here.
  781. */
  782. if ( FindTableRow(tmp_instance, &hrStorage_cache) == NULL ) {
  783. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  784. }
  785. else
  786. {
  787. // the instance is valid. Create the instance portion of the OID
  788. // to be returned from this call.
  789. instance->ids[ 0 ] = tmp_instance ;
  790. instance->idLength = 1 ;
  791. }
  792. return SNMP_ERRORSTATUS_NOERROR ;
  793. } /* end of HrStorageEntryFindInstance() */
  794. /*
  795. * HrStorageEntryFindNextInstance
  796. *
  797. * This routine is called to get the next instance. If no instance
  798. * was passed than return the first instance (1).
  799. *
  800. * Arguments:
  801. *
  802. * FullOid Address for the full oid - group, variable,
  803. * and instance information
  804. * instance Address for instance specification as an oid
  805. *
  806. * Return Codes:
  807. *
  808. * SNMP_ERRORSTATUS_NOERROR Instance found and valid
  809. * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance
  810. *
  811. */
  812. UINT
  813. HrStorageEntryFindNextInstance( IN ObjectIdentifier *FullOid ,
  814. IN OUT ObjectIdentifier *instance )
  815. {
  816. // Developer supplied code to find the next instance of class goes here.
  817. //
  818. // The purpose of this function is to indicate to the rest of the system
  819. // what the exact OID of the "next instance" is GIVEN THAT:
  820. //
  821. // a) The "FullOid" passed in will have enough arcs to specify
  822. // both the TABLE and the ATTRIBUTE in the table
  823. //
  824. // b) The "instance" OID array is always big enough to have
  825. // as many arcs as needed loaded into it by this function
  826. // to specify (exactly) the "next instance"
  827. //
  828. //
  829. // If this is a class with cardinality 1, no modification of this routine
  830. // is necessary unless additional context needs to be set.
  831. //
  832. // If the FullOid is so short that it does not specify an instance,
  833. // then the only instance of the class should be returned. If this is a
  834. // table, the first row of the table is returned. To do these things,
  835. // set the "instance" OID to just the right arcs such that when
  836. // concatenated onto the FullOid, the concatenation exactly specifies
  837. // the first instance of this attribute in the table.
  838. //
  839. // If an instance is specified and this is a non-table class, then
  840. // NOSUCHNAME is returned so that correct MIB rollover processing occurs.
  841. //
  842. // If this is a table, then the next instance is the one following the
  843. // current instance.
  844. //
  845. // If there are no more instances in the table, return NOSUCHNAME.
  846. //
  847. CACHEROW *row;
  848. ULONG tmp_instance;
  849. if ( FullOid->idLength <= HRSTORAGEENTRY_VAR_INDEX )
  850. {
  851. /*
  852. | Too short: must return the instance arc that selects the first
  853. | entry in the table if there is one.
  854. */
  855. tmp_instance = 0;
  856. }
  857. else {
  858. /*
  859. | There is at least one instance arc. Even if it is the only arc
  860. | we use it as the "index" in a request for the "NEXT" one.
  861. */
  862. tmp_instance = FullOid->ids[ HRSTORAGEENTRY_VAR_INDEX ] ;
  863. }
  864. /*
  865. | Check for age-out and possibly refresh the entire cache for the
  866. | hrStorage table and hrFSTable before we check to see if the
  867. | instance is there.
  868. */
  869. if (hrStorageCache_hrFSTableCache_Refresh() == FALSE) {
  870. return SNMP_ERRORSTATUS_GENERR;
  871. }
  872. /* Now go off and try to find the next instance in the table */
  873. if ((row = FindNextTableRow(tmp_instance, &hrStorage_cache)) == NULL) {
  874. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  875. }
  876. instance->ids[ 0 ] = row->index ;
  877. instance->idLength = 1 ;
  878. return SNMP_ERRORSTATUS_NOERROR ;
  879. } /* end of HrStorageEntryFindNextInstance() */
  880. /*
  881. * HrStorageEntryConvertInstance
  882. *
  883. * This routine is used to convert the object id specification of an
  884. * instance into an ordered native representation. The object id format
  885. * is that object identifier that is returned from the Find Instance
  886. * or Find Next Instance routines. It is NOT the full object identifier
  887. * that contains the group and variable object ids as well. The native
  888. * representation is an argc/argv-like structure that contains the
  889. * ordered variables that define the instance. This is specified by
  890. * the MIB's INDEX clause. See RFC 1212 for information about the INDEX
  891. * clause.
  892. *
  893. *
  894. * Arguments:
  895. *
  896. * oid_spec Address of the object id instance specification
  897. * native_spec Address to return the ordered native instance
  898. * specification
  899. *
  900. * Return Codes:
  901. *
  902. * SUCCESS Conversion complete successfully
  903. * FAILURE Unable to convert object id into native format
  904. *
  905. */
  906. UINT
  907. HrStorageEntryConvertInstance( IN ObjectIdentifier *oid_spec ,
  908. IN OUT InstanceName *native_spec )
  909. {
  910. static char *array; /* The address of this (char *) is passed back */
  911. /* as though it were an array of length 1 of these */
  912. /* types. */
  913. static ULONG inst; /* The address of this ULONG is passed back */
  914. /* (Obviously, no "free()" action is needed) */
  915. /* We only expect the one arc in "oid_spec" */
  916. inst = oid_spec->ids[0];
  917. array = (char *) &inst;
  918. native_spec->count = 1;
  919. native_spec->array = &array;
  920. return SUCCESS ;
  921. } /* end of HrStorageEntryConvertInstance() */
  922. /*
  923. * HrStorageEntryFreeInstance
  924. *
  925. * This routine is used to free an ordered native representation of an
  926. * instance name.
  927. *
  928. * Arguments:
  929. *
  930. * instance Address to return the ordered native instance
  931. * specification
  932. *
  933. * Return Codes:
  934. *
  935. *
  936. */
  937. void
  938. HrStorageEntryFreeInstance( IN OUT InstanceName *instance )
  939. {
  940. /* No action needed for hrStorageTable */
  941. } /* end of HrStorageEntryFreeInstance() */
  942. /*
  943. | End of Generated Code
  944. */
  945. /* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */
  946. /* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */
  947. /* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */
  948. BOOL
  949. hrStorageCache_hrFSTableCache_Refresh(
  950. void
  951. )
  952. /*
  953. | EXPLICIT INPUTS:
  954. |
  955. | None.
  956. |
  957. | IMPLICIT INPUTS:
  958. |
  959. | The "hrStorage_cache" CACHEHEAD structure and the time when
  960. | it was last refreshed in module-local cell "cache_time".
  961. | The "hrFSTable_cache" CACHEHEAD structure which depends on
  962. | the hrStorage_cache CACHEHEAD structure.
  963. |
  964. | OUTPUTS:
  965. |
  966. | On Success/Failure:
  967. | The function returns TRUE. Only if the cache-time has aged-out
  968. | is the cache actually rebuilt.
  969. |
  970. | On any Failure:
  971. | If during a rebuild there is an error, this function returns FALSE.
  972. | The state of the cache is indeterminate.
  973. |
  974. | THE BIG PICTURE:
  975. |
  976. | This function is invoked before any reference is made to any SNMP
  977. | variable in the hrStorage table. It checks to see
  978. | if the cache needs to be rebuilt based on the last time it was built.
  979. | Since the hrFSTable_cache depends on the hrStorage table,
  980. | hrFSTable_cache will be rebuilt whenever hrStorage table is rebuilt.
  981. |
  982. | The calls to this function are strategically located in the
  983. | "FindInstance" and "FindNextInstance" functions in "HRSTOENT.C"
  984. | (this module).
  985. |
  986. | OTHER THINGS TO KNOW:
  987. |
  988. */
  989. {
  990. LARGE_INTEGER now_time; /* Current System time in 100 ns ticks */
  991. /* Get the current time in 100 ns ticks*/
  992. NtQuerySystemTime (&now_time);
  993. /* If the cache is older than the maximum allowed time (in ticks) . . . */
  994. if ( (now_time.QuadPart - cache_time.QuadPart) > (CACHE_MAX_AGE * 10000000) )
  995. {
  996. if (Gen_Hrstorage_Cache())
  997. {
  998. // hrFSStorageIndex attribute of hrFSTable depends on the
  999. // the index of the hrStorageEntry
  1000. return (Gen_HrFSTable_Cache());
  1001. }
  1002. else
  1003. return FALSE;
  1004. }
  1005. return ( TRUE ); /* No Error (because no refresh) */
  1006. }
  1007. /* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */
  1008. /* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */
  1009. /* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */
  1010. BOOL
  1011. Gen_Hrstorage_Cache(
  1012. void
  1013. )
  1014. /*
  1015. | EXPLICIT INPUTS:
  1016. |
  1017. | None.
  1018. |
  1019. | IMPLICIT INPUTS:
  1020. |
  1021. | The module-local head of the cache for the HrStorage table,
  1022. | "hrStorage_cache".
  1023. |
  1024. | OUTPUTS:
  1025. |
  1026. | On Success:
  1027. | Function returns TRUE indicating that the cache has been fully
  1028. | populated with all "static" cache-able values.
  1029. |
  1030. | On any Failure:
  1031. | Function returns FALSE (indicating "not enough storage").
  1032. |
  1033. | THE BIG PICTURE:
  1034. |
  1035. | At subagent startup time, the cache for each table in the MIB is
  1036. | populated with rows for each row in the table. This function is
  1037. | invoked by the start-up code in "UserMibInit()" ("MIB.C") to
  1038. | populate the cache for the HrStorage table.
  1039. |
  1040. | OTHER THINGS TO KNOW:
  1041. |
  1042. | There is one of these function for every table that has a cache.
  1043. | Each is found in the respective source file.
  1044. |
  1045. |=============== From WebEnable Design Spec Rev 3 04/11/97==================
  1046. | DISCUSSION:
  1047. |
  1048. | Since this table is meant for diagnosing "out-of-storage" situations and
  1049. | given that the information is meant to be regarded from the point of view
  1050. | of an application, we simply report every instance of what would appear
  1051. | on the "Drive Bar" of the File Manager (excepting network drives) plus
  1052. | one more table entry to reflect information on "Virtual Memory".
  1053. |
  1054. | To this end, a combination of Win32 API functions "GetLogicalDrives",
  1055. | "GetVolumeInformation", "GetDriveType" and "GetDiskFreeSpace" are used to
  1056. | acquire the information for the SNMP attributes in this table.
  1057. |
  1058. | For reporting on "Virtual Memory", functions "GlobalMemoryStatus" and
  1059. | "GetSystemInfo" are invoked.
  1060. |============================================================================
  1061. | 1.3.6.1.2.1.25.2.1....
  1062. | | |
  1063. | | *-hrStorageTypes (OIDs specifying storage types)
  1064. | *-hrStorage
  1065. |
  1066. | 1.3.6.1.2.1.25.2.2....
  1067. | | |
  1068. | | *-hrMemorySize (standalone attribute)
  1069. | *-hrStorage
  1070. |
  1071. | 1.3.6.1.2.1.25.2.3....
  1072. | | |
  1073. | | *-hrStorageTable (the table)
  1074. | *-hrStorage
  1075. */
  1076. #define VOL_NAME_SIZE 256
  1077. #define DESCR_SIZE 384
  1078. {
  1079. CHAR temp[8]; /* Temporary buffer for first call */
  1080. LPSTR pDrvStrings; /* --> allocated storage for drive strings */
  1081. LPSTR pOriginal_DrvStrings; /* (Needed for final deallocation */
  1082. DWORD DS_request_len; /* Storage actually needed */
  1083. DWORD DS_current_len; /* Storage used on 2nd call */
  1084. ULONG table_index=0; /* hrStorageTable index counter */
  1085. CACHEROW *row; /* --> Cache structure for row-being built */
  1086. SYSTEM_INFO sys_info; /* Filled in by GetSystemInfo for VM */
  1087. LPSTR str_descr; /* String for disk label/serial description*/
  1088. TCHAR volname[VOL_NAME_SIZE+2]; /* Volume Name returned here */
  1089. DWORD volnamesize=VOL_NAME_SIZE; /* Size of volname buffer */
  1090. DWORD serial_number; /* Volume Serial Number */
  1091. DWORD max_comp_len; /* File system file-name component length */
  1092. DWORD filesys_flags; /* File System flags (GetVolInformation) */
  1093. CHAR descr[DESCR_SIZE]; /* Full description possibly built here */
  1094. DWORD SectorsPerCluster; /* GetDiskFreeSpace() cells */
  1095. DWORD BytesPerSector;
  1096. DWORD NumberOfFreeClusters;
  1097. DWORD TotalNumberOfClusters;
  1098. MEMORYSTATUS mem_status; /* Filled in by GlobalMemoryStatus */
  1099. NTSTATUS ntstatus; /* Generic return status */
  1100. /*
  1101. | Blow away any old copy of the cache
  1102. */
  1103. DestroyTable(&hrStorage_cache);
  1104. /*
  1105. | We're going to call GetLogicalDriveStrings() twice, once to get the proper
  1106. | buffer size, and the second time to actually get the drive strings.
  1107. |
  1108. | Bogus:
  1109. */
  1110. if ((DS_request_len = GetLogicalDriveStrings(2, temp)) == 0) {
  1111. /* Request failed altogether, can't initialize */
  1112. return ( FALSE );
  1113. }
  1114. /*
  1115. | Grab enough storage for the drive strings plus one null byte at the end
  1116. */
  1117. if ( (pOriginal_DrvStrings = pDrvStrings = malloc( (DS_request_len + 2) ) )
  1118. == NULL) {
  1119. /* Storage Request failed altogether, can't initialize */
  1120. return ( FALSE );
  1121. }
  1122. /* Go for all of the strings */
  1123. if ((DS_current_len = GetLogicalDriveStrings(DS_request_len, pDrvStrings))
  1124. == 0) {
  1125. /* Request failed altogether, can't initialize */
  1126. free( pOriginal_DrvStrings );
  1127. return ( FALSE );
  1128. }
  1129. /*
  1130. | Freshen the time on the cache
  1131. |
  1132. | Get the current system-time in 100ns intervals . . . */
  1133. ntstatus = NtQuerySystemTime (&cache_time);
  1134. /*
  1135. |==============================================================================
  1136. | As long as we've got an unprocessed drive-string. . .
  1137. */
  1138. while ( strlen(pDrvStrings) > 0 ) {
  1139. UINT drivetype; /* Type of the drive from "GetDriveType()" */
  1140. /*
  1141. | Get the drive-type so we can decide whether it should participate in
  1142. | this table.
  1143. */
  1144. drivetype = GetDriveType(pDrvStrings);
  1145. if ( drivetype == DRIVE_UNKNOWN
  1146. || drivetype == DRIVE_NO_ROOT_DIR
  1147. || drivetype == DRIVE_REMOTE /* No Remotes in HrStorage */
  1148. ) {
  1149. /* Step to next string, if any */
  1150. pDrvStrings += strlen(pDrvStrings) + 1;
  1151. continue;
  1152. }
  1153. /*
  1154. | OK, we want this one in the table, get a row-entry created.
  1155. */
  1156. if ((row = CreateTableRow( HRST_ATTRIB_COUNT ) ) == NULL) {
  1157. return ( FALSE ); // Out of memory
  1158. }
  1159. /* =========== hrStorageIndex ==========*/
  1160. row->attrib_list[HRST_INDEX].attrib_type = CA_NUMBER;
  1161. row->attrib_list[HRST_INDEX].u.unumber_value = ++table_index;
  1162. /* =========== hrStorageType ==========*/
  1163. row->attrib_list[HRST_TYPE].attrib_type = CA_NUMBER;
  1164. /*
  1165. | Based on the drive-type returned, we store a single number as
  1166. | the cached value of the hrStorageType attribute. When this attribute
  1167. | is fetched, the cached number forms the last arc in the OBJECT IDENTIFIER
  1168. | that actually specifies the type: { hrStorageTypes x }, where "x" is
  1169. | what gets stored.
  1170. */
  1171. switch (drivetype) {
  1172. case DRIVE_REMOVABLE:
  1173. row->attrib_list[HRST_TYPE].u.unumber_value = 5;
  1174. break;
  1175. case DRIVE_FIXED:
  1176. row->attrib_list[HRST_TYPE].u.unumber_value = 4;
  1177. break;
  1178. case DRIVE_CDROM:
  1179. row->attrib_list[HRST_TYPE].u.unumber_value = 7;
  1180. break;
  1181. case DRIVE_RAMDISK:
  1182. row->attrib_list[HRST_TYPE].u.unumber_value = 8;
  1183. break;
  1184. default:
  1185. row->attrib_list[HRST_TYPE].u.unumber_value = 1; // "Other"
  1186. break;
  1187. }
  1188. /* =========== hrStorageDescr ==========
  1189. |
  1190. | We try and fetch the volume label here, to get a string
  1191. | that may look like:
  1192. | C: Label="Main Disk" Serial #=0030-34FE
  1193. |
  1194. | Handle all kinds of disk storage here:
  1195. |
  1196. | Try to get volume label and serial number. If we fail, we just give
  1197. | 'em the root-path name.
  1198. |
  1199. | Presume that we'll fail, and just return the root-path string.
  1200. */
  1201. str_descr = pDrvStrings;
  1202. /*
  1203. | Suppress any attempt by the system to make the user put a volume in a
  1204. | removable drive.
  1205. */
  1206. SetErrorMode(SEM_FAILCRITICALERRORS);
  1207. if (GetVolumeInformation(pDrvStrings, /* drive name */
  1208. volname, /* Volume Name Buffer */
  1209. volnamesize, /* Size of buffer */
  1210. &serial_number, /* Vol. # Returned here */
  1211. &max_comp_len, /* Max filename length */
  1212. &filesys_flags, /* File System flags */
  1213. NULL, /* Name of Filesystem */
  1214. 0 /* Length of name */
  1215. )) {
  1216. /*
  1217. | We got something back.
  1218. |
  1219. | If we have room given string lengths, build a description:
  1220. |
  1221. | <root path> Label:<volume name> Serial Number: <#>
  1222. */
  1223. #define SPRINTF_FORMAT "%s Label:%s Serial Number %x"
  1224. if ((strlen(SPRINTF_FORMAT) + strlen(volname) + strlen(str_descr))
  1225. < DESCR_SIZE) {
  1226. sprintf(descr,
  1227. SPRINTF_FORMAT,
  1228. str_descr, // root-path
  1229. volname, // volume name
  1230. serial_number); // volume serial #
  1231. str_descr = descr;
  1232. }
  1233. }
  1234. row->attrib_list[HRST_DESCR].attrib_type = CA_STRING;
  1235. /*
  1236. | Note:
  1237. | The convention is established that the first characters of
  1238. | this description string is always the device-string (e.g. "C:")
  1239. | or the value of local symbol "VM" ("Virtual Memory").
  1240. |
  1241. | Code in "GetHrStorageAllocationFailures()" attempts to extract
  1242. | the drive letter (or "Virtual Memory") from the beginning of this
  1243. | string in order to determine allocation failures from the
  1244. | Event Log(!).
  1245. */
  1246. if ( (row->attrib_list[HRST_DESCR].u.string_value
  1247. = ( LPSTR ) malloc(strlen(str_descr) + 1)) == NULL) {
  1248. return ( FALSE ); /* out of memory */
  1249. }
  1250. /* Copy the Value into the space */
  1251. strcpy(row->attrib_list[HRST_DESCR].u.string_value, str_descr);
  1252. row->attrib_list[HRST_ALLOC].attrib_type = CA_NUMBER;
  1253. row->attrib_list[HRST_SIZE].attrib_type = CA_NUMBER;
  1254. row->attrib_list[HRST_USED].attrib_type = CA_NUMBER;
  1255. /*
  1256. | Handle all kinds of disk storage info here:
  1257. |
  1258. | Try to get volume statistics via GetDiskFreeSpace().
  1259. */
  1260. if (GetDiskFreeSpace(pDrvStrings, // drive
  1261. &SectorsPerCluster,
  1262. &BytesPerSector,
  1263. &NumberOfFreeClusters,
  1264. &TotalNumberOfClusters
  1265. )) {
  1266. /* Success */
  1267. /* =========== hrStorageAllocationUnits ==========*/
  1268. row->attrib_list[HRST_ALLOC].u.unumber_value =
  1269. BytesPerSector * SectorsPerCluster;
  1270. /* =========== hrStorageSize ==========*/
  1271. row->attrib_list[HRST_SIZE].u.unumber_value = TotalNumberOfClusters;
  1272. /* =========== hrStorageUsed ==========*/
  1273. row->attrib_list[HRST_USED].u.unumber_value =
  1274. TotalNumberOfClusters - NumberOfFreeClusters;
  1275. }
  1276. else {
  1277. /* Failure */
  1278. /* =========== hrStorageAllocationUnits ==========*/
  1279. row->attrib_list[HRST_ALLOC].u.unumber_value = 0;
  1280. /* =========== hrStorageSize ==========*/
  1281. row->attrib_list[HRST_SIZE].u.unumber_value = 0;
  1282. /* =========== hrStorageUsed ==========*/
  1283. row->attrib_list[HRST_USED].u.unumber_value = 0;
  1284. }
  1285. /* =========== hrStorageAllocationFailures ==========*/
  1286. row->attrib_list[HRST_FAILS].attrib_type = CA_COMPUTED;
  1287. SetErrorMode(0); /* Turn error suppression mode off */
  1288. /*
  1289. | Now insert the filled-in CACHEROW structure into the
  1290. | cache-list for the hrStorageTable.
  1291. */
  1292. if (AddTableRow(row->attrib_list[HRST_INDEX].u.unumber_value, /* Index */
  1293. row, /* Row */
  1294. &hrStorage_cache /* Cache */
  1295. ) == FALSE) {
  1296. return ( FALSE ); /* Internal Logic Error! */
  1297. }
  1298. /* Step to next string, if any */
  1299. pDrvStrings += strlen(pDrvStrings) + 1;
  1300. }
  1301. free( pOriginal_DrvStrings );
  1302. /*
  1303. |==============================================================================
  1304. | Now handle Virtual Memory as a special case.
  1305. |==============================================================================
  1306. */
  1307. if ((row = CreateTableRow( HRST_ATTRIB_COUNT ) ) == NULL) {
  1308. return ( FALSE ); // Out of memory
  1309. }
  1310. /* =========== hrStorageIndex ==========*/
  1311. row->attrib_list[HRST_INDEX].attrib_type = CA_NUMBER;
  1312. row->attrib_list[HRST_INDEX].u.unumber_value = ++table_index;
  1313. /* =========== hrStorageType ==========*/
  1314. row->attrib_list[HRST_TYPE].attrib_type = CA_NUMBER;
  1315. row->attrib_list[HRST_TYPE].u.unumber_value = 3; /* Virtual Memory */
  1316. /* =========== hrStorageDescr ==========*/
  1317. row->attrib_list[HRST_DESCR].attrib_type = CA_STRING;
  1318. if ( (row->attrib_list[HRST_DESCR].u.string_value
  1319. = ( LPSTR ) malloc(strlen(VM) + 1)) == NULL) {
  1320. return ( FALSE ); /* out of memory */
  1321. }
  1322. strcpy(row->attrib_list[HRST_DESCR].u.string_value, VM);
  1323. /* =========== hrStorageAllocationUnits ==========*/
  1324. GetSystemInfo(&sys_info);
  1325. row->attrib_list[HRST_ALLOC].attrib_type = CA_NUMBER;
  1326. row->attrib_list[HRST_ALLOC].u.unumber_value =
  1327. sys_info.dwAllocationGranularity;
  1328. /* =========== hrStorageSize ==========*/
  1329. /* Acquire current memory statistics */
  1330. GlobalMemoryStatus(&mem_status);
  1331. row->attrib_list[HRST_SIZE].attrib_type = CA_NUMBER;
  1332. row->attrib_list[HRST_SIZE].u.unumber_value =
  1333. (DWORD)(mem_status.dwTotalPageFile / sys_info.dwAllocationGranularity);
  1334. /* =========== hrStorageUsed ==========*/
  1335. row->attrib_list[HRST_USED].attrib_type = CA_NUMBER;
  1336. row->attrib_list[HRST_USED].attrib_type =
  1337. (int)((mem_status.dwTotalPageFile - mem_status.dwAvailPageFile)
  1338. / sys_info.dwAllocationGranularity);
  1339. /* =========== hrStorageAllocationFailures ==========*/
  1340. row->attrib_list[HRST_FAILS].attrib_type = CA_COMPUTED;
  1341. /*
  1342. | Now insert the filled-in CACHEROW structure into the
  1343. | cache-list for the hrStorageTable.
  1344. */
  1345. if (AddTableRow(row->attrib_list[HRST_INDEX].u.unumber_value, /* Index */
  1346. row, /* Row */
  1347. &hrStorage_cache /* Cache */
  1348. ) == FALSE) {
  1349. return ( FALSE ); /* Internal Logic Error! */
  1350. }
  1351. /*
  1352. |==============================================================================
  1353. | End of Virtual Memory
  1354. |==============================================================================
  1355. */
  1356. #if defined(CACHE_DUMP)
  1357. PrintCache(&hrStorage_cache);
  1358. #endif
  1359. /*
  1360. | Initialization of this table's cache succeeded
  1361. */
  1362. return (TRUE);
  1363. }
  1364. /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */
  1365. /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */
  1366. /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */
  1367. static UINT
  1368. ScanLog_Failures(
  1369. CHAR *device
  1370. )
  1371. /*
  1372. | EXPLICIT INPUTS:
  1373. |
  1374. | "device" is either the string "VM" (for "Virtual Memory") or
  1375. | the logical device for which we're looking for failures (e.g. "C:").
  1376. |
  1377. | IMPLICIT INPUTS:
  1378. |
  1379. | The System Event log file.
  1380. |
  1381. | OUTPUTS:
  1382. |
  1383. | On Success/Failure:
  1384. | Function returns the number of storage allocation failures
  1385. | found for the specified device.
  1386. |
  1387. | THE BIG PICTURE:
  1388. |
  1389. | This is a "helper" function for routine "GetHrStorageAllocationFailures"
  1390. | within this module.
  1391. |
  1392. | OTHER THINGS TO KNOW:
  1393. |
  1394. | We scan backwards (in time) thru the Event Log until we hit the
  1395. | "Event Logging Started" event record (because, presumably, we don't
  1396. | care about failures that happened before the system last came up).
  1397. */
  1398. /*
  1399. | These symbols select the "Event Log Started" informational message.
  1400. */
  1401. #define EVENTLOG_START_ID 0x80001775
  1402. #define EVENTLOG_START_TYPE 4
  1403. #define EVENTLOG_START_SRC "EventLog"
  1404. {
  1405. #define EVL_BUFFER_SIZE 2048
  1406. EVENTLOGRECORD *pevlr;
  1407. BYTE bBuffer[EVL_BUFFER_SIZE];
  1408. DWORD dwRead, dwNeeded, cRecords;
  1409. HANDLE h;
  1410. BOOL keep_scanning = TRUE;
  1411. UINT alloc_failures = 0;
  1412. /*
  1413. | Open the System event log
  1414. */
  1415. h = OpenEventLog(NULL, /* local computer */
  1416. "System" /* source name */
  1417. );
  1418. if (h == NULL) {
  1419. return ( alloc_failures );
  1420. }
  1421. pevlr = (EVENTLOGRECORD *) &bBuffer;
  1422. /*
  1423. | Read records sequentially "Backward in Time" until there
  1424. | are no more, or we hit the "Event Logging Started" event.
  1425. |
  1426. | Read a "Slug 'o Records":
  1427. */
  1428. while (ReadEventLog(h, // event log handle
  1429. EVENTLOG_BACKWARDS_READ | // reads backward
  1430. EVENTLOG_SEQUENTIAL_READ, // sequential read
  1431. 0, // ignored for sequential reads
  1432. pevlr, // address of buffer
  1433. EVL_BUFFER_SIZE, // size of buffer
  1434. &dwRead, // count of bytes read
  1435. &dwNeeded) // bytes in next record
  1436. && keep_scanning == TRUE) {
  1437. /* Wind down thru this "slug" . . . */
  1438. while (dwRead > 0) {
  1439. /*
  1440. | Check for "Event Logging Started"
  1441. |
  1442. | (The source name is just past the end of the formal structure).
  1443. */
  1444. if ( pevlr->EventID == EVENTLOG_START_ID
  1445. && pevlr->EventType == EVENTLOG_START_TYPE
  1446. && strcmp( ((LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD))),
  1447. EVENTLOG_START_SRC) == 0
  1448. ) {
  1449. keep_scanning = FALSE;
  1450. break;
  1451. }
  1452. //============================================================================
  1453. // INSERT RECORD CHECKING LOGIC OF THIS SORT HERE:
  1454. //
  1455. // IF ( <eventrecordID> == pevlr->EventID
  1456. // && <eventrecordtype> == pevlr->EventType
  1457. // && <eventrecordsourcestring> == (is the same as..)
  1458. // ( (LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD)) )
  1459. // ) {
  1460. // // It's an allocation-failure record, if it is for device
  1461. // // "device", then count it.
  1462. // IF (strcmp(device, <eventrecordinstance-data>) {
  1463. // alloc_failures += 1;
  1464. // }
  1465. // }
  1466. //============================================================================
  1467. dwRead -= pevlr->Length;
  1468. pevlr = (EVENTLOGRECORD *)
  1469. ((LPBYTE) pevlr + pevlr->Length);
  1470. }
  1471. pevlr = (EVENTLOGRECORD *) &bBuffer;
  1472. }
  1473. CloseEventLog(h);
  1474. /* Give 'em the count */
  1475. return (alloc_failures);
  1476. }
  1477. #if defined(CACHE_DUMP)
  1478. /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */
  1479. /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */
  1480. /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */
  1481. static void
  1482. debug_print_hrstorage(
  1483. CACHEROW *row /* Row in hrstorage table */
  1484. )
  1485. /*
  1486. | EXPLICIT INPUTS:
  1487. |
  1488. | "row" - points to the row to be dumped, if NULL, the function
  1489. | merely prints a suitable title.
  1490. |
  1491. | IMPLICIT INPUTS:
  1492. |
  1493. | - Symbols used to reference the attributes in the row entry.
  1494. | - File handle defined by OFILE, presumed to be open.
  1495. |
  1496. | OUTPUTS:
  1497. |
  1498. | On Success:
  1499. | Function prints a dump of the row in ASCII for debugging purposes
  1500. | on file handle OFILE.
  1501. |
  1502. | THE BIG PICTURE:
  1503. |
  1504. | Debugging only.
  1505. |
  1506. | OTHER THINGS TO KNOW:
  1507. */
  1508. {
  1509. if (row == NULL) {
  1510. fprintf(OFILE, "=====================\n");
  1511. fprintf(OFILE, "hrStorage Table Cache\n");
  1512. fprintf(OFILE, "=====================\n");
  1513. return;
  1514. }
  1515. fprintf(OFILE, "hrStorageIndex . . . . . %d\n",
  1516. row->attrib_list[HRST_INDEX].u.unumber_value);
  1517. fprintf(OFILE, "hrStorageType. . . . . . %d ",
  1518. row->attrib_list[HRST_TYPE].u.unumber_value);
  1519. switch (row->attrib_list[HRST_TYPE].u.unumber_value) {
  1520. case 1: fprintf(OFILE, "(Other)\n"); break;
  1521. case 2: fprintf(OFILE, "(RAM)\n"); break;
  1522. case 3: fprintf(OFILE, "(Virtual Memory)\n"); break;
  1523. case 4: fprintf(OFILE, "(Fixed Disk)\n"); break;
  1524. case 5: fprintf(OFILE, "(Removable Disk)\n"); break;
  1525. case 6: fprintf(OFILE, "(Floppy Disk)\n"); break;
  1526. case 7: fprintf(OFILE, "(Compact Disk)\n"); break;
  1527. case 8: fprintf(OFILE, "(RAM Disk)\n"); break;
  1528. default:
  1529. fprintf(OFILE, "(Unknown)\n");
  1530. }
  1531. fprintf(OFILE, "hrStorageDescr . . . . . \"%s\"\n",
  1532. row->attrib_list[HRST_DESCR].u.string_value);
  1533. fprintf(OFILE, "hrStorageAllocationUnits %d\n",
  1534. row->attrib_list[HRST_ALLOC].u.number_value);
  1535. fprintf(OFILE, "hrStorageSize. . . . . . %d\n",
  1536. row->attrib_list[HRST_SIZE].u.number_value);
  1537. fprintf(OFILE, "hrStorageUsed. . . . . . %d\n",
  1538. row->attrib_list[HRST_USED].u.number_value);
  1539. fprintf(OFILE, "hrStorageAllocationFails (Computed)\n");
  1540. }
  1541. #endif