Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
6.4 KiB

  1. /*
  2. * user.c v0.10
  3. *
  4. ****************************************************************************
  5. * *
  6. * (C) Copyright 1995 DIGITAL EQUIPMENT CORPORATION *
  7. * *
  8. * This software is an unpublished work protected under the *
  9. * the copyright laws of the United States of America, all *
  10. * rights reserved. *
  11. * *
  12. * In the event this software is licensed for use by the United *
  13. * States Government, all use, duplication or disclosure by the *
  14. * United States Government is subject to restrictions as set *
  15. * forth in either subparagraph (c)(1)(ii) of the Rights in *
  16. * Technical Data And Computer Software Clause at DFARS *
  17. * 252.227-7013, or the Commercial Computer Software Restricted *
  18. * Rights Clause at FAR 52.221-19, whichever is applicable. *
  19. * *
  20. ****************************************************************************
  21. *
  22. * Facility:
  23. *
  24. * SNMP Extension Agent
  25. *
  26. * Abstract:
  27. *
  28. * This module contains support functions for the HostMIB Subagent.
  29. *
  30. *
  31. * Author:
  32. *
  33. * D. D. Burns @ WebEnable, Inc.
  34. *
  35. *
  36. * Revision History:
  37. *
  38. * V0.01 - 04/16/97 D. D. Burns Original Creation
  39. *
  40. *
  41. */
  42. /*
  43. |
  44. | Support Functions accessible from outside this module:
  45. |
  46. Spt_GetProcessCount
  47. This function supports hrSystem table attribute "hrSystemProcesses"
  48. by returning the number of active processes in the system. This
  49. code is derived from PERFDLL code in files "PERFSPRC.C" and
  50. "PERFPROC.C".
  51. |
  52. | Support Functions accessible only from inside this module:
  53. |
  54. */
  55. #include <nt.h>
  56. #include <ntrtl.h>
  57. #include <nturtl.h>
  58. #include <windows.h>
  59. #include <stdlib.h>
  60. #include <malloc.h>
  61. /*
  62. || LOCAL DEFINES
  63. */
  64. /*
  65. | Spt_GetProcessCount
  66. */
  67. #define INCREMENT_BUFFER_SIZE ((DWORD)(4096*2))
  68. #define LARGE_BUFFER_SIZE ((DWORD)(4096*16))
  69. /* Spt_GetProcessCount - Retrieve count of number of active processes */
  70. /* Spt_GetProcessCount - Retrieve count of number of active processes */
  71. /* Spt_GetProcessCount - Retrieve count of number of active processes */
  72. ULONG
  73. Spt_GetProcessCount(
  74. void
  75. )
  76. /*
  77. | IN SUPPORT OF:
  78. |
  79. | HRSYSTEM.C - "hrSystemProcesses"
  80. |
  81. | EXPLICIT INPUTS:
  82. |
  83. | None.
  84. |
  85. | IMPLICIT INPUTS:
  86. |
  87. | System performance information is fetched thru
  88. | "NtQuerySystemInformation()".
  89. |
  90. | OUTPUTS:
  91. |
  92. | On Success:
  93. | Function returns the count of active processes as determined by
  94. | the number of performance information blocks for processes that
  95. | have both a name and a non-zero thread count (in the style of code in
  96. | "PERFPROC.C").
  97. |
  98. | On any Failure:
  99. | Function returns zero (not a legal number of processes).
  100. |
  101. | THE BIG PICTURE:
  102. |
  103. | The generated function "GetHrSystemProcesses()" in HRSYSTEM.C is
  104. | invoked by the generic subagent to retrieve the current value of
  105. | the SNMP attribute "GetHrSystemProcesses". All the work of
  106. | retrieving that value is done by this support function.
  107. |
  108. | OTHER THINGS TO KNOW:
  109. |
  110. | This function incurs a rather substantial bit of overhead in that
  111. | to determine the number of processes active it actually fetches
  112. | a large slug of performance data (a "slug" per process) for all
  113. | processes and merely counts the number of slugs returned.
  114. | This seems to be the only available way to acquire this information.
  115. |
  116. */
  117. {
  118. DWORD dwReturnedBufferSize;
  119. NTSTATUS Status;
  120. DWORD ProcessBufSize = LARGE_BUFFER_SIZE; // Initial Process-Buf size
  121. LPBYTE pProcessBuffer = NULL; // Pointer to Process-Buf
  122. PSYSTEM_PROCESS_INFORMATION ProcessInfo; // Walking ptr thru Process-Buf
  123. ULONG ProcessBufferOffset = 0; //
  124. ULONG Process_count = 0; // Count of Live processes
  125. //
  126. // Get process data from system.
  127. //
  128. // Grab an initially-sized buffer to receive data
  129. pProcessBuffer = malloc(ProcessBufSize);
  130. if (pProcessBuffer == NULL) {
  131. return (0); // Out of memory
  132. }
  133. /*
  134. | Loop until we've allocated a buffer big enough to receive all the data
  135. | NtQuery wants to give us.
  136. |
  137. | Exit with the buffer loaded with info or on some kind of non-mismatch error.
  138. */
  139. while( (Status = NtQuerySystemInformation(
  140. SystemProcessInformation,
  141. pProcessBuffer,
  142. ProcessBufSize,
  143. &dwReturnedBufferSize))
  144. == STATUS_INFO_LENGTH_MISMATCH ) {
  145. LPBYTE pNewProcessBuffer; // For use on realloc
  146. // expand buffer & retry
  147. ProcessBufSize += INCREMENT_BUFFER_SIZE;
  148. if ( !(pNewProcessBuffer = realloc(pProcessBuffer,ProcessBufSize)) ) {
  149. /* If realloc failed and left us with the old buffer, free it */
  150. if (pProcessBuffer != NULL) {
  151. free(pProcessBuffer);
  152. }
  153. return (0); // Out of memory
  154. }
  155. else {
  156. /* Successful Realloc */
  157. pProcessBuffer = pNewProcessBuffer;
  158. }
  159. /* Try another query */
  160. }
  161. /* If we didn't meet with full success. . . */
  162. if ( !NT_SUCCESS(Status) ) {
  163. if (pProcessBuffer != NULL) {
  164. free(pProcessBuffer);
  165. }
  166. return (0); // Unknown error that prevents us from continuing
  167. }
  168. /*
  169. | At this point, "pProcessBuffer" points to a buffer formatted as a
  170. | "System Process Information" structure.
  171. |
  172. | Setup to go a-walking it.
  173. */
  174. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessBuffer;
  175. while ( TRUE ) {
  176. // check for Live processes
  177. // (i.e. name or threads)
  178. if ((ProcessInfo->ImageName.Buffer != NULL) ||
  179. (ProcessInfo->NumberOfThreads > 0)) {
  180. /* thread is not Dead */
  181. Process_count += 1;
  182. }
  183. // exit if this was the last process in list
  184. if (ProcessInfo->NextEntryOffset == 0) {
  185. break;
  186. }
  187. // point to next buffer in list
  188. ProcessBufferOffset += ProcessInfo->NextEntryOffset;
  189. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  190. &pProcessBuffer[ProcessBufferOffset];
  191. }
  192. free(pProcessBuffer);
  193. return (Process_count);
  194. }