home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / winnt / perftool / perfdlls / perfgen / perfutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-10  |  10.9 KB  |  430 lines

  1. /*++
  2.  
  3. Copyright (c) 1995-6  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     perfutil.c
  8.  
  9. Abstract:
  10.  
  11.     This file implements the utility routines used to construct the
  12.     common parts of a PERF_INSTANCE_DEFINITION (see winperf.h) and
  13.     perform event logging functions.
  14.                  
  15. Created:    
  16.  
  17.     Bob Watson  28-Jul-1995
  18.  
  19. Revision History:
  20.  
  21. --*/
  22. //
  23. //  include files
  24. //        
  25. #include <windows.h>
  26. #include <string.h>
  27. #include <winperf.h>
  28. #include "genctrs.h"     // error message definition
  29. #include "perfmsg.h"
  30. #include "perfutil.h"
  31.  
  32. //
  33. // Global data definitions.
  34. //
  35.  
  36. ULONG ulInfoBufferSize = 0;
  37.  
  38. HANDLE hEventLog = NULL;      // event log handle for reporting events
  39.                               // initialized in Open... routines
  40. DWORD  dwLogUsers = 0;        // count of functions using event log
  41.  
  42. DWORD MESSAGE_LEVEL = 0;
  43.  
  44. WCHAR GLOBAL_STRING[] = L"Global";
  45. WCHAR FOREIGN_STRING[] = L"Foreign";
  46. WCHAR COSTLY_STRING[] = L"Costly";
  47.  
  48. WCHAR NULL_STRING[] = L"\0";    // pointer to null string 
  49.  
  50. // test for delimiter, end of line and non-digit characters
  51. // used by IsNumberInUnicodeList routine
  52. //
  53. #define DIGIT       1
  54. #define DELIMITER   2
  55. #define INVALID     3
  56.  
  57. #define EvalThisChar(c,d) ( \
  58.      (c == d) ? DELIMITER : \
  59.      (c == 0) ? DELIMITER : \
  60.      (c < (WCHAR)'0') ? INVALID : \
  61.      (c > (WCHAR)'9') ? INVALID : \
  62.      DIGIT)
  63.  
  64.  
  65. HANDLE
  66. MonOpenEventLog (
  67. )
  68. /*++
  69.  
  70. Routine Description:
  71.  
  72.     Reads the level of event logging from the registry and opens the
  73.         channel to the event logger for subsequent event log entries.
  74.  
  75. Arguments:
  76.  
  77.       None
  78.  
  79. Return Value:
  80.  
  81.     Handle to the event log for reporting events.
  82.     NULL if open not successful.
  83.  
  84. --*/
  85. {
  86.     HKEY hAppKey;
  87.     TCHAR LogLevelKeyName[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
  88.     TCHAR LogLevelValueName[] = "EventLogLevel";
  89.  
  90.     LONG lStatus;
  91.  
  92.     DWORD dwLogLevel;
  93.     DWORD dwValueType;
  94.     DWORD dwValueSize;
  95.    
  96.     // if global value of the logging level not initialized or is disabled, 
  97.     //  check the registry to see if it should be updated.
  98.  
  99.     if (!MESSAGE_LEVEL) {
  100.  
  101.        lStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  102.                                LogLevelKeyName,
  103.                                0,                         
  104.                                KEY_READ,
  105.                                &hAppKey);
  106.  
  107.        dwValueSize = sizeof (dwLogLevel);
  108.  
  109.        if (lStatus == ERROR_SUCCESS) {
  110.             lStatus = RegQueryValueEx (hAppKey,
  111.                                LogLevelValueName,
  112.                                (LPDWORD)NULL,           
  113.                                &dwValueType,
  114.                                (LPBYTE)&dwLogLevel,
  115.                                &dwValueSize);
  116.  
  117.             if (lStatus == ERROR_SUCCESS) {
  118.                MESSAGE_LEVEL = dwLogLevel;
  119.             } else {
  120.                MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  121.             }
  122.             RegCloseKey (hAppKey);
  123.        } else {
  124.          MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  125.        }
  126.     }
  127.        
  128.     if (hEventLog == NULL){
  129.          hEventLog = RegisterEventSource (
  130.             (LPTSTR)NULL,            // Use Local Machine
  131.             APP_NAME);               // event log app name to find in registry
  132.  
  133.          if (hEventLog != NULL) {
  134.             REPORT_INFORMATION (UTIL_LOG_OPEN, LOG_DEBUG);
  135.          }
  136.     }
  137.     
  138.     if (hEventLog != NULL) {
  139.          dwLogUsers++;           // increment count of perfctr log users
  140.     }
  141.     return (hEventLog);
  142. }
  143.  
  144.  
  145. VOID
  146. MonCloseEventLog (
  147. )
  148. /*++
  149.  
  150. Routine Description:
  151.  
  152.       Closes the handle to the event logger if this is the last caller
  153.       
  154. Arguments:
  155.  
  156.       None
  157.  
  158. Return Value:
  159.  
  160.       None
  161.  
  162. --*/
  163. {
  164.     if (hEventLog != NULL) {
  165.         dwLogUsers--;         // decrement usage
  166.         if (dwLogUsers <= 0) {    // and if we're the last, then close up log
  167.             REPORT_INFORMATION (UTIL_CLOSING_LOG, LOG_DEBUG);
  168.             DeregisterEventSource (hEventLog);
  169.         }
  170.     }
  171. }
  172.  
  173. DWORD
  174. GetQueryType (
  175.     IN LPWSTR lpValue
  176. )
  177. /*++
  178.  
  179. GetQueryType
  180.  
  181.     returns the type of query described in the lpValue string so that
  182.     the appropriate processing method may be used
  183.  
  184. Arguments
  185.  
  186.     IN lpValue
  187.         string passed to PerfRegQuery Value for processing
  188.  
  189. Return Value
  190.  
  191.     QUERY_GLOBAL
  192.         if lpValue == 0 (null pointer)
  193.            lpValue == pointer to Null string
  194.            lpValue == pointer to "Global" string
  195.  
  196.     QUERY_FOREIGN
  197.         if lpValue == pointer to "Foriegn" string
  198.  
  199.     QUERY_COSTLY
  200.         if lpValue == pointer to "Costly" string
  201.  
  202.     otherwise:
  203.  
  204.     QUERY_ITEMS
  205.  
  206. --*/
  207. {
  208.     WCHAR   *pwcArgChar, *pwcTypeChar;
  209.     BOOL    bFound;
  210.  
  211.     if (lpValue == 0) {
  212.         return QUERY_GLOBAL;
  213.     } else if (*lpValue == 0) {
  214.         return QUERY_GLOBAL;
  215.     }
  216.  
  217.     // check for "Global" request
  218.  
  219.     pwcArgChar = lpValue;
  220.     pwcTypeChar = GLOBAL_STRING;
  221.     bFound = TRUE;  // assume found until contradicted
  222.  
  223.     // check to the length of the shortest string
  224.     
  225.     while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  226.         if (*pwcArgChar++ != *pwcTypeChar++) {
  227.             bFound = FALSE; // no match
  228.             break;          // bail out now
  229.         }
  230.     }
  231.  
  232.     if (bFound) return QUERY_GLOBAL;
  233.  
  234.     // check for "Foreign" request
  235.     
  236.     pwcArgChar = lpValue;
  237.     pwcTypeChar = FOREIGN_STRING;
  238.     bFound = TRUE;  // assume found until contradicted
  239.  
  240.     // check to the length of the shortest string
  241.     
  242.     while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  243.         if (*pwcArgChar++ != *pwcTypeChar++) {
  244.             bFound = FALSE; // no match
  245.             break;          // bail out now
  246.         }
  247.     }
  248.  
  249.     if (bFound) return QUERY_FOREIGN;
  250.  
  251.     // check for "Costly" request
  252.     
  253.     pwcArgChar = lpValue;
  254.     pwcTypeChar = COSTLY_STRING;
  255.     bFound = TRUE;  // assume found until contradicted
  256.  
  257.     // check to the length of the shortest string
  258.     
  259.     while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  260.         if (*pwcArgChar++ != *pwcTypeChar++) {
  261.             bFound = FALSE; // no match
  262.             break;          // bail out now
  263.         }
  264.     }
  265.  
  266.     if (bFound) return QUERY_COSTLY;
  267.  
  268.     // if not Global and not Foreign and not Costly, 
  269.     // then it must be an item list
  270.     
  271.     return QUERY_ITEMS;
  272.  
  273. }
  274.  
  275. BOOL
  276. IsNumberInUnicodeList (
  277.     IN DWORD   dwNumber,
  278.     IN LPWSTR  lpwszUnicodeList
  279. )
  280. /*++
  281.  
  282. IsNumberInUnicodeList
  283.  
  284. Arguments:
  285.         
  286.     IN dwNumber
  287.         DWORD number to find in list
  288.  
  289.     IN lpwszUnicodeList
  290.         Null terminated, Space delimited list of decimal numbers
  291.  
  292. Return Value:
  293.  
  294.     TRUE:
  295.             dwNumber was found in the list of unicode number strings
  296.  
  297.     FALSE:
  298.             dwNumber was not found in the list.
  299.  
  300. --*/
  301. {
  302.     DWORD   dwThisNumber;
  303.     WCHAR   *pwcThisChar;
  304.     BOOL    bValidNumber;
  305.     BOOL    bNewItem;
  306.     WCHAR   wcDelimiter;    // could be an argument to be more flexible
  307.  
  308.     if (lpwszUnicodeList == 0) return FALSE;    // null pointer, # not founde
  309.  
  310.     pwcThisChar = lpwszUnicodeList;
  311.     dwThisNumber = 0;
  312.     wcDelimiter = (WCHAR)' ';
  313.     bValidNumber = FALSE;
  314.     bNewItem = TRUE;
  315.     
  316.     while (TRUE) {
  317.         switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  318.             case DIGIT:
  319.                 // if this is the first digit after a delimiter, then 
  320.                 // set flags to start computing the new number
  321.                 if (bNewItem) {
  322.                     bNewItem = FALSE;
  323.                     bValidNumber = TRUE;
  324.                 }
  325.                 if (bValidNumber) {
  326.                     dwThisNumber *= 10;
  327.                     dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  328.                 }
  329.                 break;
  330.             
  331.             case DELIMITER:
  332.                 // a delimter is either the delimiter character or the 
  333.                 // end of the string ('\0') if when the delimiter has been
  334.                 // reached a valid number was found, then compare it to the
  335.                 // number from the argument list. if this is the end of the
  336.                 // string and no match was found, then return.
  337.                 //
  338.                 if (bValidNumber) {
  339.                     if (dwThisNumber == dwNumber) return TRUE;
  340.                     bValidNumber = FALSE;
  341.                 }
  342.                 if (*pwcThisChar == 0) {
  343.                     return FALSE;
  344.                 } else {
  345.                     bNewItem = TRUE;
  346.                     dwThisNumber = 0;
  347.                 }
  348.                 break;
  349.  
  350.             case INVALID:
  351.                 // if an invalid character was encountered, ignore all
  352.                 // characters up to the next delimiter and then start fresh.
  353.                 // the invalid number is not compared.
  354.                 bValidNumber = FALSE;
  355.                 break;
  356.  
  357.             default:
  358.                 break;
  359.  
  360.         }
  361.         pwcThisChar++;
  362.     }
  363.     return FALSE;
  364. }   // IsNumberInUnicodeList
  365.  
  366.  
  367. BOOL
  368. MonBuildInstanceDefinition(
  369.     PERF_INSTANCE_DEFINITION *pBuffer,
  370.     PVOID *pBufferNext,
  371.     DWORD ParentObjectTitleIndex,
  372.     DWORD ParentObjectInstance,
  373.     DWORD UniqueID,
  374.     LPWSTR Name
  375.     )
  376. /*++
  377.  
  378.     MonBuildInstanceDefinition  -   Build an instance of an object
  379.  
  380.         Inputs:
  381.  
  382.             pBuffer         -   pointer to buffer where instance is to
  383.                                 be constructed
  384.  
  385.             pBufferNext     -   pointer to a pointer which will contain
  386.                                 next available location, DWORD aligned
  387.  
  388.             ParentObjectTitleIndex
  389.                             -   Title Index of parent object type; 0 if
  390.                                 no parent object
  391.  
  392.             ParentObjectInstance
  393.                             -   Index into instances of parent object
  394.                                 type, starting at 0, for this instances
  395.                                 parent object instance
  396.  
  397.             UniqueID        -   a unique identifier which should be used
  398.                                 instead of the Name for identifying
  399.                                 this instance
  400.  
  401.             Name            -   Name of this instance
  402. --*/
  403. {
  404.     DWORD NameLength;
  405.     LPWSTR pName;
  406.     //
  407.     //  Include trailing null in name size
  408.     //
  409.  
  410.     NameLength = (lstrlenW(Name) + 1) * sizeof(WCHAR);
  411.  
  412.     pBuffer->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
  413.                           DWORD_MULTIPLE(NameLength);
  414.  
  415.     pBuffer->ParentObjectTitleIndex = ParentObjectTitleIndex;
  416.     pBuffer->ParentObjectInstance = ParentObjectInstance;
  417.     pBuffer->UniqueID = UniqueID;
  418.     pBuffer->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
  419.     pBuffer->NameLength = NameLength;
  420.  
  421.     // copy name to name buffer
  422.     pName = (LPWSTR)&pBuffer[1];
  423.     RtlMoveMemory(pName,Name,NameLength);
  424.  
  425.     // update "next byte" pointer
  426.     *pBufferNext = (PVOID) ((PCHAR) pBuffer + pBuffer->ByteLength);
  427.  
  428.     return 0;
  429. }
  430.