//+------------------------------------------------------------------------- // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1999 - 1999 // // File: certperf.cpp // // Contents: Certificate Performance Counter Functions // // Functions: // OpenCertPerformanceData // CollectCertPerformanceData // CloseCertPerformanceData // CertPerfDllMain // // CertPerfGetCertificateChainBefore // CertPerfGetCertificateChainAfter // // History: 04-May-99 philh created //-------------------------------------------------------------------------- #include "global.hxx" #include #ifdef STATIC #undef STATIC #endif #define STATIC #define DWORD_MULTIPLE(x) (((x+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD)) #define CERT_PERF_REGPATH \ L"SYSTEM\\CurrentControlSet\\Services\\crypt32\\Performance" #define CERT_PERF_SHARED_MEMORY_FILE_NAME \ L"crypt32CertPerfFile" #define CERT_PERF_SHARED_MEMORY_MUTEX_NAME \ L"crypt32CertPerfMutex" #define CERT_PERF_TS_GLOBAL_PREFIX \ L"Global\\" #define CERT_PERF_TS_SHARED_MEMORY_FILE_NAME \ CERT_PERF_TS_GLOBAL_PREFIX CERT_PERF_SHARED_MEMORY_FILE_NAME #define CERT_PERF_TS_SHARED_MEMORY_MUTEX_NAME \ CERT_PERF_TS_GLOBAL_PREFIX CERT_PERF_SHARED_MEMORY_MUTEX_NAME #define CERT_PERF_SHARED_MEMORY_MUTEX_TIMEOUT ((DWORD) 5000L) #define CERT_PERF_MAX_PROCESS_NAME_LEN 32 #define CERT_PERF_MAX_PROCESS_CNT 50 #include // Note, a dwIndex >= CERT_PERF_MAX_PROCESS_CNT indicates an empty or // the end of a list typedef struct _CERT_PERF_PROCESS_DATA { DWORD dwNextIndex; DWORD dwPrevIndex; DWORD dwProcessId; DWORD dwReserved; WCHAR wcszProcessName[CERT_PERF_MAX_PROCESS_NAME_LEN]; CERT_PERF_PROCESS_COUNTERS Counters; } CERT_PERF_PROCESS_DATA, *PCERT_PERF_PROCESS_DATA; typedef struct _CERT_PERF_SHARED_MEMORY { DWORD dwProcessCnt; DWORD dwFirstInUseIndex; DWORD dwFirstFreeIndex; DWORD dwReserved; CERT_PERF_PROCESS_DATA rgProcessData[CERT_PERF_MAX_PROCESS_CNT]; } CERT_PERF_SHARED_MEMORY, *PCERT_PERF_SHARED_MEMORY; // Certificate performance counters typedef struct _CERT_PERF_DATA_DEFINITION { PERF_OBJECT_TYPE ObjectType; PERF_COUNTER_DEFINITION ChainCnt; PERF_COUNTER_DEFINITION ChainElementCnt; PERF_COUNTER_DEFINITION ChainEngineCurrentCnt; PERF_COUNTER_DEFINITION ChainEngineTotalCnt; PERF_COUNTER_DEFINITION ChainEngineResyncCnt; PERF_COUNTER_DEFINITION ChainCertCacheCnt; PERF_COUNTER_DEFINITION ChainCtlCacheCnt; PERF_COUNTER_DEFINITION ChainEndCertInCacheCnt; PERF_COUNTER_DEFINITION ChainCacheEndCertCnt; PERF_COUNTER_DEFINITION ChainRevocationCnt; PERF_COUNTER_DEFINITION ChainRevokedCnt; PERF_COUNTER_DEFINITION ChainRevocationOfflineCnt; PERF_COUNTER_DEFINITION ChainNoRevocationCheckCnt; PERF_COUNTER_DEFINITION ChainVerifyCertSignatureCnt; PERF_COUNTER_DEFINITION ChainCompareIssuerPublicKeyCnt; PERF_COUNTER_DEFINITION ChainVerifyCtlSignatureCnt; PERF_COUNTER_DEFINITION ChainBeenVerifiedCtlSignatureCnt; PERF_COUNTER_DEFINITION ChainUrlIssuerCnt; PERF_COUNTER_DEFINITION ChainCacheOnlyUrlIssuerCnt; PERF_COUNTER_DEFINITION ChainRequestedEngineResyncCnt; PERF_COUNTER_DEFINITION ChangeNotifyCnt; PERF_COUNTER_DEFINITION ChangeNotifyLmGpCnt; PERF_COUNTER_DEFINITION ChangeNotifyCuGpCnt; PERF_COUNTER_DEFINITION ChangeNotifyCuMyCnt; PERF_COUNTER_DEFINITION ChangeNotifyRegCnt; PERF_COUNTER_DEFINITION StoreCurrentCnt; PERF_COUNTER_DEFINITION StoreTotalCnt; PERF_COUNTER_DEFINITION StoreRegCurrentCnt; PERF_COUNTER_DEFINITION StoreRegTotalCnt; PERF_COUNTER_DEFINITION RegElementReadCnt; PERF_COUNTER_DEFINITION RegElementWriteCnt; PERF_COUNTER_DEFINITION RegElementDeleteCnt; PERF_COUNTER_DEFINITION CertElementCurrentCnt; PERF_COUNTER_DEFINITION CertElementTotalCnt; PERF_COUNTER_DEFINITION CrlElementCurrentCnt; PERF_COUNTER_DEFINITION CrlElementTotalCnt; PERF_COUNTER_DEFINITION CtlElementCurrentCnt; PERF_COUNTER_DEFINITION CtlElementTotalCnt; //--### Add New Counters ###-- } CERT_PERF_DATA_DEFINITION, *PCERT_PERF_DATA_DEFINITION; typedef struct _CERT_PERF_COUNTERS { PERF_COUNTER_BLOCK CounterBlock; DWORD dwChainCnt; DWORD dwChainElementCnt; DWORD dwChainEngineCurrentCnt; DWORD dwChainEngineTotalCnt; DWORD dwChainEngineResyncCnt; DWORD dwChainCertCacheCnt; DWORD dwChainCtlCacheCnt; DWORD dwChainEndCertInCacheCnt; DWORD dwChainCacheEndCertCnt; DWORD dwChainRevocationCnt; DWORD dwChainRevokedCnt; DWORD dwChainRevocationOfflineCnt; DWORD dwChainNoRevocationCheckCnt; DWORD dwChainVerifyCertSignatureCnt; DWORD dwChainCompareIssuerPublicKeyCnt; DWORD dwChainVerifyCtlSignatureCnt; DWORD dwChainBeenVerifiedCtlSignatureCnt; DWORD dwChainUrlIssuerCnt; DWORD dwChainCacheOnlyUrlIssuerCnt; DWORD dwChainRequestedEngineResyncCnt; DWORD dwChangeNotifyCnt; DWORD dwChangeNotifyLmGpCnt; DWORD dwChangeNotifyCuGpCnt; DWORD dwChangeNotifyCuMyCnt; DWORD dwChangeNotifyRegCnt; DWORD dwStoreCurrentCnt; DWORD dwStoreTotalCnt; DWORD dwStoreRegCurrentCnt; DWORD dwStoreRegTotalCnt; DWORD dwRegElementReadCnt; DWORD dwRegElementWriteCnt; DWORD dwRegElementDeleteCnt; DWORD dwCertElementCurrentCnt; DWORD dwCertElementTotalCnt; DWORD dwCrlElementCurrentCnt; DWORD dwCrlElementTotalCnt; DWORD dwCtlElementCurrentCnt; DWORD dwCtlElementTotalCnt; //--### Add New Counters ###-- } CERT_PERF_COUNTERS, *PCERT_PERF_COUNTERS; #include //+---------------------------------------------------------------------- // The following are set at DLL_PROCESS_ATTACH if certperf.reg has been // regedit'ed and certperf.ini has been lodctr'ed. Otherwise, they remain // NULL. //----------------------------------------------------------------------- HANDLE hCertPerfSharedMemoryMutex; HANDLE hCertPerfSharedMemoryFile; PCERT_PERF_SHARED_MEMORY pCertPerfSharedMemory; PCERT_PERF_PROCESS_DATA pCertPerfProcessData; PCERT_PERF_PROCESS_COUNTERS pCertPerfProcessCounters; // Always initialized CRITICAL_SECTION CertPerfProcessCriticalSection; #define IMPURE 0 CERT_PERF_DATA_DEFINITION CertPerfDataDefinition = { // PERF_OBJECT_TYPE ObjectType { IMPURE, // TotalByteLength sizeof(CERT_PERF_DATA_DEFINITION), sizeof(PERF_OBJECT_TYPE), IMPURE, // ObjectNameTitleIndex: dwFirstCounter + CERT_OBJ 0, IMPURE, // ObjectHelpTitleIndex: dwFirstHelp + CERT_OBJ 0, PERF_DETAIL_NOVICE, (sizeof(CERT_PERF_DATA_DEFINITION) - sizeof(PERF_OBJECT_TYPE))/ sizeof(PERF_COUNTER_DEFINITION), 0, // ChainCnt is the default counter IMPURE, // NumInstances 0, // unicode instance names {0,0}, {0,0} }, // 0 - PERF_COUNTER_DEFINITION ChainCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCnt), offsetof(CERT_PERF_COUNTERS, dwChainCnt), }, // 1 - PERF_COUNTER_DEFINITION ChainElementCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainElementCnt), offsetof(CERT_PERF_COUNTERS, dwChainElementCnt), }, // 2 - PERF_COUNTER_DEFINITION ChainEngineCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainEngineCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwChainEngineCurrentCnt), }, // 3 - PERF_COUNTER_DEFINITION ChainEngineTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainEngineTotalCnt), offsetof(CERT_PERF_COUNTERS, dwChainEngineTotalCnt), }, // 4 - PERF_COUNTER_DEFINITION ChainEngineResyncCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainEngineResyncCnt), offsetof(CERT_PERF_COUNTERS, dwChainEngineResyncCnt), }, // 5 - PERF_COUNTER_DEFINITION ChainCertCacheCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCertCacheCnt), offsetof(CERT_PERF_COUNTERS, dwChainCertCacheCnt), }, // 6 - PERF_COUNTER_DEFINITION ChainCtlCacheCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCtlCacheCnt), offsetof(CERT_PERF_COUNTERS, dwChainCtlCacheCnt), }, // 7 - PERF_COUNTER_DEFINITION ChainEndCertInCacheCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainEndCertInCacheCnt), offsetof(CERT_PERF_COUNTERS, dwChainEndCertInCacheCnt), }, // 8 - PERF_COUNTER_DEFINITION ChainCacheEndCertCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCacheEndCertCnt), offsetof(CERT_PERF_COUNTERS, dwChainCacheEndCertCnt), }, // 9 - PERF_COUNTER_DEFINITION ChainRevocationCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainRevocationCnt), offsetof(CERT_PERF_COUNTERS, dwChainRevocationCnt), }, // 10 - PERF_COUNTER_DEFINITION ChainRevokedCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainRevokedCnt), offsetof(CERT_PERF_COUNTERS, dwChainRevokedCnt), }, // 11 - PERF_COUNTER_DEFINITION ChainRevocationOfflineCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainRevocationOfflineCnt), offsetof(CERT_PERF_COUNTERS, dwChainRevocationOfflineCnt), }, // 12 - PERF_COUNTER_DEFINITION ChainNoRevocationCheckCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainNoRevocationCheckCnt), offsetof(CERT_PERF_COUNTERS, dwChainNoRevocationCheckCnt), }, // 13 - PERF_COUNTER_DEFINITION ChainVerifyCertSignatureCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainVerifyCertSignatureCnt), offsetof(CERT_PERF_COUNTERS, dwChainVerifyCertSignatureCnt), }, // 14 - PERF_COUNTER_DEFINITION ChainCompareIssuerPublicKeyCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCompareIssuerPublicKeyCnt), offsetof(CERT_PERF_COUNTERS, dwChainCompareIssuerPublicKeyCnt), }, // 15 - PERF_COUNTER_DEFINITION ChainVerifyCtlSignatureCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainVerifyCtlSignatureCnt), offsetof(CERT_PERF_COUNTERS, dwChainVerifyCtlSignatureCnt), }, // 16 - PERF_COUNTER_DEFINITION ChainBeenVerifiedCtlSignatureCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainBeenVerifiedCtlSignatureCnt), offsetof(CERT_PERF_COUNTERS, dwChainBeenVerifiedCtlSignatureCnt), }, // 17 - PERF_COUNTER_DEFINITION ChainUrlIssuerCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainUrlIssuerCnt), offsetof(CERT_PERF_COUNTERS, dwChainUrlIssuerCnt), }, // 18 - PERF_COUNTER_DEFINITION ChainCacheOnlyUrlIssuerCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainCacheOnlyUrlIssuerCnt), offsetof(CERT_PERF_COUNTERS, dwChainCacheOnlyUrlIssuerCnt), }, // 19 - PERF_COUNTER_DEFINITION ChainRequestedEngineResyncCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChainRequestedEngineResyncCnt), offsetof(CERT_PERF_COUNTERS, dwChainRequestedEngineResyncCnt), }, // 20 - PERF_COUNTER_DEFINITION ChangeNotifyCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChangeNotifyCnt), offsetof(CERT_PERF_COUNTERS, dwChangeNotifyCnt), }, // 21 - PERF_COUNTER_DEFINITION ChangeNotifyLmGpCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChangeNotifyLmGpCnt), offsetof(CERT_PERF_COUNTERS, dwChangeNotifyLmGpCnt), }, // 22 - PERF_COUNTER_DEFINITION ChangeNotifyCuGpCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChangeNotifyCuGpCnt), offsetof(CERT_PERF_COUNTERS, dwChangeNotifyCuGpCnt), }, // 23 - PERF_COUNTER_DEFINITION ChangeNotifyCuMyCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChangeNotifyCuMyCnt), offsetof(CERT_PERF_COUNTERS, dwChangeNotifyCuMyCnt), }, // 24 - PERF_COUNTER_DEFINITION ChangeNotifyRegCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwChangeNotifyRegCnt), offsetof(CERT_PERF_COUNTERS, dwChangeNotifyRegCnt), }, // 25 - PERF_COUNTER_DEFINITION StoreCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwStoreCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwStoreCurrentCnt), }, // 26 - PERF_COUNTER_DEFINITION StoreTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwStoreTotalCnt), offsetof(CERT_PERF_COUNTERS, dwStoreTotalCnt), }, // 27 - PERF_COUNTER_DEFINITION StoreRegCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwStoreRegCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwStoreRegCurrentCnt), }, // 28 - PERF_COUNTER_DEFINITION StoreRegTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwStoreRegTotalCnt), offsetof(CERT_PERF_COUNTERS, dwStoreRegTotalCnt), }, // 29 - PERF_COUNTER_DEFINITION RegElementReadCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwRegElementReadCnt), offsetof(CERT_PERF_COUNTERS, dwRegElementReadCnt), }, // 30 - PERF_COUNTER_DEFINITION RegElementWriteCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwRegElementWriteCnt), offsetof(CERT_PERF_COUNTERS, dwRegElementWriteCnt), }, // 31 - PERF_COUNTER_DEFINITION RegElementDeleteCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwRegElementDeleteCnt), offsetof(CERT_PERF_COUNTERS, dwRegElementDeleteCnt), }, // 32 - PERF_COUNTER_DEFINITION CertElementCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCertElementCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwCertElementCurrentCnt), }, // 33 - PERF_COUNTER_DEFINITION CertElementTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCertElementTotalCnt), offsetof(CERT_PERF_COUNTERS, dwCertElementTotalCnt), }, // 34 - PERF_COUNTER_DEFINITION CrlElementCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCrlElementCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwCrlElementCurrentCnt), }, // 35 - PERF_COUNTER_DEFINITION CrlElementTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCrlElementTotalCnt), offsetof(CERT_PERF_COUNTERS, dwCrlElementTotalCnt), }, // 36 - PERF_COUNTER_DEFINITION CtlElementCurrentCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCtlElementCurrentCnt), offsetof(CERT_PERF_COUNTERS, dwCtlElementCurrentCnt), }, // 37 - PERF_COUNTER_DEFINITION CtlElementTotalCnt { sizeof(PERF_COUNTER_DEFINITION), IMPURE, // CounterNameTitleIndex: dwFirstCounter + 0, IMPURE, // CounterHelpTitleIndex: dwFirstHelp + 0, -2, PERF_DETAIL_NOVICE, PERF_COUNTER_RAWCOUNT, sizeof(((PCERT_PERF_COUNTERS) 0)->dwCtlElementTotalCnt), offsetof(CERT_PERF_COUNTERS, dwCtlElementTotalCnt), }, //--### Add New Counters ###-- }; STATIC BOOL I_CertPerfSetNameAndHelpIndices() { BOOL fResult; HKEY hKey = NULL; DWORD dwType; DWORD cbValue; DWORD dwFirstCounter; DWORD dwFirstHelp; if (!FIsWinNT()) return FALSE; if (ERROR_SUCCESS != RegOpenKeyExW( HKEY_LOCAL_MACHINE, CERT_PERF_REGPATH, 0, // dwReserved KEY_READ, &hKey)) goto ErrorReturn; cbValue = sizeof(DWORD); if (ERROR_SUCCESS != RegQueryValueExW( hKey, L"First Counter", NULL, // pdwReserved &dwType, (PBYTE) &dwFirstCounter, &cbValue)) goto ErrorReturn; cbValue = sizeof(DWORD); if (ERROR_SUCCESS != RegQueryValueExW( hKey, L"First Help", NULL, // pdwReserved &dwType, (PBYTE) &dwFirstHelp, &cbValue)) goto ErrorReturn; // Update CertPerfDataDefinitions' counter and help name indices CertPerfDataDefinition.ObjectType.ObjectNameTitleIndex = dwFirstCounter + CERT_OBJ; CertPerfDataDefinition.ObjectType.ObjectHelpTitleIndex = dwFirstHelp + CERT_OBJ; CertPerfDataDefinition.ChainCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_CNT; CertPerfDataDefinition.ChainCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_CNT; CertPerfDataDefinition.ChainElementCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_ELEMENT_CNT; CertPerfDataDefinition.ChainElementCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_ELEMENT_CNT; CertPerfDataDefinition.ChainEngineCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_ENGINE_CURRENT_CNT; CertPerfDataDefinition.ChainEngineCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_ENGINE_CURRENT_CNT; CertPerfDataDefinition.ChainEngineTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_ENGINE_TOTAL_CNT; CertPerfDataDefinition.ChainEngineTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_ENGINE_TOTAL_CNT; CertPerfDataDefinition.ChainEngineResyncCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_ENGINE_RESYNC_CNT; CertPerfDataDefinition.ChainEngineResyncCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_ENGINE_RESYNC_CNT; CertPerfDataDefinition.ChainCertCacheCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_CERT_CACHE_CNT; CertPerfDataDefinition.ChainCertCacheCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_CERT_CACHE_CNT; CertPerfDataDefinition.ChainCtlCacheCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_CTL_CACHE_CNT; CertPerfDataDefinition.ChainCtlCacheCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_CTL_CACHE_CNT; CertPerfDataDefinition.ChainEndCertInCacheCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_END_CERT_IN_CACHE_CNT; CertPerfDataDefinition.ChainEndCertInCacheCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_END_CERT_IN_CACHE_CNT; CertPerfDataDefinition.ChainCacheEndCertCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_CACHE_END_CERT_CNT; CertPerfDataDefinition.ChainCacheEndCertCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_CACHE_END_CERT_CNT; CertPerfDataDefinition.ChainRevocationCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_REVOCATION_CNT; CertPerfDataDefinition.ChainRevocationCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_REVOCATION_CNT; CertPerfDataDefinition.ChainRevokedCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_REVOKED_CNT; CertPerfDataDefinition.ChainRevokedCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_REVOKED_CNT; CertPerfDataDefinition.ChainRevocationOfflineCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_REVOCATION_OFFLINE_CNT; CertPerfDataDefinition.ChainRevocationOfflineCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_REVOCATION_OFFLINE_CNT; CertPerfDataDefinition.ChainNoRevocationCheckCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_NO_REVOCATION_CHECK_CNT; CertPerfDataDefinition.ChainNoRevocationCheckCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_NO_REVOCATION_CHECK_CNT; CertPerfDataDefinition.ChainVerifyCertSignatureCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_VERIFY_CERT_SIGNATURE_CNT; CertPerfDataDefinition.ChainVerifyCertSignatureCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_VERIFY_CERT_SIGNATURE_CNT; CertPerfDataDefinition.ChainCompareIssuerPublicKeyCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_COMPARE_ISSUER_PUBLIC_KEY_CNT; CertPerfDataDefinition.ChainCompareIssuerPublicKeyCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_COMPARE_ISSUER_PUBLIC_KEY_CNT; CertPerfDataDefinition.ChainVerifyCtlSignatureCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_VERIFY_CTL_SIGNATURE_CNT; CertPerfDataDefinition.ChainVerifyCtlSignatureCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_VERIFY_CTL_SIGNATURE_CNT; CertPerfDataDefinition.ChainBeenVerifiedCtlSignatureCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_BEEN_VERIFIED_CTL_SIGNATURE_CNT; CertPerfDataDefinition.ChainBeenVerifiedCtlSignatureCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_BEEN_VERIFIED_CTL_SIGNATURE_CNT; CertPerfDataDefinition.ChainUrlIssuerCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_URL_ISSUER_CNT; CertPerfDataDefinition.ChainUrlIssuerCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_URL_ISSUER_CNT; CertPerfDataDefinition.ChainCacheOnlyUrlIssuerCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_CACHE_ONLY_URL_ISSUER_CNT; CertPerfDataDefinition.ChainCacheOnlyUrlIssuerCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_CACHE_ONLY_URL_ISSUER_CNT; CertPerfDataDefinition.ChainRequestedEngineResyncCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHAIN_REQUESTED_ENGINE_RESYNC_CNT; CertPerfDataDefinition.ChainRequestedEngineResyncCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHAIN_REQUESTED_ENGINE_RESYNC_CNT; CertPerfDataDefinition.ChangeNotifyCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHANGE_NOTIFY_CNT; CertPerfDataDefinition.ChangeNotifyCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHANGE_NOTIFY_CNT; CertPerfDataDefinition.ChangeNotifyLmGpCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHANGE_NOTIFY_LM_GP_CNT; CertPerfDataDefinition.ChangeNotifyLmGpCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHANGE_NOTIFY_LM_GP_CNT; CertPerfDataDefinition.ChangeNotifyCuGpCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHANGE_NOTIFY_CU_GP_CNT; CertPerfDataDefinition.ChangeNotifyCuGpCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHANGE_NOTIFY_CU_GP_CNT; CertPerfDataDefinition.ChangeNotifyCuMyCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHANGE_NOTIFY_CU_MY_CNT; CertPerfDataDefinition.ChangeNotifyCuMyCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHANGE_NOTIFY_CU_MY_CNT; CertPerfDataDefinition.ChangeNotifyRegCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CHANGE_NOTIFY_REG_CNT; CertPerfDataDefinition.ChangeNotifyRegCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CHANGE_NOTIFY_REG_CNT; CertPerfDataDefinition.StoreCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_STORE_CURRENT_CNT; CertPerfDataDefinition.StoreCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_STORE_CURRENT_CNT; CertPerfDataDefinition.StoreTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_STORE_TOTAL_CNT; CertPerfDataDefinition.StoreTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_STORE_TOTAL_CNT; CertPerfDataDefinition.StoreRegCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_STORE_REG_CURRENT_CNT; CertPerfDataDefinition.StoreRegCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_STORE_REG_CURRENT_CNT; CertPerfDataDefinition.StoreRegTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_STORE_REG_TOTAL_CNT; CertPerfDataDefinition.StoreRegTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_STORE_REG_TOTAL_CNT; CertPerfDataDefinition.RegElementReadCnt.CounterNameTitleIndex = dwFirstCounter + CERT_REG_ELEMENT_READ_CNT; CertPerfDataDefinition.RegElementReadCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_REG_ELEMENT_READ_CNT; CertPerfDataDefinition.RegElementWriteCnt.CounterNameTitleIndex = dwFirstCounter + CERT_REG_ELEMENT_WRITE_CNT; CertPerfDataDefinition.RegElementWriteCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_REG_ELEMENT_WRITE_CNT; CertPerfDataDefinition.RegElementDeleteCnt.CounterNameTitleIndex = dwFirstCounter + CERT_REG_ELEMENT_DELETE_CNT; CertPerfDataDefinition.RegElementDeleteCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_REG_ELEMENT_DELETE_CNT; CertPerfDataDefinition.CertElementCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CERT_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CertElementCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CERT_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CertElementTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CERT_ELEMENT_TOTAL_CNT; CertPerfDataDefinition.CertElementTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CERT_ELEMENT_TOTAL_CNT; CertPerfDataDefinition.CrlElementCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CRL_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CrlElementCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CRL_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CrlElementTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CRL_ELEMENT_TOTAL_CNT; CertPerfDataDefinition.CrlElementTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CRL_ELEMENT_TOTAL_CNT; CertPerfDataDefinition.CtlElementCurrentCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CTL_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CtlElementCurrentCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CTL_ELEMENT_CURRENT_CNT; CertPerfDataDefinition.CtlElementTotalCnt.CounterNameTitleIndex = dwFirstCounter + CERT_CTL_ELEMENT_TOTAL_CNT; CertPerfDataDefinition.CtlElementTotalCnt.CounterHelpTitleIndex = dwFirstHelp + CERT_CTL_ELEMENT_TOTAL_CNT; //--### Add New Counters ###-- fResult = TRUE; CommonReturn: if (hKey) RegCloseKey(hKey); return fResult; ErrorReturn: fResult = FALSE; goto CommonReturn; } STATIC void I_CertPerfGetProcessName( OUT WCHAR wcszProcessName[CERT_PERF_MAX_PROCESS_NAME_LEN] ) { WCHAR wszModule[MAX_PATH + 1]; LPWSTR pwsz; LPWSTR pwszSlash; LPWSTR pwszPeriod; WCHAR wc; DWORD cchProcessName; wszModule[MAX_PATH] = L'\0'; if (0 == GetModuleFileNameW(NULL, wszModule, MAX_PATH)) goto GetModuleFileNameError; // Go from beginning to end and find last backslash and // last period in name pwszPeriod = NULL; pwszSlash = NULL; for (pwsz = wszModule; L'\0' != (wc = *pwsz); pwsz++) { if (L'\\' == wc) pwszSlash = pwsz; else if (L'.' == wc) pwszPeriod = pwsz; } // If present, the process name is between the last \ and the last period. // Otherwise, between beginning and/or end of entire module name if (pwszSlash) pwszSlash++; else pwszSlash = wszModule; if (NULL == pwszPeriod) pwszPeriod = pwsz; if (pwszSlash >= pwszPeriod) goto InvalidModuleName; cchProcessName = (DWORD) (pwszPeriod - pwszSlash); if (cchProcessName > (CERT_PERF_MAX_PROCESS_NAME_LEN - 1)) cchProcessName = CERT_PERF_MAX_PROCESS_NAME_LEN - 1; memcpy(wcszProcessName, pwszSlash, cchProcessName * sizeof(WCHAR)); wcszProcessName[cchProcessName] = L'\0'; CommonReturn: return; ErrorReturn: wcscpy(wcszProcessName, L"???"); goto CommonReturn; TRACE_ERROR(GetModuleFileNameError) TRACE_ERROR(InvalidModuleName) } // The returnd ACL must be freed via PkiFree() STATIC PACL CreateEveryoneAcl( IN DWORD dwAccessMask ) { DWORD dwLastErr = 0; PACL pEveryoneAcl = NULL; PSID psidEveryone = NULL; DWORD dwAclSize; SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; if (!AllocateAndInitializeSid( &siaWorldSidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryone )) goto AllocateAndInitializeSidError; // // compute size of ACL // dwAclSize = sizeof(ACL) + ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetLengthSid(psidEveryone); // // allocate storage for Acl // if (NULL == (pEveryoneAcl = (PACL) PkiNonzeroAlloc(dwAclSize))) goto OutOfMemory; if (!InitializeAcl(pEveryoneAcl, dwAclSize, ACL_REVISION)) goto InitializeAclError; if (!AddAccessAllowedAce( pEveryoneAcl, ACL_REVISION, dwAccessMask, psidEveryone )) goto AddAceError; CommonReturn: if (psidEveryone) FreeSid(psidEveryone); if (dwLastErr) SetLastError(dwLastErr); return pEveryoneAcl; ErrorReturn: dwLastErr = GetLastError(); if (pEveryoneAcl) { PkiFree(pEveryoneAcl); pEveryoneAcl = NULL; } goto CommonReturn; TRACE_ERROR(AllocateAndInitializeSidError) TRACE_ERROR(OutOfMemory) TRACE_ERROR(InitializeAclError) TRACE_ERROR(AddAceError) } STATIC BOOL InitializeSecurityDescriptorAndAttributes( IN PACL pAcl, OUT SECURITY_DESCRIPTOR *psd, OUT SECURITY_ATTRIBUTES *psa ) { BOOL fResult; if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) goto InitializeSecurityDescriptorError; if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE)) goto SetSecurityDescriptorDaclError; psa->nLength = sizeof(SECURITY_ATTRIBUTES); psa->lpSecurityDescriptor = psd; psa->bInheritHandle = FALSE; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult = FALSE; goto CommonReturn; TRACE_ERROR(InitializeSecurityDescriptorError) TRACE_ERROR(SetSecurityDescriptorDaclError) } STATIC HANDLE CreateMutexWithSynchronizeAccess( IN LPWSTR pwszMutexName ) { HANDLE hMutex = NULL; PACL pEveryoneAcl = NULL; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; DWORD i; if (NULL == (pEveryoneAcl = CreateEveryoneAcl(SYNCHRONIZE))) goto CreateEveryoneAclError; if (!InitializeSecurityDescriptorAndAttributes(pEveryoneAcl, &sd, &sa)) goto InitializeSecurityDescriptorAndAttributesError; // Retry a couple of times. There is a small window between the // CreateMutex and OpenMutex where the mutex is deleted. for (i = 0; i < 5; i++) { hMutex = CreateMutexU( &sa, FALSE, // fInitialOwner pwszMutexName ); if (NULL != hMutex) goto CommonReturn; hMutex = OpenMutexU( SYNCHRONIZE, FALSE, // bInheritHandle pwszMutexName ); if (NULL != hMutex) { SetLastError(ERROR_ALREADY_EXISTS); goto CommonReturn; } if (ERROR_FILE_NOT_FOUND != GetLastError()) break; } assert(NULL == hMutex); goto OpenMutexError; CommonReturn: if (pEveryoneAcl) PkiFree(pEveryoneAcl); return hMutex; ErrorReturn: assert(NULL == hMutex); goto CommonReturn; TRACE_ERROR(CreateEveryoneAclError) TRACE_ERROR(InitializeSecurityDescriptorAndAttributesError) TRACE_ERROR(OpenMutexError) } STATIC HANDLE CreateFileMappingWithWriteAccess( IN DWORD dwMaximumSizeLow, IN LPWSTR pwszFileName ) { HANDLE hFile = NULL; PACL pEveryoneAcl = NULL; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; DWORD i; if (NULL == (pEveryoneAcl = CreateEveryoneAcl(FILE_MAP_WRITE))) goto CreateEveryoneAclError; if (!InitializeSecurityDescriptorAndAttributes(pEveryoneAcl, &sd, &sa)) goto InitializeSecurityDescriptorAndAttributesError; // Retry a couple of times. There is a small window between the // CreateFileMapping and OpenFileMapping where the file is closed. for (i = 0; i < 5; i++) { hFile = CreateFileMappingW( INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, // dwMaximumSizeHigh dwMaximumSizeLow, pwszFileName ); if (NULL != hFile) goto CommonReturn; hFile = OpenFileMappingW( FILE_MAP_WRITE, FALSE, // bInheritHandle pwszFileName ); if (NULL != hFile) { SetLastError(ERROR_ALREADY_EXISTS); goto CommonReturn; } if (ERROR_FILE_NOT_FOUND != GetLastError()) break; } assert(NULL == hFile); goto OpenFileError; CommonReturn: if (pEveryoneAcl) PkiFree(pEveryoneAcl); return hFile; ErrorReturn: assert(NULL == hFile); goto CommonReturn; TRACE_ERROR(CreateEveryoneAclError) TRACE_ERROR(InitializeSecurityDescriptorAndAttributesError) TRACE_ERROR(OpenFileError) } STATIC void I_CertPerfGetSharedMemory() { DWORD dwFileMappingStatus; BOOL fReleaseMutex = FALSE; DWORD dwIndex; DWORD dwNextIndex; BOOL fTerminalServerGlobalName; if (!I_CertPerfSetNameAndHelpIndices()) return; // First try with W2K Terminal Server "Global\" prefix if (NULL == (hCertPerfSharedMemoryMutex = CreateMutexWithSynchronizeAccess( CERT_PERF_TS_SHARED_MEMORY_MUTEX_NAME ))) { if (NULL == (hCertPerfSharedMemoryMutex = CreateMutexWithSynchronizeAccess( CERT_PERF_SHARED_MEMORY_MUTEX_NAME ))) goto CreateMutexError; else fTerminalServerGlobalName = FALSE; } else fTerminalServerGlobalName = TRUE; if (WAIT_OBJECT_0 != WaitForSingleObject( hCertPerfSharedMemoryMutex, CERT_PERF_SHARED_MEMORY_MUTEX_TIMEOUT )) goto WaitForMutexError; else fReleaseMutex = TRUE; if (NULL == (hCertPerfSharedMemoryFile = CreateFileMappingWithWriteAccess( sizeof(CERT_PERF_SHARED_MEMORY), fTerminalServerGlobalName ? CERT_PERF_TS_SHARED_MEMORY_FILE_NAME : CERT_PERF_SHARED_MEMORY_FILE_NAME ))) goto CreateFileMappingError; dwFileMappingStatus = GetLastError(); if (NULL == (pCertPerfSharedMemory = (PCERT_PERF_SHARED_MEMORY) MapViewOfFile( hCertPerfSharedMemoryFile, FILE_MAP_WRITE, 0, // dwOffsetHigh 0, // dwOffsetLow sizeof(CERT_PERF_SHARED_MEMORY) ))) goto MapViewOfFileError; if (ERROR_ALREADY_EXISTS != dwFileMappingStatus) { DWORD i; assert(ERROR_SUCCESS == dwFileMappingStatus); // Need to initialize the shared memory memset(pCertPerfSharedMemory, 0, sizeof(CERT_PERF_SHARED_MEMORY)); // Create linked list of process free elements. // // Only need forward indices for the free list for (i = 0; i < CERT_PERF_MAX_PROCESS_CNT; i++) { // An index >= CERT_PERF_MAX_PROCESS_CNT indicates end of list pCertPerfSharedMemory->rgProcessData[i].dwNextIndex = i + 1; } pCertPerfSharedMemory->dwFirstFreeIndex = 0; // An index >= CERT_PERF_MAX_PROCESS_CNT indicates an empty list pCertPerfSharedMemory->dwFirstInUseIndex = CERT_PERF_MAX_PROCESS_CNT; } if (CERT_PERF_MAX_PROCESS_CNT <= (dwIndex = pCertPerfSharedMemory->dwFirstFreeIndex)) goto OutOfSharedMemoryProcessData; pCertPerfProcessData = &pCertPerfSharedMemory->rgProcessData[dwIndex]; // Remove process data element from the free list pCertPerfSharedMemory->dwFirstFreeIndex = pCertPerfProcessData->dwNextIndex; // Add process data element to the in use list dwNextIndex = pCertPerfSharedMemory->dwFirstInUseIndex; if (CERT_PERF_MAX_PROCESS_CNT > dwNextIndex) pCertPerfSharedMemory->rgProcessData[dwNextIndex].dwPrevIndex = dwIndex; pCertPerfProcessData->dwNextIndex = dwNextIndex; pCertPerfProcessData->dwPrevIndex = CERT_PERF_MAX_PROCESS_CNT; pCertPerfSharedMemory->dwFirstInUseIndex = dwIndex; pCertPerfSharedMemory->dwProcessCnt++; pCertPerfProcessData->dwProcessId = GetCurrentProcessId(); I_CertPerfGetProcessName(pCertPerfProcessData->wcszProcessName); memset(&pCertPerfProcessData->Counters, 0, sizeof(pCertPerfProcessData->Counters)); ReleaseMutex(hCertPerfSharedMemoryMutex); pCertPerfProcessCounters = &pCertPerfProcessData->Counters; CommonReturn: return; ErrorReturn: assert(NULL == pCertPerfProcessData); if (pCertPerfSharedMemory) { UnmapViewOfFile(pCertPerfSharedMemory); pCertPerfSharedMemory = NULL; } if (hCertPerfSharedMemoryFile) { CloseHandle(hCertPerfSharedMemoryFile); hCertPerfSharedMemoryFile = NULL; } if (hCertPerfSharedMemoryMutex) { if (fReleaseMutex) ReleaseMutex(hCertPerfSharedMemoryMutex); CloseHandle(hCertPerfSharedMemoryMutex); hCertPerfSharedMemoryMutex = NULL; } goto CommonReturn; TRACE_ERROR(CreateMutexError) TRACE_ERROR(WaitForMutexError) TRACE_ERROR(CreateFileMappingError) TRACE_ERROR(MapViewOfFileError) TRACE_ERROR(OutOfSharedMemoryProcessData) } STATIC void I_CertPerfFreeSharedMemory() { if (NULL == pCertPerfProcessData) return; pCertPerfProcessData->dwProcessId = 0; if (WAIT_OBJECT_0 == WaitForSingleObject( hCertPerfSharedMemoryMutex, CERT_PERF_SHARED_MEMORY_MUTEX_TIMEOUT )) { DWORD dwIndex; DWORD dwPrevIndex; DWORD dwNextIndex; // Remove process data element from the in use list dwIndex = (DWORD)(pCertPerfProcessData - pCertPerfSharedMemory->rgProcessData); assert(CERT_PERF_MAX_PROCESS_CNT > dwIndex); dwPrevIndex = pCertPerfProcessData->dwPrevIndex; dwNextIndex = pCertPerfProcessData->dwNextIndex; if (CERT_PERF_MAX_PROCESS_CNT > dwNextIndex) pCertPerfSharedMemory->rgProcessData[dwNextIndex].dwPrevIndex = dwPrevIndex; if (CERT_PERF_MAX_PROCESS_CNT > dwPrevIndex) pCertPerfSharedMemory->rgProcessData[dwPrevIndex].dwNextIndex = dwNextIndex; else pCertPerfSharedMemory->dwFirstInUseIndex = dwNextIndex; if (pCertPerfSharedMemory->dwProcessCnt) pCertPerfSharedMemory->dwProcessCnt--; // Add to the free list pCertPerfProcessData->dwNextIndex = pCertPerfSharedMemory->dwFirstFreeIndex; pCertPerfSharedMemory->dwFirstFreeIndex = dwIndex; ReleaseMutex(hCertPerfSharedMemoryMutex); } assert(pCertPerfSharedMemory); UnmapViewOfFile(pCertPerfSharedMemory); pCertPerfSharedMemory = NULL; assert(hCertPerfSharedMemoryFile); CloseHandle(hCertPerfSharedMemoryFile); hCertPerfSharedMemoryFile = NULL; assert(hCertPerfSharedMemoryMutex); CloseHandle(hCertPerfSharedMemoryMutex); hCertPerfSharedMemoryMutex = NULL; pCertPerfProcessCounters = NULL; pCertPerfProcessData = NULL; } BOOL WINAPI CertPerfDllMain( HMODULE hInst, ULONG ulReason, LPVOID lpReserved ) { BOOL fRet = TRUE; switch (ulReason) { case DLL_PROCESS_ATTACH: fRet = Pki_InitializeCriticalSection(&CertPerfProcessCriticalSection); if (fRet) I_CertPerfGetSharedMemory(); break; case DLL_PROCESS_DETACH: I_CertPerfFreeSharedMemory(); DeleteCriticalSection(&CertPerfProcessCriticalSection); break; case DLL_THREAD_DETACH: default: break; } return fRet; } // // Function Prototypes // // these are used to insure that the data collection functions // accessed by Perflib will have the correct calling format. // PM_OPEN_PROC OpenCertPerformanceData; PM_COLLECT_PROC CollectCertPerformanceData; PM_CLOSE_PROC CloseCertPerformanceData; DWORD APIENTRY OpenCertPerformanceData( IN LPWSTR lpDeviceNames ) { if (NULL == pCertPerfProcessData) return ERROR_FILE_NOT_FOUND; return ERROR_SUCCESS; } #define QUERY_GLOBAL 1 #define QUERY_ITEMS 2 #define QUERY_FOREIGN 3 #define QUERY_COSTLY 4 #define GLOBAL_STRING L"Global" #define FOREIGN_STRING L"Foreign" #define COSTLY_STRING L"Costly" // test for delimiter, end of line and non-digit characters // used by I_CertPerfIsNumberInUnicodeList routine // #define DIGIT 1 #define DELIMITER 2 #define INVALID 3 #define EvalThisChar(c,d) ( \ (c == d) ? DELIMITER : \ (c == 0) ? DELIMITER : \ (c < (WCHAR)'0') ? INVALID : \ (c > (WCHAR)'9') ? INVALID : \ DIGIT) DWORD I_CertPerfGetQueryType( IN LPWSTR pwszValue ) /*++ returns the type of query described in the lpValue string so that the appropriate processing method may be used Arguments IN pwszValue string passed to PerfRegQuery Value for processing Return Value QUERY_GLOBAL if pwszValue == 0 (null pointer) pwszValue == pointer to Null string pwszValue == pointer to "Global" string QUERY_FOREIGN if pwszValue == pointer to "Foreign" string QUERY_COSTLY if pwszValue == pointer to "Costly" string otherwise: QUERY_ITEMS --*/ { DWORD dwQueryType; if (NULL == pwszValue || L'\0' == *pwszValue || 0 == _wcsnicmp(pwszValue, GLOBAL_STRING, wcslen(GLOBAL_STRING))) dwQueryType = QUERY_GLOBAL; else if (0 == _wcsnicmp(pwszValue, COSTLY_STRING, wcslen(COSTLY_STRING))) dwQueryType = QUERY_COSTLY; else if (0 == _wcsnicmp(pwszValue, FOREIGN_STRING, wcslen(FOREIGN_STRING))) dwQueryType = QUERY_FOREIGN; else dwQueryType = QUERY_ITEMS; return dwQueryType; } BOOL I_CertPerfIsNumberInUnicodeList ( IN DWORD dwNumber, IN LPWSTR lpwszUnicodeList ) /*++ Arguments: IN dwNumber DWORD number to find in list IN lpwszUnicodeList Null terminated, Space delimited list of decimal numbers Return Value: TRUE: dwNumber was found in the list of unicode number strings FALSE: dwNumber was not found in the list. --*/ { DWORD dwThisNumber; WCHAR *pwcThisChar; BOOL bValidNumber; BOOL bNewItem; WCHAR wcDelimiter; // could be an argument to be more flexible if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not found pwcThisChar = lpwszUnicodeList; dwThisNumber = 0; wcDelimiter = (WCHAR)' '; bValidNumber = FALSE; bNewItem = TRUE; while (TRUE) { switch (EvalThisChar (*pwcThisChar, wcDelimiter)) { case DIGIT: // if this is the first digit after a delimiter, then // set flags to start computing the new number if (bNewItem) { bNewItem = FALSE; bValidNumber = TRUE; } if (bValidNumber) { dwThisNumber *= 10; dwThisNumber += (*pwcThisChar - (WCHAR)'0'); } break; case DELIMITER: // a delimter is either the delimiter character or the // end of the string ('\0') if when the delimiter has been // reached a valid number was found, then compare it to the // number from the argument list. if this is the end of the // string and no match was found, then return. // if (bValidNumber) { if (dwThisNumber == dwNumber) return TRUE; bValidNumber = FALSE; } if (*pwcThisChar == 0) { return FALSE; } else { bNewItem = TRUE; dwThisNumber = 0; } break; case INVALID: // if an invalid character was encountered, ignore all // characters up to the next delimiter and then start fresh. // the invalid number is not compared. bValidNumber = FALSE; break; default: break; } pwcThisChar++; } return FALSE; } DWORD APIENTRY CollectCertPerformanceData( IN LPWSTR pwszValueName, IN OUT LPVOID *ppvData, IN OUT LPDWORD pcbTotalBytes, IN OUT LPDWORD pNumObjectTypes ) { DWORD dwErr = ERROR_SUCCESS; BOOL fReleaseMutex = FALSE; PCERT_PERF_DATA_DEFINITION pDataDef; PERF_INSTANCE_DEFINITION *pInstanceDef; DWORD cbNeededBytes; DWORD dwProcessCnt; DWORD dwInUseIndex; LONG NumInstances; DWORD dwQueryType; if (NULL == pCertPerfProcessData) goto NoProcessDataError; dwQueryType = I_CertPerfGetQueryType(pwszValueName); if (QUERY_FOREIGN == dwQueryType) goto ForeignQueryNotSupported; if (QUERY_ITEMS == dwQueryType) { if (!(I_CertPerfIsNumberInUnicodeList( CertPerfDataDefinition.ObjectType.ObjectNameTitleIndex, pwszValueName))) goto ObjectTypeQueryNotSupported; } if (WAIT_OBJECT_0 != WaitForSingleObject( hCertPerfSharedMemoryMutex, CERT_PERF_SHARED_MEMORY_MUTEX_TIMEOUT )) goto WaitForMutexError; else fReleaseMutex = TRUE; pDataDef = (PCERT_PERF_DATA_DEFINITION) *ppvData; // always return an "instance sized" buffer after the definition blocks // to prevent perfmon from reading bogus data. This is strictly a hack // to accomodate how PERFMON handles the "0" instance case. // By doing this, perfmon won't choke when there are no instances // and the counter object & counters will be displayed in the // list boxes, even though no instances will be listed. dwProcessCnt = pCertPerfSharedMemory->dwProcessCnt; if (CERT_PERF_MAX_PROCESS_CNT < dwProcessCnt) goto InvalidProcessData; cbNeededBytes = sizeof(CERT_PERF_DATA_DEFINITION) + (dwProcessCnt > 0 ? dwProcessCnt : 1 ) * ( sizeof(PERF_INSTANCE_DEFINITION) + CERT_PERF_MAX_PROCESS_NAME_LEN + sizeof(CERT_PERF_COUNTERS)); if (*pcbTotalBytes < cbNeededBytes) { dwErr = ERROR_MORE_DATA; goto MoreDataError; } // copy the object & counter definition information memcpy(pDataDef, &CertPerfDataDefinition, sizeof(CERT_PERF_DATA_DEFINITION)); // Update the instance data for each InUse process. pInstanceDef = (PERF_INSTANCE_DEFINITION *) &pDataDef[1]; dwInUseIndex = pCertPerfSharedMemory->dwFirstInUseIndex; NumInstances = 0; while (NumInstances < (LONG) dwProcessCnt && CERT_PERF_MAX_PROCESS_CNT > dwInUseIndex) { PCERT_PERF_PROCESS_DATA pInUseData; PCERT_PERF_COUNTERS pCtr; DWORD cchProcessName; DWORD NameLength; DWORD ByteLength; pInUseData = &pCertPerfSharedMemory->rgProcessData[dwInUseIndex]; dwInUseIndex = pInUseData->dwNextIndex; if (0 == pInUseData->dwProcessId) continue; // The following is updated for each InUse process: // - PERF_INSTANCE_DEFINITION // - wcszProcessName // - optional padding for DWORD alignment // - CERT_PERF_COUNTERS // Get process name and instance definition byte lengths for (cchProcessName = 0; cchProcessName < CERT_PERF_MAX_PROCESS_NAME_LEN && L'\0' != pInUseData->wcszProcessName[cchProcessName]; cchProcessName++) ; if (CERT_PERF_MAX_PROCESS_NAME_LEN <= cchProcessName) goto InvalidProcessData; // Include trailing null in name length NameLength = cchProcessName * sizeof(WCHAR) + sizeof(WCHAR); ByteLength = sizeof(PERF_INSTANCE_DEFINITION) + DWORD_MULTIPLE(NameLength); // Update the instance definition fields pInstanceDef->ByteLength = ByteLength; pInstanceDef->ParentObjectTitleIndex = 0; // no parent pInstanceDef->ParentObjectInstance = 0; // " " pInstanceDef->UniqueID = PERF_NO_UNIQUE_ID; pInstanceDef->NameOffset = sizeof(PERF_INSTANCE_DEFINITION); pInstanceDef->NameLength = NameLength; // Update the process name that immediately follows the // instance definition memcpy(&pInstanceDef[1], pInUseData->wcszProcessName, NameLength); // Update the performance counters immediately following the // above process name. Note, start of counters is DWORD aligned pCtr = (PCERT_PERF_COUNTERS) (((PBYTE) pInstanceDef) + ByteLength); pCtr->CounterBlock.ByteLength = sizeof(CERT_PERF_COUNTERS); pCtr->dwChainCnt = (DWORD) pInUseData->Counters.lChainCnt; pCtr->dwChainElementCnt = (DWORD) pInUseData->Counters.lChainElementCnt; pCtr->dwChainEngineCurrentCnt = (DWORD) pInUseData->Counters.lChainEngineCurrentCnt; pCtr->dwChainEngineTotalCnt = (DWORD) pInUseData->Counters.lChainEngineTotalCnt; pCtr->dwChainEngineResyncCnt = (DWORD) pInUseData->Counters.lChainEngineResyncCnt; pCtr->dwChainCertCacheCnt = (DWORD) pInUseData->Counters.lChainCertCacheCnt; pCtr->dwChainCtlCacheCnt = (DWORD) pInUseData->Counters.lChainCtlCacheCnt; pCtr->dwChainEndCertInCacheCnt = (DWORD) pInUseData->Counters.lChainEndCertInCacheCnt; pCtr->dwChainCacheEndCertCnt = (DWORD) pInUseData->Counters.lChainCacheEndCertCnt; pCtr->dwChainRevocationCnt = (DWORD) pInUseData->Counters.lChainRevocationCnt; pCtr->dwChainRevokedCnt = (DWORD) pInUseData->Counters.lChainRevokedCnt; pCtr->dwChainRevocationOfflineCnt = (DWORD) pInUseData->Counters.lChainRevocationOfflineCnt; pCtr->dwChainNoRevocationCheckCnt = (DWORD) pInUseData->Counters.lChainNoRevocationCheckCnt; pCtr->dwChainVerifyCertSignatureCnt = (DWORD) pInUseData->Counters.lChainVerifyCertSignatureCnt; pCtr->dwChainCompareIssuerPublicKeyCnt = (DWORD) pInUseData->Counters.lChainCompareIssuerPublicKeyCnt; pCtr->dwChainVerifyCtlSignatureCnt = (DWORD) pInUseData->Counters.lChainVerifyCtlSignatureCnt; pCtr->dwChainBeenVerifiedCtlSignatureCnt = (DWORD) pInUseData->Counters.lChainBeenVerifiedCtlSignatureCnt; pCtr->dwChainUrlIssuerCnt = (DWORD) pInUseData->Counters.lChainUrlIssuerCnt; pCtr->dwChainCacheOnlyUrlIssuerCnt = (DWORD) pInUseData->Counters.lChainCacheOnlyUrlIssuerCnt; pCtr->dwChainRequestedEngineResyncCnt = (DWORD) pInUseData->Counters.lChainRequestedEngineResyncCnt; pCtr->dwChangeNotifyCnt = (DWORD) pInUseData->Counters.lChangeNotifyCnt; pCtr->dwChangeNotifyLmGpCnt = (DWORD) pInUseData->Counters.lChangeNotifyLmGpCnt; pCtr->dwChangeNotifyCuGpCnt = (DWORD) pInUseData->Counters.lChangeNotifyCuGpCnt; pCtr->dwChangeNotifyCuMyCnt = (DWORD) pInUseData->Counters.lChangeNotifyCuMyCnt; pCtr->dwChangeNotifyRegCnt = (DWORD) pInUseData->Counters.lChangeNotifyRegCnt; pCtr->dwStoreCurrentCnt = (DWORD) pInUseData->Counters.lStoreCurrentCnt; pCtr->dwStoreTotalCnt = (DWORD) pInUseData->Counters.lStoreTotalCnt; pCtr->dwStoreRegCurrentCnt = (DWORD) pInUseData->Counters.lStoreRegCurrentCnt; pCtr->dwStoreRegTotalCnt = (DWORD) pInUseData->Counters.lStoreRegTotalCnt; pCtr->dwRegElementReadCnt = (DWORD) pInUseData->Counters.lRegElementReadCnt; pCtr->dwRegElementWriteCnt = (DWORD) pInUseData->Counters.lRegElementWriteCnt; pCtr->dwRegElementDeleteCnt = (DWORD) pInUseData->Counters.lRegElementDeleteCnt; pCtr->dwCertElementCurrentCnt = (DWORD) pInUseData->Counters.lCertElementCurrentCnt; pCtr->dwCertElementTotalCnt = (DWORD) pInUseData->Counters.lCertElementTotalCnt; pCtr->dwCrlElementCurrentCnt = (DWORD) pInUseData->Counters.lCrlElementCurrentCnt; pCtr->dwCrlElementTotalCnt = (DWORD) pInUseData->Counters.lCrlElementTotalCnt; pCtr->dwCtlElementCurrentCnt = (DWORD) pInUseData->Counters.lCtlElementCurrentCnt; pCtr->dwCtlElementTotalCnt = (DWORD) pInUseData->Counters.lCtlElementTotalCnt; //--### Add New Counters ###-- NumInstances++; // setup for the next instance // Next instance starts immediately after the counters pInstanceDef = (PERF_INSTANCE_DEFINITION *) &pCtr[1]; } if (0 == NumInstances) { // zero fill one instance sized block of data if there are no // data instances memset(pInstanceDef, 0, sizeof(PERF_INSTANCE_DEFINITION) + CERT_PERF_MAX_PROCESS_NAME_LEN + sizeof(CERT_PERF_COUNTERS)); // Advance past the zero'ed instance pInstanceDef = (PERF_INSTANCE_DEFINITION *) ((PBYTE) pInstanceDef + sizeof(PERF_INSTANCE_DEFINITION) + CERT_PERF_MAX_PROCESS_NAME_LEN + sizeof(CERT_PERF_COUNTERS)); } // update arguments for return *ppvData = (LPVOID) pInstanceDef; *pNumObjectTypes = 1; pDataDef->ObjectType.NumInstances = NumInstances; pDataDef->ObjectType.TotalByteLength = *pcbTotalBytes = (DWORD)((PBYTE) pInstanceDef - (PBYTE) pDataDef); assert(*pcbTotalBytes <= cbNeededBytes); CommonReturn: if (fReleaseMutex) ReleaseMutex(hCertPerfSharedMemoryMutex); return dwErr; ErrorReturn: *pcbTotalBytes = 0; *pNumObjectTypes = 0; goto CommonReturn; TRACE_ERROR(NoProcessDataError) TRACE_ERROR(ForeignQueryNotSupported) TRACE_ERROR(ObjectTypeQueryNotSupported) TRACE_ERROR(WaitForMutexError) TRACE_ERROR(InvalidProcessData) TRACE_ERROR(MoreDataError) } DWORD APIENTRY CloseCertPerformanceData() { return ERROR_SUCCESS; } #if 0 // Example of timing the CertGetCertificateChain API typedef struct _CERT_PERF_CHAIN_DATA { union { SYSTEMTIME stBefore; LARGE_INTEGER liBefore; }; } CERT_PERF_CHAIN_DATA, *PCERT_PERF_CHAIN_DATA; void WINAPI CertPerfGetCertificateChainBefore( OUT PCERT_PERF_CHAIN_DATA pData ) { if (pCertPerfProcessData) { if (fCertPerfHighFreq) QueryPerformanceCounter(&pData->liBefore); else GetSystemTime(&pData->stBefore); } } void WINAPI CertPerfGetCertificateChainAfter( IN PCERT_PERF_CHAIN_DATA pData, IN PCCERT_CHAIN_CONTEXT pChainContext ) { if (pCertPerfProcessData) { if (fCertPerfHighFreq) { LARGE_INTEGER liAfter; _int64 i64DeltaTime; QueryPerformanceCounter(&liAfter); i64DeltaTime = liAfter.QuadPart - pData->liBefore.QuadPart; EnterCriticalSection(&CertPerfProcessCriticalSection); pCertPerfProcessData->Counters.dwChainCnt++; pCertPerfProcessData->Counters.i64TotalChainTime = pCertPerfProcessData->Counters.i64TotalChainTime + i64DeltaTime; if (0 == pCertPerfProcessData->Counters.i64MinChainTime || i64DeltaTime < pCertPerfProcessData->Counters.i64MinChainTime) pCertPerfProcessData->Counters.i64MinChainTime = i64DeltaTime; if (i64DeltaTime > pCertPerfProcessData->Counters.i64MaxChainTime) pCertPerfProcessData->Counters.i64MaxChainTime = i64DeltaTime; LeaveCriticalSection(&CertPerfProcessCriticalSection); } else { SYSTEMTIME stAfter; FILETIME ftBefore; FILETIME ftAfter; _int64 i64DeltaTime; GetSystemTime(&stAfter); SystemTimeToFileTime(&pData->stBefore, &ftBefore); SystemTimeToFileTime(&stAfter, &ftAfter); i64DeltaTime = *((_int64 *) &ftAfter) - *((_int64 *) &ftBefore); EnterCriticalSection(&CertPerfProcessCriticalSection); pCertPerfProcessData->Counters.dwChainCnt++; pCertPerfProcessData->Counters.i64TotalChainTime = pCertPerfProcessData->Counters.i64TotalChainTime + i64DeltaTime; if (0 == pCertPerfProcessData->Counters.i64MinChainTime || i64DeltaTime < pCertPerfProcessData->Counters.i64MinChainTime) pCertPerfProcessData->Counters.i64MinChainTime = i64DeltaTime; if (i64DeltaTime > pCertPerfProcessData->Counters.i64MaxChainTime) pCertPerfProcessData->Counters.i64MaxChainTime = i64DeltaTime; LeaveCriticalSection(&CertPerfProcessCriticalSection); } } } #endif