1 /* 2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "pdh_interface.hpp" 27 #include "runtime/os.hpp" 28 #include "utilities/macros.hpp" 29 30 // PDH API 31 typedef PDH_STATUS (WINAPI *PdhAddCounter_Fn)(HQUERY, LPCSTR, DWORD, HCOUNTER*); 32 typedef PDH_STATUS (WINAPI *PdhOpenQuery_Fn)(LPCWSTR, DWORD, HQUERY*); 33 typedef DWORD (WINAPI *PdhCloseQuery_Fn)(HQUERY); 34 typedef PDH_STATUS (WINAPI *PdhCollectQueryData_Fn)(HQUERY); 35 typedef DWORD (WINAPI *PdhGetFormattedCounterValue_Fn)(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE); 36 typedef PDH_STATUS (WINAPI *PdhEnumObjectItems_Fn)(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, LPDWORD, LPTSTR, LPDWORD, DWORD, DWORD); 37 typedef PDH_STATUS (WINAPI *PdhRemoveCounter_Fn)(HCOUNTER); 38 typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndex_Fn)(LPCSTR, DWORD, LPSTR, LPDWORD); 39 typedef PDH_STATUS (WINAPI *PdhMakeCounterPath_Fn)(PDH_COUNTER_PATH_ELEMENTS*, LPTSTR, LPDWORD, DWORD); 40 41 PdhAddCounter_Fn PdhDll::_PdhAddCounter = NULL; 42 PdhOpenQuery_Fn PdhDll::_PdhOpenQuery = NULL; 43 PdhCloseQuery_Fn PdhDll::_PdhCloseQuery = NULL; 44 PdhCollectQueryData_Fn PdhDll::_PdhCollectQueryData = NULL; 45 PdhGetFormattedCounterValue_Fn PdhDll::_PdhGetFormattedCounterValue = NULL; 46 PdhEnumObjectItems_Fn PdhDll::_PdhEnumObjectItems = NULL; 47 PdhRemoveCounter_Fn PdhDll::_PdhRemoveCounter = NULL; 48 PdhLookupPerfNameByIndex_Fn PdhDll::_PdhLookupPerfNameByIndex = NULL; 49 PdhMakeCounterPath_Fn PdhDll::_PdhMakeCounterPath = NULL; 50 51 LONG PdhDll::_critical_section = 0; 52 LONG PdhDll::_initialized = 0; 53 LONG PdhDll::_pdh_reference_count = 0; 54 HMODULE PdhDll::_hModule = NULL; 55 56 void PdhDll::initialize(void) { 57 _hModule = os::win32::load_Windows_dll("pdh.dll", NULL, 0); 58 if (NULL == _hModule) { 59 return; 60 } 61 // The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods 62 _PdhAddCounter = (PdhAddCounter_Fn)::GetProcAddress(_hModule, "PdhAddCounterA"); 63 _PdhOpenQuery = (PdhOpenQuery_Fn)::GetProcAddress(_hModule, "PdhOpenQueryA"); 64 _PdhCloseQuery = (PdhCloseQuery_Fn)::GetProcAddress(_hModule, "PdhCloseQuery"); 65 _PdhCollectQueryData = (PdhCollectQueryData_Fn)::GetProcAddress(_hModule, "PdhCollectQueryData"); 66 _PdhGetFormattedCounterValue = (PdhGetFormattedCounterValue_Fn)::GetProcAddress(_hModule, "PdhGetFormattedCounterValue"); 67 _PdhEnumObjectItems = (PdhEnumObjectItems_Fn)::GetProcAddress(_hModule, "PdhEnumObjectItemsA"); 68 _PdhRemoveCounter = (PdhRemoveCounter_Fn)::GetProcAddress(_hModule, "PdhRemoveCounter"); 69 _PdhLookupPerfNameByIndex = (PdhLookupPerfNameByIndex_Fn)::GetProcAddress(_hModule, "PdhLookupPerfNameByIndexA"); 70 _PdhMakeCounterPath = (PdhMakeCounterPath_Fn)::GetProcAddress(_hModule, "PdhMakeCounterPathA"); 71 InterlockedExchange(&_initialized, 1); 72 } 73 74 bool PdhDll::PdhDetach(void) { 75 LONG prev_ref_count = InterlockedExchangeAdd(&_pdh_reference_count, -1); 76 BOOL ret = false; 77 if (1 == prev_ref_count) { 78 if (_initialized && _hModule != NULL) { 79 ret = FreeLibrary(_hModule); 80 if (ret) { 81 _hModule = NULL; 82 _PdhAddCounter = NULL; 83 _PdhOpenQuery = NULL; 84 _PdhCloseQuery = NULL; 85 _PdhCollectQueryData = NULL; 86 _PdhGetFormattedCounterValue = NULL; 87 _PdhEnumObjectItems = NULL; 88 _PdhRemoveCounter = NULL; 89 _PdhLookupPerfNameByIndex = NULL; 90 _PdhMakeCounterPath = NULL; 91 InterlockedExchange(&_initialized, 0); 92 } 93 } 94 } 95 return ret != 0; 96 } 97 98 bool PdhDll::PdhAttach(void) { 99 InterlockedExchangeAdd(&_pdh_reference_count, 1); 100 if (1 == _initialized) { 101 return true; 102 } 103 while (InterlockedCompareExchange(&_critical_section, 1, 0) == 1); 104 if (0 == _initialized) { 105 initialize(); 106 } 107 while (InterlockedCompareExchange(&_critical_section, 0, 1) == 0); 108 return (_PdhAddCounter != NULL && _PdhOpenQuery != NULL 109 && _PdhCloseQuery != NULL && PdhCollectQueryData != NULL 110 && _PdhGetFormattedCounterValue != NULL && _PdhEnumObjectItems != NULL 111 && _PdhRemoveCounter != NULL && PdhLookupPerfNameByIndex != NULL 112 && _PdhMakeCounterPath != NULL); 113 } 114 115 PDH_STATUS PdhDll::PdhAddCounter(HQUERY hQuery, LPCSTR szFullCounterPath, DWORD dwUserData, HCOUNTER* phCounter) { 116 assert(_initialized && _PdhAddCounter != NULL, "PdhAvailable() not yet called"); 117 return _PdhAddCounter(hQuery, szFullCounterPath, dwUserData, phCounter); 118 } 119 120 PDH_STATUS PdhDll::PdhOpenQuery(LPCWSTR szDataSource, DWORD dwUserData, HQUERY* phQuery) { 121 assert(_initialized && _PdhOpenQuery != NULL, "PdhAvailable() not yet called"); 122 return _PdhOpenQuery(szDataSource, dwUserData, phQuery); 123 } 124 125 DWORD PdhDll::PdhCloseQuery(HQUERY hQuery) { 126 assert(_initialized && _PdhCloseQuery != NULL, "PdhAvailable() not yet called"); 127 return _PdhCloseQuery(hQuery); 128 } 129 130 PDH_STATUS PdhDll::PdhCollectQueryData(HQUERY hQuery) { 131 assert(_initialized && _PdhCollectQueryData != NULL, "PdhAvailable() not yet called"); 132 return _PdhCollectQueryData(hQuery); 133 } 134 135 DWORD PdhDll::PdhGetFormattedCounterValue(HCOUNTER hCounter, DWORD dwFormat, LPDWORD lpdwType, PPDH_FMT_COUNTERVALUE pValue) { 136 assert(_initialized && _PdhGetFormattedCounterValue != NULL, "PdhAvailable() not yet called"); 137 return _PdhGetFormattedCounterValue(hCounter, dwFormat, lpdwType, pValue); 138 } 139 140 PDH_STATUS PdhDll::PdhEnumObjectItems(LPCTSTR szDataSource, LPCTSTR szMachineName, LPCTSTR szObjectName, 141 LPTSTR mszCounterList, LPDWORD pcchCounterListLength, LPTSTR mszInstanceList, 142 LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags) { 143 assert(_initialized && _PdhEnumObjectItems != NULL, "PdhAvailable() not yet called"); 144 return _PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList, pcchCounterListLength, 145 mszInstanceList, pcchInstanceListLength, dwDetailLevel, dwFlags); 146 } 147 148 PDH_STATUS PdhDll::PdhRemoveCounter(HCOUNTER hCounter) { 149 assert(_initialized && _PdhRemoveCounter != NULL, "PdhAvailable() not yet called"); 150 return _PdhRemoveCounter(hCounter); 151 } 152 153 PDH_STATUS PdhDll::PdhLookupPerfNameByIndex(LPCSTR szMachineName, DWORD dwNameIndex, LPSTR szNameBuffer, LPDWORD pcchNameBufferSize) { 154 assert(_initialized && _PdhLookupPerfNameByIndex != NULL, "PdhAvailable() not yet called"); 155 return _PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, szNameBuffer, pcchNameBufferSize); 156 } 157 158 PDH_STATUS PdhDll::PdhMakeCounterPath(PDH_COUNTER_PATH_ELEMENTS* pCounterPathElements, LPTSTR szFullPathBuffer, LPDWORD pcchBufferSize, DWORD dwFlags) { 159 assert(_initialized && _PdhMakeCounterPath != NULL, "PdhAvailable() not yet called"); 160 return _PdhMakeCounterPath(pCounterPathElements, szFullPathBuffer, pcchBufferSize, dwFlags); 161 } 162 163 bool PdhDll::PdhStatusFail(PDH_STATUS pdhStat) { 164 return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA; 165 }