123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- #include "pch.h"
- CPerfShare::CPerfShare()
- {
- mhSharedMemory = NULL;
- mhSharedMutex = NULL;
- mpShareHeader = NULL;
- mpShareInstance = NULL;
- mlLockCount = 0;
- }
- CPerfShare::~CPerfShare()
- {
- this->Terminate();
- }
- BOOL CPerfShare::Lock()
- {
- BOOL fResult;
- LONG lTemp;
- fResult = FALSE;
- if (TRUE == this->Initialized())
- {
- lTemp = InterlockedIncrement(&mlLockCount);
- if (lTemp > 1)
- fResult = TRUE;
- else if (WAIT_FAILED != WaitForSingleObject(mhSharedMutex,
- SHARE_MUTEX_TIMEOUT))
- {
- fResult = TRUE;
- }
- }
-
- return(fResult);
- }
- VOID CPerfShare::Unlock()
- {
- LONG lTemp;
- if (TRUE == this->Initialized())
- {
- lTemp = InterlockedDecrement(&mlLockCount);
- if (0 == lTemp)
- ReleaseMutex(mhSharedMutex);
- }
- }
- BOOL CPerfShare::InitializeHeader()
- {
- PSHARE_INSTANCE pInstance;
- DWORD dwIndex;
- //
- // Map the file.
- //
- mpShareHeader = (PSHARE_HEADER) MapViewOfFile(
- mhSharedMemory, // Memory Handle
- FILE_MAP_WRITE, // Permissions
- 0, // Start Offset Hi
- 0, // Start Offset Low
- 0); // Map all of it
- if (NULL == mpShareHeader)
- return(FALSE);
- //
- // Initialize the queue.
- //
- mpShareHeader->dwNumberOfInstances = 0;
- mpShareHeader->dwInstanceHeader = DWORD_NULL;
- mpShareHeader->dwFreeHeader = 0;
- pInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
- for(dwIndex = 0; dwIndex < MAX_INSTANCES_OF_ALL_SHARES - 1; dwIndex++)
- {
- pInstance->dwNextInList = dwIndex + 1;
- pInstance++;
- }
- pInstance->dwNextInList = DWORD_NULL;
- return(TRUE);
- }
- BOOL CPerfShare::Initialize(BOOL bReadOnly)
- {
- LONG lError;
- if (TRUE == this->Initialized())
- return(FALSE);
- // Create a NULL dacl to give "everyone" access
- SECURITY_DESCRIPTOR sd;
- SECURITY_ATTRIBUTES sa = {sizeof(sa), &sd, false};
- InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
- SetSecurityDescriptorDacl(&sd, true, NULL, FALSE);
- //
- // Create/access the shared memory queue.
- //
- mhSharedMemory = CreateFileMapping((HANDLE) 0xFFFFFFFF, // OS paging file
- &sa, // Security
- PAGE_READWRITE, // Permissions
- 0, // Max Size High
- SHARE_SIZE, // Max Size Low
- SHARE_FILE_NAME); // Name of File
- lError = GetLastError();
- if (NULL == mhSharedMemory)
- return(FALSE);
- //
- // Create/access the shared mutex for syncronization.
- //
- mhSharedMutex = CreateMutex(&sa, // Security
- FALSE, // Initial Owner
- SHARE_MUTEX_NAME); // Name of Mutex
- if (NULL == mhSharedMutex)
- return(FALSE);
- //
- // See if we need to initialize the global structure.
- //
- if (ERROR_ALREADY_EXISTS != lError)
- {
- if (FALSE == this->InitializeHeader())
- return(FALSE);
- } else
- {
- //
- // Map the file.
- //
- mpShareHeader = (PSHARE_HEADER) MapViewOfFile(
- mhSharedMemory, // Memory Handl
- bReadOnly ? // Permissions
- FILE_MAP_READ :
- FILE_MAP_WRITE,
- 0, // Start Offset Hi
- 0, // Start Offset Low
- 0); // Map all of it
- if (NULL == mpShareHeader)
- return(FALSE);
- }
- return(TRUE);
- }
- VOID CPerfShare::Terminate()
- {
- SHARE_INSTANCE * pTempInstance;
- while(NULL != mpShareInstance)
- {
- pTempInstance = mpShareInstance;
- mpShareInstance = mpShareInstance->pNextUsedByClient;
- this->FreeCounters(pTempInstance->Data);
- }
- if (mpShareHeader != NULL)
- {
- UnmapViewOfFile(mpShareHeader);
- mpShareHeader = NULL;
- }
- if (mhSharedMutex != NULL)
- {
- CloseHandle(mhSharedMutex);
- mhSharedMutex = NULL;
- }
- if (mhSharedMemory != NULL)
- {
- CloseHandle(mhSharedMemory);
- mhSharedMemory = NULL;
- }
- }
- BOOL CPerfShare::GetFirstCounterValue(PCHAR szServiceName, PDWORD pdwFirst)
- {
- HKEY hRegKey;
- DWORD dwSize, dwType;
- LONG lStatus;
- lStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE, // Hive
- szServiceName, // Subkey
- 0L, // Reserved
- KEY_READ, // Access Rights
- &hRegKey); // Hkey
- if (ERROR_SUCCESS != lStatus)
- return(FALSE);
- if (pdwFirst)
- {
- dwSize = sizeof(DWORD);
- lStatus = RegQueryValueExA(hRegKey, // SubKey
- FIRST_COUNTERA, // Value name
- 0L, // Reserved
- &dwType, // Value Type
- (LPBYTE) pdwFirst, // Destination
- &dwSize); // Size of buffer
- if ((ERROR_SUCCESS != lStatus) || (REG_DWORD != dwType))
- {
- RegCloseKey(hRegKey);
- return(FALSE);
- }
- }
- RegCloseKey(hRegKey);
- return(TRUE);
- }
- BOOL CPerfShare::GetFirstCounterValue(PWCHAR wszServiceName, PDWORD pdwFirst)
- {
- HKEY hRegKey;
- DWORD dwSize, dwType;
- LONG lStatus;
- lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // Hive
- wszServiceName, // Subkey
- 0L, // Reserved
- KEY_READ, // Access Rights
- &hRegKey); // Hkey
- if (ERROR_SUCCESS != lStatus)
- return(FALSE);
- if (pdwFirst)
- {
- dwSize = sizeof(DWORD);
- lStatus = RegQueryValueExW(hRegKey, // SubKey
- FIRST_COUNTERW, // Value name
- 0L, // Reserved
- &dwType, // Value Type
- (LPBYTE) pdwFirst, // Destination
- &dwSize); // Size of buffer
- if ((ERROR_SUCCESS != lStatus) || (REG_DWORD != dwType))
- {
- RegCloseKey(hRegKey);
- return(FALSE);
- }
- }
- RegCloseKey(hRegKey);
- return(TRUE);
- }
- BOOL CPerfShare::GetFirstCounterValueA(PCHAR szServiceName, PDWORD pdwFirst)
- {
- CHAR szSubKey[2048];
- sprintf(szSubKey, "System\\CurrentControlSet\\Services\\%s\\Performance",
- szServiceName);
- return(GetFirstCounterValue(szSubKey, pdwFirst));
- }
- BOOL CPerfShare::GetFirstCounterValueW(PWCHAR wszServiceName, PDWORD pdwFirst)
- {
- WCHAR wszSubKey[2048];
- swprintf(wszSubKey, L"System\\CurrentControlSet\\Services\\%s\\Performance",
- wszServiceName);
- return(GetFirstCounterValue(wszSubKey, pdwFirst));
- }
- PVOID CPerfShare::AllocateLocalCounters(DWORD dwDataSize)
- {
- SHARE_INSTANCE * pShareInstance;
- if (dwDataSize > MAX_BYTES_FOR_INSTANCE_COUNTERS)
- return(NULL);
- if (FALSE == this->Lock())
- return(NULL);
- pShareInstance = new SHARE_INSTANCE;
- if (NULL != pShareInstance)
- {
- *(pShareInstance->wszInstanceName) = L'\0';
- pShareInstance->dwFirstCounter = 0xFFFF;
- pShareInstance->dwDataSize = MAX_BYTES_FOR_INSTANCE_COUNTERS;
- pShareInstance->dwNextInList = DWORD_NULL;
- pShareInstance->pNextUsedByClient = mpShareInstance;
- mpShareInstance = pShareInstance;
- } else
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- this->Unlock();
- return(pShareInstance);
- }
- PVOID CPerfShare::AllocateCounters(PWCHAR wszInstanceName,
- DWORD dwFirstCounter,
- DWORD dwDataSize)
- {
- SHARE_INSTANCE * pShareInstance;
- if (dwDataSize > MAX_BYTES_FOR_INSTANCE_COUNTERS)
- return(NULL);
- if (FALSE == this->Lock())
- return(NULL);
- if (DWORD_NULL == mpShareHeader->dwFreeHeader)
- {
- this->Unlock();
- return(NULL);
- }
- //
- // Pop the first element off the free list.
- //
- pShareInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
- pShareInstance += mpShareHeader->dwFreeHeader;
- mpShareHeader->dwFreeHeader = pShareInstance->dwNextInList;
- //
- // Push the element onto the use list.
- //
- pShareInstance->dwNextInList = mpShareHeader->dwInstanceHeader;
- mpShareHeader->dwInstanceHeader = (pShareInstance -
- (PSHARE_INSTANCE) (mpShareHeader + 1));
- mpShareHeader->dwNumberOfInstances++;
- //
- // Initialize the instance.
- //
- ZeroMemory(pShareInstance->Data, MAX_BYTES_FOR_INSTANCE_COUNTERS);
- pShareInstance->wszInstanceName[MAX_INSTANCE_NAME_LENGTH] = 0;
- wcsncpy(pShareInstance->wszInstanceName,
- wszInstanceName,
- MAX_INSTANCE_NAME_LENGTH);
- pShareInstance->dwFirstCounter = dwFirstCounter;
- pShareInstance->dwDataSize = dwDataSize;
- //
- // Throw the instance onto our local in use list.
- //
- pShareInstance->pNextUsedByClient = mpShareInstance;
- mpShareInstance = pShareInstance;
- this->Unlock();
- return(mpShareInstance->Data);
- }
- PVOID CPerfShare::AllocateCounters(PWCHAR wszServiceName,
- PWCHAR wszInstanceName,
- DWORD dwDataSize)
- {
- DWORD dwFirstCounter;
- PVOID pTemp;
- //
- // We need some kind of tracking ID in the DLL to differentiate
- // between different objects. We require the tool to give us
- // the service name, and we'll use the FirstCounter Id as our
- // unique value. Since this could fail, we do it first so that
- // we know things later are ok.
- //
- if (FALSE == this->GetFirstCounterValueW(wszServiceName, &dwFirstCounter))
- return(this->AllocateLocalCounters(dwDataSize));
- pTemp = this->AllocateCounters(wszInstanceName,
- dwFirstCounter,
- dwDataSize);
- return(pTemp);
- }
- PVOID CPerfShare::AllocateCounters(PCHAR szServiceName,
- PCHAR szInstanceName,
- DWORD dwDataSize)
- {
- PVOID pTemp;
- WCHAR wszInstanceName[MAX_INSTANCE_NAME_LENGTH + 4];
- DWORD dwFirstCounter;
- INT i;
- if (FALSE == this->GetFirstCounterValueA(szServiceName, &dwFirstCounter))
- return(this->AllocateLocalCounters(dwDataSize));
- i = MultiByteToWideChar(
- CP_ACP, // Source code page
- 0, // Flags
- szInstanceName, // Source
- -1, // NULL terminated
- wszInstanceName, // Destination
- MAX_INSTANCE_NAME_LENGTH + 1);
- if (0 == i)
- {
- return(NULL);
- }
- pTemp = this->AllocateCounters(wszInstanceName,
- dwFirstCounter,
- dwDataSize);
- return(pTemp);
- }
- VOID CPerfShare::FreeCounters(PVOID pvCounters)
- {
- PSHARE_INSTANCE pInstance, pLoop, pPrev;
- DWORD *pdwLoop, dwFind;
- if (FALSE == this->Lock())
- return;
- //
- // Find the element in our list.
- //
- pPrev = NULL;
- for(pLoop = mpShareInstance; NULL != pLoop;
- pLoop = pLoop->pNextUsedByClient)
- {
- if (pLoop->Data == pvCounters)
- break;
- pPrev = pLoop;
- }
- if (NULL == pLoop)
- {
- this->Unlock();
- return;
- }
- //
- // Now remove it from our internal list.
- //
- if (NULL == pPrev)
- mpShareInstance = pLoop->pNextUsedByClient;
- else
- pPrev->pNextUsedByClient = pLoop->pNextUsedByClient;
- pLoop->pNextUsedByClient = NULL;
- //
- // Find the counter element on the use list and remove it.
- //
- pInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
- dwFind = (pLoop - pInstance);
- for(pdwLoop = &(mpShareHeader->dwInstanceHeader); *pdwLoop != DWORD_NULL;
- pdwLoop = &(pInstance[*pdwLoop].dwNextInList))
- {
- if (*pdwLoop == dwFind)
- break;
- }
- //
- // Make sure we really found it.
- //
- if (DWORD_NULL == *pdwLoop)
- {
- this->Unlock();
- return;
- }
- *pdwLoop = pInstance[dwFind].dwNextInList;
- mpShareHeader->dwNumberOfInstances--;
- //
- // Add the node to the top of the free list.
- //
- pInstance[dwFind].dwNextInList = mpShareHeader->dwFreeHeader;
- mpShareHeader->dwFreeHeader = dwFind;
- this->Unlock();
- }
- PSHARE_HEADER CPerfShare::GetShareHeader()
- {
- return(mpShareHeader);
- }
- BOOL CPerfShare::Initialized()
- {
- return(mpShareHeader != NULL);
- }
|