PERFMEM.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1995-1997  Microsoft Corporation
  3. Module Name:
  4.     perfmem.c
  5. Abstract:
  6.     This file implements the Extensible Objects for  the application
  7.     memory object
  8. Created:
  9.     Bob Watson 24 august 1995
  10. Revision History
  11.     None
  12. --*/
  13. //
  14. //  Include Files
  15. //
  16. #include <windows.h>
  17. #include <string.h>
  18. #include <winperf.h>
  19. #include "..incappmemi.h"     // definitions shared with the app. dll
  20. #include "memctrs.h"            // error message definition
  21. #include "perfmsg.h"            // message utilities
  22. #include "perfutil.h"           // perf data utilities
  23. #include "datamem.h"            // perf data structure definitions
  24. //
  25. //  References to constants which initialize the Object type definitions
  26. //
  27. extern APPMEM_DATA_DEFINITION AppMemDataDefinition;
  28. static DWORD   dwOpenCount = 0;        // count of "Open" threads
  29. static BOOL    bInitOK = FALSE;        // true = DLL initialized OK
  30. //
  31. // App Mem counter data structures
  32. //
  33. static  HANDLE  hAppMemSharedMemory = NULL; // Handle of counter Shared Memory
  34. static  HANDLE  hAppMemMutex = NULL;        // sync mutex for memory
  35. static  PAPPMEM_DATA_HEADER pDataHeader = NULL; // pointer to header of shared mem
  36. //
  37. //  Function Prototypes
  38. //
  39. //      these are used to insure that the data collection functions
  40. //      accessed by Perflib will have the correct calling format.
  41. //
  42. PM_OPEN_PROC    OpenAppMemPerformanceData;
  43. PM_COLLECT_PROC CollectAppMemPerformanceData;
  44. PM_CLOSE_PROC   CloseAppMemPerformanceData;
  45. DWORD APIENTRY
  46. OpenAppMemPerformanceData(
  47.     LPWSTR lpDeviceNames
  48. )
  49. /*++
  50. Routine Description:
  51.     This routine will open and map the memory used by the App Mem DLL to
  52.     pass performance data in. This routine also initializes the data
  53.     structures used to pass data back to the registry
  54. Arguments:
  55.     Pointer to object ID of each device to be opened
  56. Return Value:
  57.     None.
  58. --*/
  59. {
  60.     LONG status;
  61.     HKEY hKeyDriverPerf;
  62.     BOOL  bFreeMutex;
  63.     DWORD size;
  64.     DWORD type;
  65.     DWORD dwFirstCounter;
  66.     DWORD dwFirstHelp;
  67.     DWORD dwInstance;
  68.     PAPPMEM_INSTANCE    pLastItem;
  69.     PAPPMEM_INSTANCE    pAppData;
  70.     APPMEM_COUNTERS     ac;
  71.     //
  72.     //  Since WINLOGON is multi-threaded and will call this routine in
  73.     //  order to service remote performance queries, this library
  74.     //  must keep track of how many times it has been opened (i.e.
  75.     //  how many threads have accessed it). the registry routines will
  76.     //  limit access to the initialization routine to only one thread
  77.     //  at a time so synchronization (i.e. reentrancy) should not be
  78.     //  a problem
  79.     //
  80.     if (dwOpenCount == 0) { // do this only on the first instance of the DLL
  81.         // open Eventlog interface
  82.         hEventLog = MonOpenEventLog();
  83.         // open/create shared memory used by the application to pass performance values
  84.         status = GetSharedMemoryDataHeader (
  85.             &hAppMemSharedMemory, &hAppMemMutex, &pDataHeader,
  86.             TRUE); // only read access is required
  87.         if (status != ERROR_SUCCESS) {
  88.             REPORT_ERROR_DATA (status, LOG_USER, NULL, 0);
  89.             goto OpenExitPoint;
  90.         }
  91.         // get counter and help index base values from registry
  92.         //      Open key to registry entry
  93.         //      read First Counter and First Help values
  94.         //      update static data strucutures by adding base to
  95.         //          offset value in structure.
  96.         status = RegOpenKeyEx (
  97.             HKEY_LOCAL_MACHINE,
  98.             "SYSTEM\CurrentControlSet\Services\AppMem\Performance",
  99.             0L,
  100.             KEY_ALL_ACCESS,
  101.             &hKeyDriverPerf);
  102.         if (status != ERROR_SUCCESS) {
  103.             REPORT_ERROR_DATA (APPMEM_UNABLE_OPEN_DRIVER_KEY, LOG_USER,
  104.                 &status, sizeof(status));
  105.             // this is fatal, if we can't get the base values of the
  106.             // counter or help names, then the names won't be available
  107.             // to the requesting application  so there's not much
  108.             // point in continuing.
  109.             goto OpenExitPoint;
  110.         }
  111.         size = sizeof (DWORD);
  112.         status = RegQueryValueEx(
  113.                     hKeyDriverPerf,
  114.                     "First Counter",
  115.                     0L,
  116.                     &type,
  117.                     (LPBYTE)&dwFirstCounter,
  118.                     &size);
  119.         if (status != ERROR_SUCCESS) {
  120.             REPORT_ERROR_DATA (APPMEM_UNABLE_READ_FIRST_COUNTER, LOG_USER,
  121.                 &status, sizeof(status));
  122.             // this is fatal, if we can't get the base values of the
  123.             // counter or help names, then the names won't be available
  124.             // to the requesting application  so there's not much
  125.             // point in continuing.
  126.             goto OpenExitPoint;
  127.         }
  128.         size = sizeof (DWORD);
  129.         status = RegQueryValueEx(
  130.                     hKeyDriverPerf,
  131.                     "First Help",
  132.                     0L,
  133.                     &type,
  134.                     (LPBYTE)&dwFirstHelp,
  135.                     &size);
  136.         if (status != ERROR_SUCCESS) {
  137.             REPORT_ERROR_DATA (APPMEM_UNABLE_READ_FIRST_HELP, LOG_USER,
  138.                 &status, sizeof(status));
  139.             // this is fatal, if we can't get the base values of the
  140.             // counter or help names, then the names won't be available
  141.             // to the requesting application  so there's not much
  142.             // point in continuing.
  143.             goto OpenExitPoint;
  144.         }
  145.         //
  146.         //  NOTE: the initialization program could also retrieve
  147.         //      LastCounter and LastHelp if they wanted to do
  148.         //      bounds checking on the new number. e.g.
  149.         //
  150.         //      counter->CounterNameTitleIndex += dwFirstCounter;
  151.         //      if (counter->CounterNameTitleIndex > dwLastCounter) {
  152.         //          LogErrorToEventLog (INDEX_OUT_OF_BOUNDS);
  153.         //      }
  154.         AppMemDataDefinition.AppMemObjectType.ObjectNameTitleIndex += dwFirstCounter;
  155.         AppMemDataDefinition.AppMemObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  156.         AppMemDataDefinition.AppMemBytesAllocated.CounterNameTitleIndex += dwFirstCounter;
  157.         AppMemDataDefinition.AppMemBytesAllocated.CounterHelpTitleIndex += dwFirstHelp;
  158.         AppMemDataDefinition.AppMemBytesAllocated.CounterOffset += 
  159.             (DWORD)((LPBYTE)&ac.dwAppMemBytesAllocated - (LPBYTE)&ac);
  160.         AppMemDataDefinition.AppMemAllocs.CounterNameTitleIndex += dwFirstCounter;
  161.         AppMemDataDefinition.AppMemAllocs.CounterHelpTitleIndex += dwFirstHelp;
  162.         AppMemDataDefinition.AppMemAllocs.CounterOffset =
  163.             (DWORD)((LPBYTE)&ac.dwAppMemAllocs - (LPBYTE)&ac);
  164.         AppMemDataDefinition.AppMemAllocsSec.CounterNameTitleIndex += dwFirstCounter;
  165.         AppMemDataDefinition.AppMemAllocsSec.CounterHelpTitleIndex += dwFirstHelp;
  166.         AppMemDataDefinition.AppMemAllocsSec.CounterOffset =
  167.             (DWORD)((LPBYTE)&ac.dwAppMemAllocsSec - (LPBYTE)&ac);
  168.         AppMemDataDefinition.AppMemReAllocs.CounterNameTitleIndex += dwFirstCounter;
  169.         AppMemDataDefinition.AppMemReAllocs.CounterHelpTitleIndex += dwFirstCounter;
  170.         AppMemDataDefinition.AppMemReAllocs.CounterOffset=
  171.             (DWORD)((LPBYTE)&ac.dwAppMemReAllocs - (LPBYTE)&ac);
  172.         AppMemDataDefinition.AppMemReAllocsSec.CounterNameTitleIndex += dwFirstCounter;
  173.         AppMemDataDefinition.AppMemReAllocsSec.CounterHelpTitleIndex += dwFirstHelp;
  174.         AppMemDataDefinition.AppMemReAllocsSec.CounterOffset =
  175.             (DWORD)((LPBYTE)&ac.dwAppMemReAllocsSec - (LPBYTE)&ac);
  176.         AppMemDataDefinition.AppMemFrees.CounterNameTitleIndex += dwFirstCounter;
  177.         AppMemDataDefinition.AppMemFrees.CounterHelpTitleIndex += dwFirstHelp;
  178.         AppMemDataDefinition.AppMemFrees.CounterOffset =
  179.             (DWORD)((LPBYTE)&ac.dwAppMemFrees - (LPBYTE)&ac);
  180.         AppMemDataDefinition.AppMemFreesSec.CounterNameTitleIndex += dwFirstCounter;
  181.         AppMemDataDefinition.AppMemFreesSec.CounterHelpTitleIndex += dwFirstHelp;
  182.         AppMemDataDefinition.AppMemFreesSec.CounterOffset =
  183.             (DWORD)((LPBYTE)&ac.dwAppMemFreesSec - (LPBYTE)&ac);
  184.         RegCloseKey (hKeyDriverPerf); // close key to registry
  185.         bInitOK = TRUE; // ok to use this function
  186.     }
  187.     dwOpenCount++;  // increment OPEN counter
  188.     status = ERROR_SUCCESS; // for successful exit
  189. OpenExitPoint:
  190.     return status;
  191. }
  192. DWORD APIENTRY
  193. CollectAppMemPerformanceData(
  194.     IN      LPWSTR  lpValueName,
  195.     IN OUT  LPVOID  *lppData,
  196.     IN OUT  LPDWORD lpcbTotalBytes,
  197.     IN OUT  LPDWORD lpNumObjectTypes
  198. )
  199. /*++
  200. Routine Description:
  201.     This routine will return the data for the Application memory counters
  202. Arguments:
  203.    IN       LPWSTR   lpValueName
  204.             pointer to a wide character string passed by registry.
  205.    IN OUT   LPVOID   *lppData
  206.          IN: pointer to the address of the buffer to receive the completed
  207.             PerfDataBlock and subordinate structures. This routine will
  208.             append its data to the buffer starting at the point referenced
  209.             by *lppData.
  210.          OUT: points to the first byte after the data structure added by this
  211.             routine. This routine updated the value at lppdata after appending
  212.             its data.
  213.    IN OUT   LPDWORD  lpcbTotalBytes
  214.          IN: the address of the DWORD that tells the size in bytes of the
  215.             buffer referenced by the lppData argument
  216.          OUT: the number of bytes added by this routine is writted to the
  217.             DWORD pointed to by this argument
  218.    IN OUT   LPDWORD  NumObjectTypes
  219.          IN: the address of the DWORD to receive the number of objects added
  220.             by this routine
  221.          OUT: the number of objects added by this routine is writted to the
  222.             DWORD pointed to by this argument
  223. Return Value:
  224.       ERROR_MORE_DATA if buffer passed is too small to hold data
  225.          any error conditions encountered are reported to the event log if
  226.          event logging is enabled.
  227.       ERROR_SUCCESS  if success or any other error. Errors, however are
  228.          also reported to the event log.
  229. --*/
  230. {
  231.     //  Variables for reformating the data
  232.     ULONG                       SpaceNeeded;
  233.     PERF_COUNTER_BLOCK          *pPerfCounterBlock;
  234.     PERF_INSTANCE_DEFINITION    *pPerfInstanceDef;
  235.     APPMEM_DATA_DEFINITION      *pAppMemDataDefinition;
  236.     DWORD                       dwQueryType;
  237.     DWORD                       dwInstanceIndex;
  238.     PAPPMEM_INSTANCE            pThisAppInstanceData = NULL;
  239.     BOOL                        bFreeMutex;
  240.     PAPPMEM_COUNTERS            pAC;
  241.     //
  242.     // before doing anything else, see if Open went OK
  243.     //
  244.     if ((!bInitOK) || (pDataHeader == NULL)) {
  245.         // unable to continue because open failed.
  246.         *lpcbTotalBytes = (DWORD) 0;
  247.         *lpNumObjectTypes = (DWORD) 0;
  248.         return ERROR_SUCCESS; // yes, this is a successful exit
  249.     }
  250.     // see if this is a foreign (i.e. non-NT) computer data request
  251.     //
  252.     dwQueryType = GetQueryType (lpValueName);
  253.     if (dwQueryType == QUERY_FOREIGN) {
  254.         // this routine does not service requests for data from
  255.         // Non-NT computers
  256.         *lpcbTotalBytes = (DWORD) 0;
  257.         *lpNumObjectTypes = (DWORD) 0;
  258.         return ERROR_SUCCESS;
  259.     }
  260.     if (dwQueryType == QUERY_ITEMS){
  261.         if ( !(IsNumberInUnicodeList (AppMemDataDefinition.AppMemObjectType.ObjectNameTitleIndex, lpValueName))) {
  262.             // request received for data object not provided by this routine
  263.             *lpcbTotalBytes = (DWORD) 0;
  264.             *lpNumObjectTypes = (DWORD) 0;
  265.             return ERROR_SUCCESS;
  266.         }
  267.     }
  268.     // if here, then this must be one for us so load data structures
  269.     pAppMemDataDefinition = (APPMEM_DATA_DEFINITION *) *lppData;
  270.     if (hAppMemMutex != NULL) {
  271.         if (WaitForSingleObject (hAppMemMutex, SHARED_MEMORY_MUTEX_TIMEOUT) == WAIT_FAILED) {
  272.             // unable to obtain a lock
  273.             bFreeMutex = FALSE;
  274.         } else {
  275.             bFreeMutex = TRUE;
  276.         }
  277.     } else {
  278.         bFreeMutex = FALSE;
  279.     }
  280.     
  281.     // always return an "instance sized" buffer after the definition blocks
  282.     // to prevent perfmon from reading bogus data. This is strictly a hack
  283.     // to accomodate how PERFMON handles the "0" instance case.
  284.     //  By doing this, perfmon won't choke when there are no instances
  285.     //  and the counter object & counters will be displayed in the
  286.     //  list boxes, even though no instances will be listed.
  287.     SpaceNeeded = sizeof(APPMEM_DATA_DEFINITION) +
  288.         ((pDataHeader->dwInstanceCount > 0 ? pDataHeader->dwInstanceCount : 1) * (
  289.             sizeof(PERF_INSTANCE_DEFINITION) +
  290.             MAX_SIZEOF_INSTANCE_NAME +
  291.             sizeof(APPMEM_COUNTERS)));
  292.     if ( *lpcbTotalBytes < SpaceNeeded ) {
  293.         // not enough room so return nothing.
  294.         *lpcbTotalBytes = (DWORD) 0;
  295.         *lpNumObjectTypes = (DWORD) 0;
  296.         return ERROR_MORE_DATA;
  297.     }
  298.     // copy the object & counter definition information
  299.     memmove(pAppMemDataDefinition,
  300.         &AppMemDataDefinition,
  301.         sizeof(APPMEM_DATA_DEFINITION));
  302.     // prepare to read the instance data
  303.     pPerfInstanceDef = (PERF_INSTANCE_DEFINITION *) &pAppMemDataDefinition[1];
  304.     // point to the first instance structure in the shared buffer
  305.     pThisAppInstanceData = FIRST_INUSE(pDataHeader);
  306.     // process each of the instances in the shared memory buffer
  307.     dwInstanceIndex = 0;
  308.     while ((dwInstanceIndex < pDataHeader->dwInstanceCount) &&
  309.             (pThisAppInstanceData != NULL)){
  310.         // initialize this instance
  311.         MonBuildInstanceDefinition (
  312.             pPerfInstanceDef,
  313.             &pAC, // pointer to first byte after instance def
  314.             0,  // no parent
  315.             0,  //  object to reference
  316.             (DWORD)PERF_NO_UNIQUE_ID,
  317.             pThisAppInstanceData->wcszInstanceName);
  318.         //
  319.         //    collect and format app memory perf data from shared memory
  320.         //
  321.         pAC->CounterBlock.ByteLength = sizeof(APPMEM_COUNTERS);
  322.         // set pointer to first counter data field
  323.         
  324.         pAC->dwAppMemBytesAllocated = pThisAppInstanceData->dwApplicationBytes;
  325.         pAC->dwAppMemAllocs = pThisAppInstanceData->dwAllocCalls;
  326.         pAC->dwAppMemAllocsSec = pThisAppInstanceData->dwAllocCalls;
  327.         pAC->dwAppMemReAllocs = pThisAppInstanceData->dwReAllocCalls;
  328.         pAC->dwAppMemReAllocsSec = pThisAppInstanceData->dwReAllocCalls;
  329.         pAC->dwAppMemFrees = pThisAppInstanceData->dwFreeCalls;
  330.         pAC->dwAppMemFreesSec = pThisAppInstanceData->dwFreeCalls;
  331.         // setup for the next instance
  332.         dwInstanceIndex++;
  333.         pThisAppInstanceData =
  334.             APPMEM_INST(pDataHeader, pThisAppInstanceData->dwOffsetOfNext);
  335.         pPerfInstanceDef =
  336.             (PERF_INSTANCE_DEFINITION *)((LPBYTE)pAC + sizeof(APPMEM_COUNTERS));
  337.     }
  338.     if (dwInstanceIndex == 0) {
  339.         // zero fill one instance sized block of data if there are no
  340.         // data instances
  341.         memset (pPerfInstanceDef, 0,
  342.             (sizeof(PERF_INSTANCE_DEFINITION) +
  343.             MAX_SIZEOF_INSTANCE_NAME +
  344.             sizeof(APPMEM_COUNTERS)));
  345.         // adjust pointer to point to end of zeroed block
  346.         (BYTE *)pPerfInstanceDef += (sizeof(PERF_INSTANCE_DEFINITION) +
  347.             MAX_SIZEOF_INSTANCE_NAME +
  348.             sizeof(APPMEM_COUNTERS));
  349.     }
  350.     // done with the shared memory so free the mutex if one was 
  351.     // acquired
  352.     if (bFreeMutex) {
  353.         ReleaseMutex (hAppMemMutex);
  354.     }
  355.     *lppData = (PVOID)pPerfInstanceDef;
  356.     // update arguments for return
  357.     *lpNumObjectTypes = 1;
  358.     pAppMemDataDefinition->AppMemObjectType.NumInstances = dwInstanceIndex;
  359.     pAppMemDataDefinition->AppMemObjectType.TotalByteLength =
  360.     *lpcbTotalBytes = (DWORD)((PBYTE)pPerfInstanceDef -
  361.                               (PBYTE) pAppMemDataDefinition);
  362.     return ERROR_SUCCESS;
  363. }
  364. DWORD APIENTRY
  365. CloseAppMemPerformanceData(
  366. )
  367. /*++
  368. Routine Description:
  369.     This routine closes the open handles to Application Memory
  370.         usage performance counters
  371. Arguments:
  372.     None.
  373. Return Value:
  374.     ERROR_SUCCESS
  375. --*/
  376. {
  377.     if ((--dwOpenCount) == 0) { // when this is the last thread...
  378.         if (hAppMemSharedMemory != NULL) CloseHandle(hAppMemSharedMemory);
  379.         if (hAppMemMutex != NULL)       CloseHandle(hAppMemMutex);
  380.         pDataHeader = NULL;
  381.         MonCloseEventLog();
  382.     }
  383.     return ERROR_SUCCESS;
  384. }