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.

1841 lines
59 KiB

  1. /*
  2. * HrSWRunEntry.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 HrSWRunEntry. Actual instrumentation code is
  32. * 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.
  39. *
  40. * Author:
  41. *
  42. * D. D. Burns @ Webenable Inc
  43. *
  44. * Revision History:
  45. *
  46. * V1.00 - 05/14/97 D. D. Burns Genned: Thu Nov 07 16:47:29 1996
  47. *
  48. */
  49. #include <nt.h>
  50. #include <ntrtl.h>
  51. #include <nturtl.h>
  52. #include <windows.h>
  53. #include <malloc.h>
  54. #include <snmp.h>
  55. #include "mib.h"
  56. #include "smint.h"
  57. #include "hostmsmi.h"
  58. #include "user.h" /* Developer supplied include file */
  59. #include "HMCACHE.H" /* Cache-related definitions */
  60. #include <string.h>
  61. /*
  62. |==============================================================================
  63. | Function prototypes for this module.
  64. |
  65. */
  66. /* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table cache */
  67. static BOOL
  68. AddHrSWRunRow(PSYSTEM_PROCESS_INFORMATION ProcessInfo);
  69. /* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
  70. void
  71. FetchProcessParams(
  72. PSYSTEM_PROCESS_INFORMATION ProcessInfo, /* Process for parameters */
  73. CHAR **path_str, /* Returned PATH string */
  74. CHAR **params_str /* Returned Parameters string */
  75. );
  76. #if defined(CACHE_DUMP)
  77. /* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
  78. static void
  79. debug_print_hrswrun(
  80. CACHEROW *row /* Row in hrSWRun(Perf) table */
  81. );
  82. #endif
  83. /*
  84. |==============================================================================
  85. | Cache Refresh Time
  86. |
  87. | The cache for the hrSWRun and hrSWRunPerf tables is refreshed automatically
  88. | when a request arrives --AND-- the cache is older than CACHE_MAX_AGE
  89. | in seconds.
  90. |
  91. */
  92. static
  93. LARGE_INTEGER cache_time; // 100ns Timestamp of cache (when last refreshed)
  94. #define CACHE_MAX_AGE 120 // Maximum age in seconds
  95. /*
  96. |==============================================================================
  97. | Create the list-head for the HrSWRun(Perf) Table cache.
  98. |
  99. | This cache contains info for both the hrSWRun and hrSWRunPerf tables.
  100. | (This macro is defined in "HMCACHE.H").
  101. |
  102. | This is global so code for the hrSWRunPerf table ("HRSWPREN.C") can
  103. | reference it.
  104. */
  105. CACHEHEAD_INSTANCE(hrSWRunTable_cache, debug_print_hrswrun);
  106. /*
  107. |==============================================================================
  108. | Operating System Index
  109. |
  110. | SNMP attribute "HrSWOSIndex" is the index into hrSWRun to the entry that
  111. | primary operating system running on the host. This value is computed in
  112. | this module in function "AddHrSWRunRow()" and stored here for reference
  113. | by code in "HRSWRUN.C".
  114. */
  115. ULONG SWOSIndex;
  116. /*
  117. * GetHrSWRunIndex
  118. * A unique value for each piece of software running on the host. Wherever
  119. * possible, this should be the system's native, unique id
  120. *
  121. * Gets the value for HrSWRunIndex.
  122. *
  123. * Arguments:
  124. *
  125. * outvalue address to return variable value
  126. * accesss Reserved for future security use
  127. * instance address of instance name as ordered native
  128. * data type(s)
  129. *
  130. * Return Codes:
  131. *
  132. * Standard PDU error codes.
  133. *
  134. * SNMP_ERRORSTATUS_NOERROR Successful get
  135. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  136. * mibtget.c v0.10
  137. *
  138. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  139. | hrSWRunIndex
  140. |
  141. | ACCESS SYNTAX
  142. | read-only INTEGER (1..2147483647)
  143. |
  144. | "A unique value for each piece of software running on the host. Wherever
  145. | possible, this should be the system's native, unique identification number."
  146. |
  147. | DISCUSSION:
  148. |
  149. | By using performance monitoring information from the Registry (using code
  150. | from "PVIEW") this attribute is given the value of the Process ID.
  151. |
  152. |============================================================================
  153. | 1.3.6.1.2.1.25.4.2.1.1.<instance>
  154. | | | | |
  155. | | | | *-hrSWRunIndex
  156. | | | *-hrSWRunEntry
  157. | | *-hrSWRunTable
  158. | *-hrSWRun
  159. */
  160. UINT
  161. GetHrSWRunIndex(
  162. OUT Integer *outvalue ,
  163. IN Access_Credential *access ,
  164. IN InstanceName *instance )
  165. {
  166. ULONG index; /* As fetched from instance structure */
  167. CACHEROW *row; /* Row entry fetched from cache */
  168. /*
  169. | Grab the instance information
  170. */
  171. index = GET_INSTANCE(0);
  172. /*
  173. | Use it to find the right entry in the cache
  174. */
  175. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  176. return SNMP_ERRORSTATUS_GENERR;
  177. }
  178. *outvalue = row->attrib_list[HRSR_INDEX].u.number_value;
  179. return SNMP_ERRORSTATUS_NOERROR ;
  180. } /* end of GetHrSWRunIndex() */
  181. /*
  182. * GetHrSWRunName
  183. * A textual description of this running piece of software, including the
  184. * manufacturer, revision, and the name by which it is commo
  185. *
  186. * Gets the value for HrSWRunName.
  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. | hrSWRunName
  205. |
  206. | ACCESS SYNTAX
  207. | read-only InternationalDisplayString (SIZE (0..64))
  208. |
  209. | "A textual description of this running piece of software, including the
  210. | manufacturer, revision, and the name by which it is commonly known. If this
  211. | software was installed locally, this should be the same string as used in the
  212. | corresponding hrSWInstalledName."
  213. |
  214. | DISCUSSION:
  215. |
  216. | By using performance monitoring information from the Registry (using code
  217. | from "PVIEW") this attribute is given the value of the Process name.
  218. |
  219. |============================================================================
  220. | 1.3.6.1.2.1.25.4.2.1.2.<instance>
  221. | | | | |
  222. | | | | *-hrSWRunName
  223. | | | *-hrSWRunEntry
  224. | | *-hrSWRunTable
  225. | *-hrSWRun
  226. */
  227. UINT
  228. GetHrSWRunName(
  229. OUT InternationalDisplayString *outvalue ,
  230. IN Access_Credential *access ,
  231. IN InstanceName *instance )
  232. {
  233. ULONG index; /* As fetched from instance structure */
  234. CACHEROW *row; /* Row entry fetched from cache */
  235. /*
  236. | Grab the instance information
  237. */
  238. index = GET_INSTANCE(0);
  239. /*
  240. | Use it to find the right entry in the cache
  241. */
  242. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  243. return SNMP_ERRORSTATUS_GENERR;
  244. }
  245. /* Return the name that was computed at cache-build time */
  246. outvalue->length = strlen(row->attrib_list[HRSR_NAME].u.string_value);
  247. outvalue->string = row->attrib_list[HRSR_NAME].u.string_value;
  248. if (outvalue->length > 64) {
  249. outvalue->length = 64; /* Truncate */
  250. }
  251. return SNMP_ERRORSTATUS_NOERROR ;
  252. } /* end of GetHrSWRunName() */
  253. /*
  254. * GetHrSWRunID
  255. * The product ID of this running piece of software.
  256. *
  257. * Gets the value for HrSWRunID.
  258. *
  259. * Arguments:
  260. *
  261. * outvalue address to return variable value
  262. * accesss Reserved for future security use
  263. * instance address of instance name as ordered native
  264. * data type(s)
  265. *
  266. * Return Codes:
  267. *
  268. * Standard PDU error codes.
  269. *
  270. * SNMP_ERRORSTATUS_NOERROR Successful get
  271. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  272. * mibtget.c v0.10
  273. *
  274. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  275. | hrSWRunID
  276. |
  277. | ACCESS SYNTAX
  278. | read-only ProductID
  279. |
  280. | "The product ID of this running piece of software."
  281. |
  282. | DISCUSSION:
  283. |
  284. | <POA-16> I anticipate always using "unknownProduct" as the value for this
  285. | attribute, as I can envision no systematic means of acquiring a registered
  286. | OID for all process software to be used as the value for this attribute.
  287. |
  288. | RESOLVED >>>>>>>
  289. | <POA-16> Returning an unknown Product ID is acceptable.
  290. | RESOLVED >>>>>>>
  291. |
  292. |============================================================================
  293. | 1.3.6.1.2.1.25.4.2.1.3.<instance>
  294. | | | | |
  295. | | | | *-hrSWRunID
  296. | | | *-hrSWRunEntry
  297. | | *-hrSWRunTable
  298. | *-hrSWRun
  299. */
  300. UINT
  301. GetHrSWRunID(
  302. OUT ProductID *outvalue ,
  303. IN Access_Credential *access ,
  304. IN InstanceName *instance )
  305. {
  306. /*
  307. | The deal on this attribute is that we'll never have a valid OID value
  308. | for this attribute. Consequently, we always return the standard
  309. | "unknown" OID value ("0.0") regardless of the instance value (which
  310. | by now in the calling sequence of things has been validated anyway).
  311. */
  312. if ( (outvalue->ids = SNMP_malloc(2 * sizeof( UINT ))) == NULL) {
  313. return SNMP_ERRORSTATUS_GENERR;
  314. }
  315. outvalue->idLength = 2;
  316. /*
  317. | Load in the OID value for "unknown" for ProductID: "0.0"
  318. */
  319. outvalue->ids[0] = 0;
  320. outvalue->ids[1] = 0;
  321. return SNMP_ERRORSTATUS_NOERROR ;
  322. } /* end of GetHrSWRunID() */
  323. /*
  324. * GetHrSWRunPath
  325. * A description of the location on long-term storage (e.g. a disk drive)
  326. * from which this software was loaded.
  327. *
  328. * Gets the value for HrSWRunPath.
  329. *
  330. * Arguments:
  331. *
  332. * outvalue address to return variable value
  333. * accesss Reserved for future security use
  334. * instance address of instance name as ordered native
  335. * data type(s)
  336. *
  337. * Return Codes:
  338. *
  339. * Standard PDU error codes.
  340. *
  341. * SNMP_ERRORSTATUS_NOERROR Successful get
  342. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  343. * mibtget.c v0.10
  344. *
  345. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  346. | hrSWRunPath
  347. |
  348. | ACCESS SYNTAX
  349. | read-only InternationalDisplayString (SIZE(0..128))
  350. |
  351. | "A description of the location on long-term storage (e.g. a disk drive) from
  352. | which this software was loaded."
  353. |
  354. | DISCUSSION:
  355. |
  356. | <POA-17> This information is not extracted by the sample PVIEW code from the
  357. | performance monitoring statistics kept in the Registry. If this information
  358. | is available from the Registry or some other source, I need to acquire the
  359. | description of how to get it.
  360. |
  361. | RESOLVED >>>>>>>>
  362. | <POA-17> This is obtained using PerfMon code pointers provided by Bob Watson.
  363. | RESOLVED >>>>>>>>
  364. |
  365. |============================================================================
  366. | 1.3.6.1.2.1.25.4.2.1.4.<instance>
  367. | | | | |
  368. | | | | *-hrSWRunPath
  369. | | | *-hrSWRunEntry
  370. | | *-hrSWRunTable
  371. | *-hrSWRun
  372. */
  373. UINT
  374. GetHrSWRunPath(
  375. OUT InternationalDisplayString *outvalue ,
  376. IN Access_Credential *access ,
  377. IN InstanceName *instance )
  378. {
  379. ULONG index; /* As fetched from instance structure */
  380. CACHEROW *row; /* Row entry fetched from cache */
  381. /*
  382. | Grab the instance information
  383. */
  384. index = GET_INSTANCE(0);
  385. /*
  386. | Use it to find the right entry in the cache
  387. */
  388. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  389. return SNMP_ERRORSTATUS_GENERR;
  390. }
  391. /*
  392. | Return the Path string that was computed at cache-build time.
  393. | NOTE: This string might be NULL.
  394. */
  395. if (row->attrib_list[HRSR_PATH].u.string_value == NULL) {
  396. outvalue->length = 0;
  397. }
  398. else {
  399. outvalue->length = strlen(row->attrib_list[HRSR_PATH].u.string_value);
  400. outvalue->string = row->attrib_list[HRSR_PATH].u.string_value;
  401. if (outvalue->length > 128) {
  402. outvalue->length = 128; /* Truncate */
  403. }
  404. }
  405. return SNMP_ERRORSTATUS_NOERROR ;
  406. } /* end of GetHrSWRunPath() */
  407. /*
  408. * GetHrSWRunParameters
  409. *
  410. * A description of the parameters supplied to this software when it was
  411. * initially loaded."
  412. *
  413. * Gets the value for HrSWRunParameters.
  414. *
  415. * Arguments:
  416. *
  417. * outvalue address to return variable value
  418. * accesss Reserved for future security use
  419. * instance address of instance name as ordered native
  420. * data type(s)
  421. *
  422. * Return Codes:
  423. *
  424. * Standard PDU error codes.
  425. *
  426. * SNMP_ERRORSTATUS_NOERROR Successful get
  427. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  428. * mibtget.c v0.10
  429. *
  430. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  431. | hrSWRunParameters
  432. |
  433. | ACCESS SYNTAX
  434. | read-only InternationalDisplayString (SIZE(0..128))
  435. |
  436. | "A description of the parameters supplied to this software when it was
  437. | initially loaded."
  438. |
  439. | DISCUSSION:
  440. |
  441. | <POA-18> This information is not extracted by the sample PVIEW code from the
  442. | performance monitoring statistics kept in the Registry. If this information
  443. | is available from the Registry or some other source, I need to acquire the
  444. | description of how to get it.
  445. |
  446. | RESOLVED >>>>>>>>
  447. | <POA-18> See discussion for "hrSWRunPath" above.
  448. | RESOLVED >>>>>>>>
  449. |
  450. |============================================================================
  451. | NOTE: This function edited in by hand, as it was not originally generated.
  452. |============================================================================
  453. | 1.3.6.1.2.1.25.4.2.1.5.<instance>
  454. | | | | |
  455. | | | | *-hrSWRunParameters
  456. | | | *-hrSWRunEntry
  457. | | *-hrSWRunTable
  458. | *-hrSWRun
  459. */
  460. UINT
  461. GetHrSWRunParameters(
  462. OUT InternationalDisplayString *outvalue ,
  463. IN Access_Credential *access ,
  464. IN InstanceName *instance )
  465. {
  466. ULONG index; /* As fetched from instance structure */
  467. CACHEROW *row; /* Row entry fetched from cache */
  468. /*
  469. | Grab the instance information
  470. */
  471. index = GET_INSTANCE(0);
  472. /*
  473. | Use it to find the right entry in the cache
  474. */
  475. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  476. return SNMP_ERRORSTATUS_GENERR;
  477. }
  478. /*
  479. | Return the Parameter string that was computed at cache-build time.
  480. | NOTE: This string might be NULL.
  481. */
  482. if (row->attrib_list[HRSR_PARAM].u.string_value == NULL) {
  483. outvalue->length = 0;
  484. }
  485. else {
  486. outvalue->length = strlen(row->attrib_list[HRSR_PARAM].u.string_value);
  487. outvalue->string = row->attrib_list[HRSR_PARAM].u.string_value;
  488. if (outvalue->length > 128) {
  489. outvalue->length = 128; /* Truncate */
  490. }
  491. }
  492. return SNMP_ERRORSTATUS_NOERROR ;
  493. } /* end of GetHrSWRunParameters() */
  494. /*
  495. * GetHrSWRunType
  496. * The type of this software.
  497. *
  498. * Gets the value for HrSWRunType.
  499. *
  500. * Arguments:
  501. *
  502. * outvalue address to return variable value
  503. * accesss Reserved for future security use
  504. * instance address of instance name as ordered native
  505. * data type(s)
  506. *
  507. * Return Codes:
  508. *
  509. * Standard PDU error codes.
  510. *
  511. * SNMP_ERRORSTATUS_NOERROR Successful get
  512. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  513. * mibtget.c v0.10
  514. *
  515. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  516. | hrSWRunType
  517. |
  518. | ACCESS SYNTAX
  519. | read-only INTEGER {unknown(1),operatingSystem(2),deviceDriver(3),
  520. | application(4)}
  521. |
  522. | "The type of this software."
  523. |
  524. | DISCUSSION:
  525. |
  526. | <POA-19> This information is not extracted by the sample PVIEW code from the
  527. | performance monitoring statistics kept in the Registry. If this information
  528. | is available from the Registry or some other source, I need to acquire the
  529. | description of how to get it.
  530. |
  531. | >>>>>>>>
  532. | <POA-19> I am not sure whether this information is included in the perfmon
  533. | data block. I will investigate further.
  534. | >>>>>>>>
  535. |
  536. |============================================================================
  537. | 1.3.6.1.2.1.25.4.2.1.6.<instance>
  538. | | | | |
  539. | | | | *-hrSWRunType
  540. | | | *-hrSWRunEntry
  541. | | *-hrSWRunTable
  542. | *-hrSWRun
  543. */
  544. UINT
  545. GetHrSWRunType(
  546. OUT INTSWType *outvalue ,
  547. IN Access_Credential *access ,
  548. IN InstanceName *instance )
  549. {
  550. ULONG index; /* As fetched from instance structure */
  551. CACHEROW *row; /* Row entry fetched from cache */
  552. /*
  553. | Grab the instance information
  554. */
  555. index = GET_INSTANCE(0);
  556. /*
  557. | Use it to find the right entry in the cache
  558. */
  559. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  560. return SNMP_ERRORSTATUS_GENERR;
  561. }
  562. *outvalue = row->attrib_list[HRSR_TYPE].u.number_value;
  563. return SNMP_ERRORSTATUS_NOERROR ;
  564. } /* end of GetHrSWRunType() */
  565. /*
  566. * GetHrSWRunStatus
  567. * The status of this running piece of software. Setting this value to
  568. * invalid(4) shall cause this software to stop running and be
  569. *
  570. * Gets the value for HrSWRunStatus.
  571. *
  572. * Arguments:
  573. *
  574. * outvalue address to return variable value
  575. * accesss Reserved for future security use
  576. * instance address of instance name as ordered native
  577. * data type(s)
  578. *
  579. * Return Codes:
  580. *
  581. * Standard PDU error codes.
  582. *
  583. * SNMP_ERRORSTATUS_NOERROR Successful get
  584. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  585. * mibtget.c v0.10
  586. *
  587. | =============== From WebEnable Design Spec Rev 3 04/11/97==================
  588. | hrSWRunStatus
  589. |
  590. | ACCESS SYNTAX
  591. | read-write INTEGER {
  592. | running(1),
  593. | runnable(2), -- waiting for resource (CPU, memory, IO)
  594. | notRunnable(3), -- loaded but waiting for event
  595. | invalid(4) -- not loaded
  596. | }
  597. |
  598. | "The status of this running piece of software. Setting this value to
  599. | invalid(4) shall cause this software to stop running and to be unloaded."
  600. |
  601. | DISCUSSION:
  602. |
  603. | <POA-20> For an SNMP "GET" on this attribute, this information is not extracted
  604. | by the sample PVIEW code from the performance monitoring statistics kept in
  605. | the Registry. If this information is available from the Registry or some
  606. | other source, I need to acquire the description of how to get it.
  607. |
  608. | RESOLVED >>>>>>>
  609. | <POA-20> I think running and notRunnable will be all that are applicable
  610. | here (that latter being returned in situations which are currently labeled
  611. | "not responding").
  612. | RESOLVED >>>>>>>
  613. |
  614. |============================================================================
  615. | 1.3.6.1.2.1.25.4.2.1.7.<instance>
  616. | | | | |
  617. | | | | *-hrSWRunStatus
  618. | | | *-hrSWRunEntry
  619. | | *-hrSWRunTable
  620. | *-hrSWRun
  621. */
  622. UINT
  623. GetHrSWRunStatus(
  624. OUT INThrSWRunStatus *outvalue ,
  625. IN Access_Credential *access ,
  626. IN InstanceName *instance )
  627. {
  628. ULONG index; /* As fetched from instance structure */
  629. CACHEROW *row; /* Row entry fetched from cache */
  630. /*
  631. | Grab the instance information
  632. */
  633. index = GET_INSTANCE(0);
  634. /*
  635. | Use it to find the right entry in the cache
  636. */
  637. if ((row = FindTableRow(index, &hrSWRunTable_cache)) == NULL) {
  638. return SNMP_ERRORSTATUS_GENERR;
  639. }
  640. *outvalue = row->attrib_list[HRSR_STATUS].u.number_value;
  641. return SNMP_ERRORSTATUS_NOERROR ;
  642. } /* end of GetHrSWRunStatus() */
  643. /*
  644. * SetHrSWRunStatus
  645. * The status of this running piece of software. Setting this value to
  646. * invalid(4) shall cause this software to stop running and be
  647. *
  648. * Sets the HrSWRunStatus value.
  649. *
  650. * Arguments:
  651. *
  652. * invalue address of value to set the variable
  653. * outvalue address to return the set variable value
  654. * access Reserved for future security use
  655. * instance address of instance name as ordered native
  656. * data type(s)
  657. *
  658. * Return Codes:
  659. *
  660. * Standard PDU error codes.
  661. *
  662. * SNMP_ERRORSTATUS_NOERROR Successful get
  663. * SNMP_ERRORSTATUS_BADVALUE Set value not in range
  664. * SNMP_ERRORSTATUS_GENERR Catch-all failure code
  665. * mibtset.ntc v0.10
  666. */
  667. UINT
  668. SetHrSWRunStatus(
  669. IN INThrSWRunStatus *invalue ,
  670. OUT INThrSWRunStatus *outvalue ,
  671. IN Access_Credential *access ,
  672. IN InstanceName *instance )
  673. {
  674. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  675. } /* end of SetHrSWRunStatus() */
  676. /*
  677. * HrSWRunEntryFindInstance
  678. *
  679. * This routine is used to verify that the specified instance is
  680. * valid.
  681. *
  682. * Arguments:
  683. *
  684. * FullOid Address for the full oid - group, variable,
  685. * and instance information
  686. * instance Address for instance specification as an oid
  687. *
  688. * Return Codes:
  689. *
  690. * SNMP_ERRORSTATUS_NOERROR Instance found and valid
  691. * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance
  692. *
  693. */
  694. UINT
  695. HrSWRunEntryFindInstance( IN ObjectIdentifier *FullOid ,
  696. IN OUT ObjectIdentifier *instance )
  697. {
  698. UINT tmp_instance ;
  699. //
  700. // Developer instrumentation code to find appropriate instance goes here.
  701. // For non-tables, it is not necessary to modify this routine. However, if
  702. // there is any context that needs to be set, it can be done here.
  703. //
  704. if ( FullOid->idLength <= HRSWRUNENTRY_VAR_INDEX )
  705. // No instance was specified
  706. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  707. else if ( FullOid->idLength != HRSWRUNENTRY_VAR_INDEX + 1 )
  708. // Instance length is more than 1
  709. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  710. else
  711. // The only valid instance for a non-table are instance 0. If this
  712. // is a non-table, the following code validates the instances. If this
  713. // is a table, developer modification is necessary below.
  714. tmp_instance = FullOid->ids[ HRSWRUNENTRY_VAR_INDEX ] ;
  715. /*
  716. | Check for age-out and possibly refresh the entire cache for the
  717. | hrSWRun table before we check to see if the instance is there.
  718. */
  719. if (hrSWRunCache_Refresh() == FALSE) {
  720. return SNMP_ERRORSTATUS_GENERR;
  721. }
  722. /*
  723. | For hrSWRun, the instance arc(s) is a single arc, and it must
  724. | correctly select an entry in the hrSWRun Table cache.
  725. | Check that here.
  726. */
  727. if ( FindTableRow(tmp_instance, &hrSWRunTable_cache) == NULL ) {
  728. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  729. }
  730. else
  731. {
  732. // the instance is valid. Create the instance portion of the OID
  733. // to be returned from this call.
  734. instance->ids[ 0 ] = tmp_instance ;
  735. instance->idLength = 1 ;
  736. }
  737. return SNMP_ERRORSTATUS_NOERROR ;
  738. } /* end of HrSWRunEntryFindInstance() */
  739. /*
  740. * HrSWRunEntryFindNextInstance
  741. *
  742. * This routine is called to get the next instance. If no instance
  743. * was passed than return the first instance (1).
  744. *
  745. * Arguments:
  746. *
  747. * FullOid Address for the full oid - group, variable,
  748. * and instance information
  749. * instance Address for instance specification as an oid
  750. *
  751. * Return Codes:
  752. *
  753. * SNMP_ERRORSTATUS_NOERROR Instance found and valid
  754. * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance
  755. *
  756. */
  757. UINT
  758. HrSWRunEntryFindNextInstance( IN ObjectIdentifier *FullOid ,
  759. IN OUT ObjectIdentifier *instance )
  760. {
  761. //
  762. // Developer supplied code to find the next instance of class goes here.
  763. // If this is a class with cardinality 1, no modification of this routine
  764. // is necessary unless additional context needs to be set.
  765. // If the FullOid does not specify an instance, then the only instance
  766. // of the class is returned. If this is a table, the first row of the
  767. // table is returned.
  768. //
  769. // If an instance is specified and this is a non-table class, then NOSUCHNAME
  770. // is returned so that correct MIB rollover processing occurs. If this is
  771. // a table, then the next instance is the one following the current instance.
  772. // If there are no more instances in the table, return NOSUCHNAME.
  773. //
  774. CACHEROW *row;
  775. ULONG tmp_instance;
  776. if ( FullOid->idLength <= HRSWRUNENTRY_VAR_INDEX )
  777. {
  778. /*
  779. | Too short: must return the instance arc that selects the first
  780. | entry in the table if there is one.
  781. */
  782. tmp_instance = 0;
  783. }
  784. else {
  785. /*
  786. | There is at least one instance arc. Even if it is the only arc
  787. | we use it as the "index" in a request for the "NEXT" one.
  788. */
  789. tmp_instance = FullOid->ids[ HRSWRUNENTRY_VAR_INDEX ] ;
  790. }
  791. /*
  792. | Check for age-out and possibly refresh the entire cache for the
  793. | hrSWRun table before we check to see if the instance is there.
  794. */
  795. if (hrSWRunCache_Refresh() == FALSE) {
  796. return SNMP_ERRORSTATUS_GENERR;
  797. }
  798. /* Now go off and try to find the next instance in the table */
  799. if ((row = FindNextTableRow(tmp_instance, &hrSWRunTable_cache)) == NULL) {
  800. return SNMP_ERRORSTATUS_NOSUCHNAME ;
  801. }
  802. instance->ids[ 0 ] = row->index ;
  803. instance->idLength = 1 ;
  804. return SNMP_ERRORSTATUS_NOERROR ;
  805. } /* end of HrSWRunEntryFindNextInstance() */
  806. /*
  807. * HrSWRunEntryConvertInstance
  808. *
  809. * This routine is used to convert the object id specification of an
  810. * instance into an ordered native representation. The object id format
  811. * is that object identifier that is returned from the Find Instance
  812. * or Find Next Instance routines. It is NOT the full object identifier
  813. * that contains the group and variable object ids as well. The native
  814. * representation is an argc/argv-like structure that contains the
  815. * ordered variables that define the instance. This is specified by
  816. * the MIB's INDEX clause. See RFC 1212 for information about the INDEX
  817. * clause.
  818. *
  819. *
  820. * Arguments:
  821. *
  822. * oid_spec Address of the object id instance specification
  823. * native_spec Address to return the ordered native instance
  824. * specification
  825. *
  826. * Return Codes:
  827. *
  828. * SUCCESS Conversion complete successfully
  829. * FAILURE Unable to convert object id into native format
  830. *
  831. */
  832. UINT
  833. HrSWRunEntryConvertInstance( IN ObjectIdentifier *oid_spec ,
  834. IN OUT InstanceName *native_spec )
  835. {
  836. static char *array; /* The address of this (char *) is passed back */
  837. /* as though it were an array of length 1 of these */
  838. /* types. */
  839. static ULONG inst; /* The address of this ULONG is passed back */
  840. /* (Obviously, no "free()" action is needed) */
  841. /* We only expect the one arc in "oid_spec" */
  842. inst = oid_spec->ids[0];
  843. array = (char *) &inst;
  844. native_spec->count = 1;
  845. native_spec->array = &array;
  846. return SUCCESS ;
  847. } /* end of HrSWRunEntryConvertInstance() */
  848. /*
  849. * HrSWRunEntryFreeInstance
  850. *
  851. * This routine is used to free an ordered native representation of an
  852. * instance name.
  853. *
  854. * Arguments:
  855. *
  856. * instance Address to return the ordered native instance
  857. * specification
  858. *
  859. * Return Codes:
  860. *
  861. *
  862. */
  863. void
  864. HrSWRunEntryFreeInstance( IN OUT InstanceName *instance )
  865. {
  866. //
  867. // Developer supplied code to free native representation of instance name goes here.
  868. //
  869. } /* end of HrSWRunEntryFreeInstance() */
  870. /*
  871. | End of Generated Code
  872. */
  873. /* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
  874. /* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
  875. /* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
  876. BOOL
  877. Gen_HrSWRun_Cache(
  878. void
  879. )
  880. /*
  881. | EXPLICIT INPUTS:
  882. |
  883. | None.
  884. |
  885. | IMPLICIT INPUTS:
  886. |
  887. | The module-local head of the cache for the HrSWRun table,
  888. | "hrSWRunTable_cache".
  889. |
  890. | OUTPUTS:
  891. |
  892. | On Success:
  893. | Function returns TRUE indicating that the cache has been fully
  894. | populated with all "static" cache-able values. This function populates
  895. | the hrSWRun Table cache, but this cache also includes the two
  896. | attributes for the hrSWRunPerf Table. So in effect, one cache serves
  897. | two tables, but the hrSWRunPerf table is a "one-to-one" extension
  898. | of hrSWRun table.. that is a row in hrSWRun always has a corresponding
  899. | "two-entry" row in hrSWRunPerf.
  900. |
  901. | On any Failure:
  902. | Function returns FALSE (indicating "not enough storage").
  903. |
  904. | THE BIG PICTURE:
  905. |
  906. | At subagent startup time, the cache for each table in the MIB is
  907. | populated with rows for each row in the table. This function is
  908. | invoked by the start-up code in "UserMibInit()" ("MIB.C") to
  909. | populate the cache for the HrSWRun table (which also serves the
  910. | hrSWRunPerf Table).
  911. |
  912. | It is also re-entered whenever a request for information from this
  913. | cache comes in and the cache is older than a certain age (symbol
  914. | "CACHE_MAX_AGE" defined at the beginning of this module). In this
  915. | case the cache is rebuilt, and in this way this function is different
  916. | from all the other "Gen_*_Cache()" functions which only build their
  917. | caches once (in the initial release).
  918. |
  919. |
  920. | OTHER THINGS TO KNOW:
  921. |
  922. | There is one of these function for every table that has a cache.
  923. | Each cachehead is found in the respective table's source file.
  924. |
  925. | The strategy on getting running software enumerated revolves around
  926. | NtQuerySystemInformation(SystemProcessInformation...) invocation.
  927. |
  928. | Once we have a list of processes, additional information (such as
  929. | the parameters on the command-line) are fetched by opening the
  930. | process (if possible) and reading process memory.
  931. |
  932. | Note that unlike the other cache's in the initial release, this cache
  933. | for hrSWRun and hrSWRunPerf is updated before it is read if it is
  934. | older than a specified period of time (set by #define at the beginning
  935. | of this file).
  936. |
  937. |============================================================================
  938. | 1.3.6.1.2.1.25.4.1.0
  939. | | |
  940. | | *-hrSWOSIndex
  941. | *-hrSWRun
  942. |
  943. | 1.3.6.1.2.1.25.4.2.1..
  944. | | | |
  945. | | | *-hrSWRunEntry
  946. | | *-hrSWRunTable
  947. | *-hrSWRun
  948. */
  949. #define LARGE_BUFFER_SIZE (4096*8)
  950. #define INCREMENT_BUFFER_SIZE (4096*2)
  951. {
  952. DWORD ProcessBufSize = LARGE_BUFFER_SIZE; /* Initial ProcessBuffer size */
  953. LPBYTE pProcessBuffer = NULL; /* Re-used and re-expanded as needed */
  954. PSYSTEM_PROCESS_INFORMATION
  955. ProcessInfo; /* --> Next process to process */
  956. ULONG ProcessBufferOffset=0; /* Accumulating offset cell */
  957. NTSTATUS ntstatus; /* Generic return status */
  958. DWORD dwReturnedBufferSize; /* From NtQuerySystemInformation() */
  959. /*
  960. | Blow away any old copy of the cache
  961. */
  962. DestroyTable( &hrSWRunTable_cache );
  963. /*
  964. | Grab an initial buffer for Process Information
  965. */
  966. if ((pProcessBuffer = malloc ( ProcessBufSize )) == NULL) {
  967. return ( FALSE );
  968. }
  969. /*
  970. | Go for a (new/refreshed) buffer of current Process Info
  971. */
  972. while( (ntstatus = NtQuerySystemInformation(
  973. SystemProcessInformation,
  974. pProcessBuffer,
  975. ProcessBufSize,
  976. &dwReturnedBufferSize
  977. )
  978. ) == STATUS_INFO_LENGTH_MISMATCH )
  979. {
  980. LPBYTE pNewProcessBuffer = NULL; // For use on realloc
  981. /* expand buffer & retry */
  982. ProcessBufSize += INCREMENT_BUFFER_SIZE;
  983. if ( !(pNewProcessBuffer = realloc(pProcessBuffer,ProcessBufSize)) )
  984. {
  985. // If realloc failed and left us with the old buffer, free it
  986. if (pProcessBuffer != NULL)
  987. {
  988. free(pProcessBuffer);
  989. }
  990. return (FALSE); // Out of memory
  991. }
  992. else
  993. {
  994. // Successful Realloc
  995. pProcessBuffer = pNewProcessBuffer;
  996. }
  997. }
  998. /*
  999. | Freshen the time on the cache
  1000. |
  1001. | Get the current system-time in 100ns intervals . . . */
  1002. ntstatus = NtQuerySystemTime (&cache_time);
  1003. if (ntstatus != STATUS_SUCCESS)
  1004. {
  1005. free( pProcessBuffer );
  1006. return ( FALSE );
  1007. }
  1008. /*
  1009. | Loop over each instance of Process Information in the ProcessBuffer
  1010. | and build a row in the cache for hrSWRun and hrSWRunPerf tables.
  1011. */
  1012. for (ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessBuffer;
  1013. ; /* Exit check below */
  1014. ProcessBufferOffset += ProcessInfo->NextEntryOffset,
  1015. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  1016. &pProcessBuffer[ProcessBufferOffset]
  1017. ) {
  1018. /* Add a Row to the cache */
  1019. if (AddHrSWRunRow(ProcessInfo) != TRUE) {
  1020. if (pProcessBuffer != NULL) {
  1021. free(pProcessBuffer);
  1022. }
  1023. return ( FALSE ); // Out of memory
  1024. }
  1025. /* If this is the last process, bag it */
  1026. if (ProcessInfo->NextEntryOffset == 0) {
  1027. break;
  1028. }
  1029. }
  1030. #if defined(CACHE_DUMP)
  1031. PrintCache(&hrSWRunTable_cache);
  1032. #endif
  1033. if (pProcessBuffer != NULL) {
  1034. free(pProcessBuffer);
  1035. }
  1036. /* Cache (re)-build successful */
  1037. return ( TRUE );
  1038. }
  1039. /* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
  1040. /* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
  1041. /* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
  1042. static BOOL
  1043. AddHrSWRunRow(
  1044. PSYSTEM_PROCESS_INFORMATION ProcessInfo /* --> Next process to process */
  1045. )
  1046. /*
  1047. | EXPLICIT INPUTS:
  1048. |
  1049. | "ProcessInfo" points to the next process (as described by a
  1050. | SYSTEM_PROCESS_INFORMATION structure) for which a row is to be
  1051. | inserted into the HrSWRun(Perf) table cache.
  1052. |
  1053. | IMPLICIT INPUTS:
  1054. |
  1055. | The module-local head of the cache for the HrDevice table,
  1056. | "hrSWRunTable_cache".
  1057. |
  1058. | OUTPUTS:
  1059. |
  1060. | On Success:
  1061. | Function creates a new row entry populated with all "static" cache-able
  1062. | values for HrSWRun(Perf) table and returns TRUE. Note that if the
  1063. | process is the "System Process", the row entry index is stored in
  1064. | module cell "SWOSIndex" for reference by code in "HRSWRUN.C".
  1065. |
  1066. | On any Failure:
  1067. | Function returns FALSE (indicating "not enough storage" or other
  1068. | internal logic error).
  1069. |
  1070. |
  1071. | THE BIG PICTURE:
  1072. |
  1073. | At subagent startup time, the cache for each table in the MIB is
  1074. | populated with rows for each row in the table. This function is
  1075. | invoked by the cache-build code in "Gen_HrSWRun_Cache()" above.
  1076. |
  1077. | OTHER THINGS TO KNOW:
  1078. |
  1079. | The cache being (re)built by this function serves two tables, hrSWRun
  1080. | and hrSWRunPerf.
  1081. |
  1082. | In general, we use the Process's "ProcessID" as the index in the
  1083. | hrSWRun(Perf) table. However special handling is done for the Idle
  1084. | Process because it's Process ID is zero. We convert it to "1" to meet
  1085. | the SNMP requirement that indexes be greater than zero. We note that
  1086. | as of this writing, no process id of 1 is seen in build 1515 (the "System"
  1087. | process has a processID of 2).
  1088. |
  1089. | The "type" of software can be unknown(1), operatingSystem(2),
  1090. | deviceDriver(3) and application(4). We only detect the Idle and System
  1091. | processes (by their names) as "operatingSystem(2)", everything else
  1092. | is presumed "application(4)".
  1093. |
  1094. | As for "status", it can be running(1), runnable(2), notRunnable(3) or
  1095. | invalid(4). If the number of threads is greater than 0, it is presumed
  1096. | "running(1)", otherwise "invalid(4)".
  1097. */
  1098. #define ANSI_PNAME_LEN 256
  1099. {
  1100. ANSI_STRING pname; /* ANSI version of UNICODE process name */
  1101. CHAR pbuf[ANSI_PNAME_LEN+1]; /* Buffer for "pname" */
  1102. CHAR *pname_str; /* Pointer to our final process name */
  1103. CHAR *path_str=NULL; /* Pointer to our Path name */
  1104. CHAR *params=NULL; /* Pointer to any parameters fnd on cmdline*/
  1105. UINT type; /* SNMP code for type of software */
  1106. UINT status; /* SNMP code for the status of software */
  1107. CACHEROW *row; /* --> Cache structure for row-being built */
  1108. NTSTATUS ntstatus; /* Generic return status */
  1109. /*
  1110. | OK, the caller wants another row in the table, get a row-entry created.
  1111. */
  1112. if ((row = CreateTableRow( HRSR_ATTRIB_COUNT ) ) == NULL) {
  1113. return ( FALSE ); // Out of memory
  1114. }
  1115. /*
  1116. | Set up the standard-hrSWRun(Perf) attributes in the new row
  1117. */
  1118. type = 4; /* Presume "application(4)" type software */
  1119. if (ProcessInfo->NumberOfThreads > 0) {
  1120. status = 1; /* Presume "running(1)" for software status */
  1121. }
  1122. else {
  1123. status = 4; /* "invalid(4)", process on the way out */
  1124. }
  1125. /* =========== HrSWRunIndex ==========*/
  1126. row->attrib_list[HRSR_INDEX].attrib_type = CA_NUMBER;
  1127. row->attrib_list[HRSR_INDEX].u.unumber_value =
  1128. HandleToUlong(ProcessInfo->UniqueProcessId) ;
  1129. /* Special check for system idle process, roll it from 0 to 1 */
  1130. if (ProcessInfo->UniqueProcessId == 0) {
  1131. row->attrib_list[HRSR_INDEX].u.unumber_value = 1;
  1132. }
  1133. /* =========== HrSWRunName ==========*/
  1134. row->attrib_list[HRSR_NAME].attrib_type = CA_STRING;
  1135. /* If we actually have a process name for this process . . . */
  1136. if (ProcessInfo->ImageName.Buffer != NULL) {
  1137. /* Prep the STRING structure */
  1138. pname.Buffer = pbuf;
  1139. pname.MaximumLength = ANSI_PNAME_LEN;
  1140. /* Convert from Unicode */
  1141. ntstatus = RtlUnicodeStringToAnsiString(&pname, // Target string
  1142. (PUNICODE_STRING)&ProcessInfo->ImageName,//Src
  1143. FALSE); // = Don't Allocate buf
  1144. if (ntstatus != STATUS_SUCCESS)
  1145. {
  1146. DestroyTableRow(row);
  1147. return ( FALSE );
  1148. }
  1149. /*
  1150. | Here we parse not only the process name but any path that may be
  1151. | prepended to it. (We make no attempt to eliminate any ".EXE" that
  1152. | may be on the end of the image name).
  1153. |
  1154. | NOTE: If you are going to rip off this code, be aware that as-of
  1155. | build 1515, we NEVER seem to get an image name that has the
  1156. | path prepended on the front... so most of this code to skip
  1157. | the possibly-present path is almost certainly superfluous.
  1158. */
  1159. /* Try to "backup" until we hit any "\" */
  1160. if ( (pname_str = strrchr(pname.Buffer,'\\')) != NULL) {
  1161. pname_str++; /* Pop to first char after "\" */
  1162. }
  1163. else {
  1164. pname_str = pname.Buffer; /* Use entire string, no "\" found */
  1165. /*
  1166. | A piece of software with no path means it could be the "System"
  1167. | process. Check for that here.
  1168. */
  1169. if (strcmp(pname_str, "System") == 0) {
  1170. type = 2; /* Mark the software as "operatingSystem(2)" type */
  1171. /*
  1172. | We're processing the main System Process, so record it's index
  1173. | in module-level cell for reference from "HRSWRUN.C".
  1174. */
  1175. SWOSIndex = row->attrib_list[HRSR_INDEX].u.unumber_value;
  1176. }
  1177. }
  1178. }
  1179. else {
  1180. /* The system idle process has no name */
  1181. pname_str = "System Idle Process";
  1182. type = 2; /* Mark the software as "operatingSystem(2)" type */
  1183. }
  1184. /* Allocate cache storage and copy the process name to it */
  1185. if ( (row->attrib_list[HRSR_NAME].u.string_value
  1186. = ( LPSTR ) malloc(strlen(pname_str) + 1)) == NULL) {
  1187. DestroyTableRow(row);
  1188. return ( FALSE ); /* out of memory */
  1189. }
  1190. strcpy(row->attrib_list[HRSR_NAME].u.string_value, pname_str);
  1191. /*
  1192. | We bother to do the overhead of trying to extract path & parameters from
  1193. | the command-line that started the process by reading process memory
  1194. | only if the type of the software is "application(4)" and status is
  1195. | "running(1)".
  1196. */
  1197. if (status == 1 && type == 4) { /* If it is a runnable application . . . */
  1198. FetchProcessParams(ProcessInfo, &path_str, &params);
  1199. }
  1200. /* =========== HrSWRunPath ==========*/
  1201. row->attrib_list[HRSR_PATH].attrib_type = CA_STRING;
  1202. row->attrib_list[HRSR_PATH].u.string_value = NULL;
  1203. /* If we did detect a path . . . */
  1204. if (path_str != NULL) {
  1205. /* Allocate cache storage and copy the path string to it */
  1206. if ( (row->attrib_list[HRSR_PATH].u.string_value
  1207. = ( LPSTR ) malloc(strlen(path_str) + 1)) == NULL) {
  1208. DestroyTableRow(row);
  1209. return ( FALSE ); /* out of memory */
  1210. }
  1211. strcpy(row->attrib_list[HRSR_PATH].u.string_value, path_str);
  1212. }
  1213. /* =========== HrSWRunParameters ==========*/
  1214. row->attrib_list[HRSR_PARAM].attrib_type = CA_STRING;
  1215. row->attrib_list[HRSR_PARAM].u.string_value = NULL; /* In case of none */
  1216. /* If we did find parameters . . . */
  1217. if (params != NULL) {
  1218. /* Allocate cache storage and copy the parameter string to it */
  1219. if ( (row->attrib_list[HRSR_PARAM].u.string_value
  1220. = ( LPSTR ) malloc(strlen(params) + 1)) == NULL) {
  1221. DestroyTableRow(row);
  1222. return ( FALSE ); /* out of memory */
  1223. }
  1224. strcpy(row->attrib_list[HRSR_PARAM].u.string_value, params);
  1225. }
  1226. /* =========== HrSWRunType ========== */
  1227. row->attrib_list[HRSR_TYPE].attrib_type = CA_NUMBER;
  1228. row->attrib_list[HRSR_TYPE].u.unumber_value = type;
  1229. /* =========== HrSWRunStatus ========== */
  1230. row->attrib_list[HRSR_STATUS].attrib_type = CA_NUMBER;
  1231. row->attrib_list[HRSR_STATUS].u.unumber_value = status;
  1232. /*
  1233. | For hrSWRunPerf Table:
  1234. */
  1235. /* =========== HrSWRunPerfCPU ==========
  1236. | UserTime + KernelTime are in 100ns (1/10th of a millionth of a second)
  1237. | units and HrSWRunPerfCPU is supposed to be in 1/100th of a second units.
  1238. |
  1239. | So .01 - second intervals
  1240. | is .010 000 0 - 100nanoseconds intervals,
  1241. |
  1242. | so dividing 100ns intervals by 100,000 gives centi-seconds.
  1243. */
  1244. row->attrib_list[HRSP_CPU].attrib_type = CA_NUMBER;
  1245. row->attrib_list[HRSP_CPU].u.unumber_value = (ULONG)
  1246. ((ProcessInfo->UserTime.QuadPart + ProcessInfo->KernelTime.QuadPart) / 100000);
  1247. /* =========== HrSWRunPerfMem ========== */
  1248. row->attrib_list[HRSP_MEM].attrib_type = CA_NUMBER;
  1249. row->attrib_list[HRSP_MEM].u.unumber_value =
  1250. (ULONG)(ProcessInfo->WorkingSetSize / 1024);
  1251. /*
  1252. | Now insert the filled-in CACHEROW structure into the
  1253. | cache-list for the hrSWRun(Perf) Table.
  1254. */
  1255. if (AddTableRow(row->attrib_list[HRSR_INDEX].u.unumber_value, /* Index */
  1256. row, /* Row */
  1257. &hrSWRunTable_cache /* Cache */
  1258. ) == FALSE) {
  1259. DestroyTableRow(row);
  1260. return ( FALSE ); /* Internal Logic Error! */
  1261. }
  1262. return ( TRUE );
  1263. }
  1264. /* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
  1265. /* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
  1266. /* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
  1267. BOOL
  1268. hrSWRunCache_Refresh(
  1269. void
  1270. )
  1271. /*
  1272. | EXPLICIT INPUTS:
  1273. |
  1274. | None.
  1275. |
  1276. | IMPLICIT INPUTS:
  1277. |
  1278. | The "hrSWRunTable_cache" CACHEHEAD structure and the time when
  1279. | it was last refreshed in module-local cell "cache_time".
  1280. |
  1281. | OUTPUTS:
  1282. |
  1283. | On Success/Failure:
  1284. | The function returns TRUE. Only if the cache-time has aged-out
  1285. | is the cache actually rebuilt.
  1286. |
  1287. | On any Failure:
  1288. | If during a rebuild there is an error, this function returns FALSE.
  1289. | The state of the cache is indeterminate.
  1290. |
  1291. | THE BIG PICTURE:
  1292. |
  1293. | This function is invoked before any reference is made to any SNMP
  1294. | variable in the hrSWRun or hrSWRunPerf table. It checks to see
  1295. | if the cache needs to be rebuilt based on the last time it was built.
  1296. |
  1297. | The calls to this function are strategically located in the
  1298. | "FindInstance" and "FindNextInstance" functions in "HRSWRUNE.C"
  1299. | (this module) and "HRSWPREN.C" (for the RunPerf table) as well
  1300. | as in "HRSWRUN.C" for the stand-alone attribute "hrSWOSIndex".
  1301. |
  1302. | OTHER THINGS TO KNOW:
  1303. |
  1304. */
  1305. {
  1306. LARGE_INTEGER now_time; /* Current System time in 100 ns ticks */
  1307. /* Get the current time in 100 ns ticks*/
  1308. if (NtQuerySystemTime (&now_time) != STATUS_SUCCESS )
  1309. return FALSE;
  1310. /* If the cache is older than the maximum allowed time (in ticks) . . . */
  1311. if ( (now_time.QuadPart - cache_time.QuadPart) > (CACHE_MAX_AGE * 10000000) ){
  1312. return ( Gen_HrSWRun_Cache() );
  1313. }
  1314. return ( TRUE ); /* No Error (because no refresh) */
  1315. }
  1316. /* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
  1317. /* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
  1318. /* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
  1319. void
  1320. FetchProcessParams(
  1321. PSYSTEM_PROCESS_INFORMATION ProcessInfo, /* Process for parameters */
  1322. CHAR **path_str, /* Returned PATH string */
  1323. CHAR **params_str /* Returned Parameters string */
  1324. )
  1325. /*
  1326. | EXPLICIT INPUTS:
  1327. |
  1328. | "ProcessInfo" points to the process (as described by a
  1329. | SYSTEM_PROCESS_INFORMATION structure) for which the path & parameters
  1330. | (from the command-line) are desired.
  1331. |
  1332. | "path_str" is the address of a pointer to be set to any "path" string.
  1333. | "params" is the address of a pointer to be set to any "parameters"
  1334. | string.
  1335. |
  1336. | IMPLICIT INPUTS:
  1337. |
  1338. | None.
  1339. |
  1340. | OUTPUTS:
  1341. |
  1342. | On Success:
  1343. | Function returns pointers to a static buffer containing the
  1344. | path & parameters section of the command line. There may be nothing
  1345. | in the buffer (ie just the null-termination).
  1346. |
  1347. | On any Failure:
  1348. | Function returns NULLS indicating a problem was encountered
  1349. | attempting to obtain the command-line image from which the
  1350. | path & parameter portion is to be extracted, or indicating that
  1351. | one or both were not present.
  1352. |
  1353. | THE BIG PICTURE:
  1354. |
  1355. | Called from "AddHrSWRunRow()" above, this is a helper function
  1356. | that serves to isolate the code lifted from "TLIST" from
  1357. | the rest of the subagent.
  1358. |
  1359. | OTHER THINGS TO KNOW:
  1360. |
  1361. | The black magic here was lifted from sections of "TLIST".
  1362. */
  1363. {
  1364. HANDLE hProcess;
  1365. PEB Peb;
  1366. NTSTATUS Status;
  1367. PROCESS_BASIC_INFORMATION BasicInfo;
  1368. WCHAR szT[(MAX_PATH * 2)+1];
  1369. UNICODE_STRING u_param;
  1370. RTL_USER_PROCESS_PARAMETERS ProcessParameters;
  1371. #define ANSI_PARAM_LEN (MAX_PATH * 2)
  1372. ANSI_STRING param; /* ANSI version of UNICODE command line */
  1373. static
  1374. CHAR pbuf[ANSI_PARAM_LEN+1]; /* Buffer for "parameters" */
  1375. CHAR *param_str; /* Pointer to our final parameter string */
  1376. SIZE_T dwbytesret; /* Count of bytes read from process memory */
  1377. pbuf[ANSI_PARAM_LEN] = 0;
  1378. szT[MAX_PATH * 2] = 0;
  1379. /* Presume failure/nothing obtained */
  1380. *path_str = NULL;
  1381. *params_str = NULL;
  1382. /* get a handle to the process */
  1383. hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,
  1384. FALSE,
  1385. HandleToUlong(ProcessInfo->UniqueProcessId));
  1386. if (!hProcess) {
  1387. return;
  1388. }
  1389. Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
  1390. &BasicInfo, sizeof(BasicInfo), NULL);
  1391. if (!NT_SUCCESS(Status)) {
  1392. CloseHandle(hProcess);
  1393. return;
  1394. }
  1395. // get the PEB
  1396. if (ReadProcessMemory(hProcess, BasicInfo.PebBaseAddress, &Peb,
  1397. sizeof(PEB), NULL)) {
  1398. // get the processparameters
  1399. if (ReadProcessMemory(hProcess, Peb.ProcessParameters,
  1400. &ProcessParameters, sizeof(ProcessParameters), NULL)) {
  1401. // get cmdline
  1402. if (ReadProcessMemory(hProcess,
  1403. ProcessParameters.CommandLine.Buffer,
  1404. szT,
  1405. sizeof(szT)-2, // minus the last 2 bytes
  1406. &dwbytesret
  1407. )
  1408. ) {
  1409. CHAR *scanner; /* Used for parsing the command-line */
  1410. /* Prep the STRING structure */
  1411. param.Buffer = pbuf;
  1412. param.MaximumLength = ANSI_PARAM_LEN;
  1413. u_param.Length = (USHORT) ((wcslen(szT) + 1) * 2); // bytes incl. NULL
  1414. u_param.Buffer = szT;
  1415. /* Convert from Unicode */
  1416. Status = RtlUnicodeStringToAnsiString(&param, // Target string
  1417. &u_param, /* Src */
  1418. FALSE); /* = Don't Allocate buf */
  1419. if (Status != STATUS_SUCCESS)
  1420. {
  1421. CloseHandle(hProcess);
  1422. return;
  1423. }
  1424. // Firstly, we need to check for command line of the form:
  1425. // "c:\program files\blah\blah" -parameter1 -parameter2
  1426. // "C:\Program Files\Internet Explorer\IEXPLORE.EXE"
  1427. // but not:
  1428. // C:\WINDOWS\system32\mmc.exe "C:\WINDOWS\system32\tsmmc.msc" /s
  1429. if ( pbuf[0] == '\"')
  1430. {
  1431. // get first '\"', see if there is another one
  1432. if ((scanner = strchr(pbuf+1, '\"')) != NULL)
  1433. {
  1434. // found the 2nd terminating '\"'
  1435. *params_str = (scanner + 1);
  1436. *scanner = 0; // Terminate the base string
  1437. // Path
  1438. if ((scanner = strrchr(pbuf, '\\')) != NULL)
  1439. {
  1440. // Terminate the path
  1441. *(scanner+1) = 0;
  1442. // Return start of buffer as path
  1443. *path_str = pbuf+1;
  1444. }
  1445. else
  1446. {
  1447. // No path
  1448. *path_str = NULL;
  1449. }
  1450. }
  1451. }
  1452. else
  1453. /*
  1454. | OK, we can have the following situations:
  1455. |
  1456. | 1) "\system\system32\smss.exe -parameter1 -parameter2"
  1457. | --------path----- -------parameters------
  1458. |
  1459. | 2) "\system\system32\smss.exe"
  1460. | --------path-----
  1461. |
  1462. | 3) "smss.exe -parameter1 -parameter2"
  1463. | -------parameters------
  1464. |
  1465. | and we want to handle this by returning "path" and "parameter"
  1466. | as shown, where:
  1467. |
  1468. | 1) both path and parameters are present
  1469. | 2) only path is present
  1470. | 3) only parameters are present
  1471. |
  1472. | We do this:
  1473. |
  1474. | - Scan forward for a blank.
  1475. | If we get one:
  1476. | + return the address following it as "parameters"
  1477. | + set the blank to a null byte (cutting off parameters)
  1478. | If not:
  1479. | + return NULL as "parameters"
  1480. |
  1481. | ----Parameters are done.
  1482. |
  1483. | - Perform a reverse search for "\" on whatever is now in the
  1484. | buffer
  1485. | If we find a "\":
  1486. | + Step forward one character and turn it into a null
  1487. | byte (turning buffer into string containing path).
  1488. | + Return the buffer address as "path"
  1489. | If not:
  1490. | + return NULL as "path"
  1491. */
  1492. /* Parameter */
  1493. {
  1494. if ((scanner = strchr(pbuf, ' ')) != NULL) {
  1495. /* Return address of char after blank as start of parameters */
  1496. *params_str = (scanner + 1);
  1497. *scanner = '\0'; /* Terminate base string */
  1498. }
  1499. else {
  1500. /* No parameters */
  1501. *params_str = NULL;
  1502. }
  1503. /* Path */
  1504. if ((scanner = strrchr(pbuf, '\\')) != NULL) {
  1505. /* Terminate the path */
  1506. *(scanner+1) = '\0';
  1507. /* Return start of buffer as path */
  1508. *path_str = pbuf;
  1509. }
  1510. else {
  1511. /* No path */
  1512. *path_str = NULL;
  1513. }
  1514. }
  1515. CloseHandle(hProcess);
  1516. /* Return address of static ANSI string buffer */
  1517. return;
  1518. }
  1519. }
  1520. }
  1521. CloseHandle(hProcess);
  1522. /* Nothing back */
  1523. return;
  1524. }
  1525. #if defined(CACHE_DUMP)
  1526. /* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
  1527. /* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
  1528. /* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
  1529. static void
  1530. debug_print_hrswrun(
  1531. CACHEROW *row /* Row in hrSWRun(Perf) table */
  1532. )
  1533. /*
  1534. | EXPLICIT INPUTS:
  1535. |
  1536. | "row" - points to the row to be dumped, if NULL, the function
  1537. | merely prints a suitable title.
  1538. |
  1539. | IMPLICIT INPUTS:
  1540. |
  1541. | - Symbols used to reference the attributes in the row entry.
  1542. | - File handle defined by OFILE, presumed to be open.
  1543. |
  1544. | OUTPUTS:
  1545. |
  1546. | On Success:
  1547. | Function prints a dump of the row in ASCII for debugging purposes
  1548. | on file handle OFILE.
  1549. |
  1550. | THE BIG PICTURE:
  1551. |
  1552. | Debugging only.
  1553. |
  1554. | OTHER THINGS TO KNOW:
  1555. */
  1556. {
  1557. if (row == NULL) {
  1558. fprintf(OFILE, "=================================\n");
  1559. fprintf(OFILE, "hrSWRun & hrSWRunPerf Table Cache\n");
  1560. fprintf(OFILE, "=================================\n");
  1561. return;
  1562. }
  1563. fprintf(OFILE, "HrSWRunIndex . . . . . . %d\n",
  1564. row->attrib_list[HRSR_INDEX].u.unumber_value);
  1565. fprintf(OFILE, "HrSWRunName. . . . . . . \"%s\"\n",
  1566. row->attrib_list[HRSR_NAME].u.string_value);
  1567. fprintf(OFILE, "HrSWRunPath. . . . . . . \"%s\"\n",
  1568. row->attrib_list[HRSR_PATH].u.string_value);
  1569. fprintf(OFILE, "HRSWRunParameters. . . . \"%s\"\n",
  1570. row->attrib_list[HRSR_PARAM].u.string_value);
  1571. fprintf(OFILE, "HrSWRunType. . . . . . . %d ",
  1572. row->attrib_list[HRSR_TYPE].u.unumber_value);
  1573. switch (row->attrib_list[HRSR_TYPE].u.unumber_value) {
  1574. case 1: fprintf(OFILE, "(unknown)\n"); break;
  1575. case 2: fprintf(OFILE, "(operatingSystem)\n"); break;
  1576. case 3: fprintf(OFILE, "(deviceDriver)\n"); break;
  1577. case 4: fprintf(OFILE, "(application)\n"); break;
  1578. default:
  1579. fprintf(OFILE, "(???)\n");
  1580. }
  1581. fprintf(OFILE, "HrSWRunStatus. . . . . . %d ",
  1582. row->attrib_list[HRSR_STATUS].u.unumber_value);
  1583. switch (row->attrib_list[HRSR_STATUS].u.unumber_value) {
  1584. case 1: fprintf(OFILE, "(running)\n"); break;
  1585. case 2: fprintf(OFILE, "(runnable)\n"); break;
  1586. case 3: fprintf(OFILE, "(notRunnable)\n"); break;
  1587. case 4: fprintf(OFILE, "(invalid)\n"); break;
  1588. default:
  1589. fprintf(OFILE, "(???)\n");
  1590. }
  1591. fprintf(OFILE, "HrSWRunPerfCpu . . . . . %d (Centi-seconds)\n",
  1592. row->attrib_list[HRSP_CPU].u.unumber_value);
  1593. fprintf(OFILE, "HrSWRunPerfMem . . . . . %d (Kbytes)\n",
  1594. row->attrib_list[HRSP_MEM].u.unumber_value);
  1595. }
  1596. #endif