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.

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