sharemem.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include "pch.h"
  2. CPerfShare::CPerfShare()
  3. {
  4. mhSharedMemory = NULL;
  5. mhSharedMutex = NULL;
  6. mpShareHeader = NULL;
  7. mpShareInstance = NULL;
  8. mlLockCount = 0;
  9. }
  10. CPerfShare::~CPerfShare()
  11. {
  12. this->Terminate();
  13. }
  14. BOOL CPerfShare::Lock()
  15. {
  16. BOOL fResult;
  17. LONG lTemp;
  18. fResult = FALSE;
  19. if (TRUE == this->Initialized())
  20. {
  21. lTemp = InterlockedIncrement(&mlLockCount);
  22. if (lTemp > 1)
  23. fResult = TRUE;
  24. else if (WAIT_FAILED != WaitForSingleObject(mhSharedMutex,
  25. SHARE_MUTEX_TIMEOUT))
  26. {
  27. fResult = TRUE;
  28. }
  29. }
  30. return(fResult);
  31. }
  32. VOID CPerfShare::Unlock()
  33. {
  34. LONG lTemp;
  35. if (TRUE == this->Initialized())
  36. {
  37. lTemp = InterlockedDecrement(&mlLockCount);
  38. if (0 == lTemp)
  39. ReleaseMutex(mhSharedMutex);
  40. }
  41. }
  42. BOOL CPerfShare::InitializeHeader()
  43. {
  44. PSHARE_INSTANCE pInstance;
  45. DWORD dwIndex;
  46. //
  47. // Map the file.
  48. //
  49. mpShareHeader = (PSHARE_HEADER) MapViewOfFile(
  50. mhSharedMemory, // Memory Handle
  51. FILE_MAP_WRITE, // Permissions
  52. 0, // Start Offset Hi
  53. 0, // Start Offset Low
  54. 0); // Map all of it
  55. if (NULL == mpShareHeader)
  56. return(FALSE);
  57. //
  58. // Initialize the queue.
  59. //
  60. mpShareHeader->dwNumberOfInstances = 0;
  61. mpShareHeader->dwInstanceHeader = DWORD_NULL;
  62. mpShareHeader->dwFreeHeader = 0;
  63. pInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
  64. for(dwIndex = 0; dwIndex < MAX_INSTANCES_OF_ALL_SHARES - 1; dwIndex++)
  65. {
  66. pInstance->dwNextInList = dwIndex + 1;
  67. pInstance++;
  68. }
  69. pInstance->dwNextInList = DWORD_NULL;
  70. return(TRUE);
  71. }
  72. BOOL CPerfShare::Initialize(BOOL bReadOnly)
  73. {
  74. LONG lError;
  75. if (TRUE == this->Initialized())
  76. return(FALSE);
  77. // Create a NULL dacl to give "everyone" access
  78. SECURITY_DESCRIPTOR sd;
  79. SECURITY_ATTRIBUTES sa = {sizeof(sa), &sd, false};
  80. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  81. SetSecurityDescriptorDacl(&sd, true, NULL, FALSE);
  82. //
  83. // Create/access the shared memory queue.
  84. //
  85. mhSharedMemory = CreateFileMapping((HANDLE) 0xFFFFFFFF, // OS paging file
  86. &sa, // Security
  87. PAGE_READWRITE, // Permissions
  88. 0, // Max Size High
  89. SHARE_SIZE, // Max Size Low
  90. SHARE_FILE_NAME); // Name of File
  91. lError = GetLastError();
  92. if (NULL == mhSharedMemory)
  93. return(FALSE);
  94. //
  95. // Create/access the shared mutex for syncronization.
  96. //
  97. mhSharedMutex = CreateMutex(&sa, // Security
  98. FALSE, // Initial Owner
  99. SHARE_MUTEX_NAME); // Name of Mutex
  100. if (NULL == mhSharedMutex)
  101. return(FALSE);
  102. //
  103. // See if we need to initialize the global structure.
  104. //
  105. if (ERROR_ALREADY_EXISTS != lError)
  106. {
  107. if (FALSE == this->InitializeHeader())
  108. return(FALSE);
  109. } else
  110. {
  111. //
  112. // Map the file.
  113. //
  114. mpShareHeader = (PSHARE_HEADER) MapViewOfFile(
  115. mhSharedMemory, // Memory Handl
  116. bReadOnly ? // Permissions
  117. FILE_MAP_READ :
  118. FILE_MAP_WRITE,
  119. 0, // Start Offset Hi
  120. 0, // Start Offset Low
  121. 0); // Map all of it
  122. if (NULL == mpShareHeader)
  123. return(FALSE);
  124. }
  125. return(TRUE);
  126. }
  127. VOID CPerfShare::Terminate()
  128. {
  129. SHARE_INSTANCE * pTempInstance;
  130. while(NULL != mpShareInstance)
  131. {
  132. pTempInstance = mpShareInstance;
  133. mpShareInstance = mpShareInstance->pNextUsedByClient;
  134. this->FreeCounters(pTempInstance->Data);
  135. }
  136. if (mpShareHeader != NULL)
  137. {
  138. UnmapViewOfFile(mpShareHeader);
  139. mpShareHeader = NULL;
  140. }
  141. if (mhSharedMutex != NULL)
  142. {
  143. CloseHandle(mhSharedMutex);
  144. mhSharedMutex = NULL;
  145. }
  146. if (mhSharedMemory != NULL)
  147. {
  148. CloseHandle(mhSharedMemory);
  149. mhSharedMemory = NULL;
  150. }
  151. }
  152. BOOL CPerfShare::GetFirstCounterValue(PCHAR szServiceName, PDWORD pdwFirst)
  153. {
  154. HKEY hRegKey;
  155. DWORD dwSize, dwType;
  156. LONG lStatus;
  157. lStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE, // Hive
  158. szServiceName, // Subkey
  159. 0L, // Reserved
  160. KEY_READ, // Access Rights
  161. &hRegKey); // Hkey
  162. if (ERROR_SUCCESS != lStatus)
  163. return(FALSE);
  164. if (pdwFirst)
  165. {
  166. dwSize = sizeof(DWORD);
  167. lStatus = RegQueryValueExA(hRegKey, // SubKey
  168. FIRST_COUNTERA, // Value name
  169. 0L, // Reserved
  170. &dwType, // Value Type
  171. (LPBYTE) pdwFirst, // Destination
  172. &dwSize); // Size of buffer
  173. if ((ERROR_SUCCESS != lStatus) || (REG_DWORD != dwType))
  174. {
  175. RegCloseKey(hRegKey);
  176. return(FALSE);
  177. }
  178. }
  179. RegCloseKey(hRegKey);
  180. return(TRUE);
  181. }
  182. BOOL CPerfShare::GetFirstCounterValue(PWCHAR wszServiceName, PDWORD pdwFirst)
  183. {
  184. HKEY hRegKey;
  185. DWORD dwSize, dwType;
  186. LONG lStatus;
  187. lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // Hive
  188. wszServiceName, // Subkey
  189. 0L, // Reserved
  190. KEY_READ, // Access Rights
  191. &hRegKey); // Hkey
  192. if (ERROR_SUCCESS != lStatus)
  193. return(FALSE);
  194. if (pdwFirst)
  195. {
  196. dwSize = sizeof(DWORD);
  197. lStatus = RegQueryValueExW(hRegKey, // SubKey
  198. FIRST_COUNTERW, // Value name
  199. 0L, // Reserved
  200. &dwType, // Value Type
  201. (LPBYTE) pdwFirst, // Destination
  202. &dwSize); // Size of buffer
  203. if ((ERROR_SUCCESS != lStatus) || (REG_DWORD != dwType))
  204. {
  205. RegCloseKey(hRegKey);
  206. return(FALSE);
  207. }
  208. }
  209. RegCloseKey(hRegKey);
  210. return(TRUE);
  211. }
  212. BOOL CPerfShare::GetFirstCounterValueA(PCHAR szServiceName, PDWORD pdwFirst)
  213. {
  214. CHAR szSubKey[2048];
  215. sprintf(szSubKey, "System\\CurrentControlSet\\Services\\%s\\Performance",
  216. szServiceName);
  217. return(GetFirstCounterValue(szSubKey, pdwFirst));
  218. }
  219. BOOL CPerfShare::GetFirstCounterValueW(PWCHAR wszServiceName, PDWORD pdwFirst)
  220. {
  221. WCHAR wszSubKey[2048];
  222. swprintf(wszSubKey, L"System\\CurrentControlSet\\Services\\%s\\Performance",
  223. wszServiceName);
  224. return(GetFirstCounterValue(wszSubKey, pdwFirst));
  225. }
  226. PVOID CPerfShare::AllocateLocalCounters(DWORD dwDataSize)
  227. {
  228. SHARE_INSTANCE * pShareInstance;
  229. if (dwDataSize > MAX_BYTES_FOR_INSTANCE_COUNTERS)
  230. return(NULL);
  231. if (FALSE == this->Lock())
  232. return(NULL);
  233. pShareInstance = new SHARE_INSTANCE;
  234. if (NULL != pShareInstance)
  235. {
  236. *(pShareInstance->wszInstanceName) = L'\0';
  237. pShareInstance->dwFirstCounter = 0xFFFF;
  238. pShareInstance->dwDataSize = MAX_BYTES_FOR_INSTANCE_COUNTERS;
  239. pShareInstance->dwNextInList = DWORD_NULL;
  240. pShareInstance->pNextUsedByClient = mpShareInstance;
  241. mpShareInstance = pShareInstance;
  242. } else
  243. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  244. this->Unlock();
  245. return(pShareInstance);
  246. }
  247. PVOID CPerfShare::AllocateCounters(PWCHAR wszInstanceName,
  248. DWORD dwFirstCounter,
  249. DWORD dwDataSize)
  250. {
  251. SHARE_INSTANCE * pShareInstance;
  252. if (dwDataSize > MAX_BYTES_FOR_INSTANCE_COUNTERS)
  253. return(NULL);
  254. if (FALSE == this->Lock())
  255. return(NULL);
  256. if (DWORD_NULL == mpShareHeader->dwFreeHeader)
  257. {
  258. this->Unlock();
  259. return(NULL);
  260. }
  261. //
  262. // Pop the first element off the free list.
  263. //
  264. pShareInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
  265. pShareInstance += mpShareHeader->dwFreeHeader;
  266. mpShareHeader->dwFreeHeader = pShareInstance->dwNextInList;
  267. //
  268. // Push the element onto the use list.
  269. //
  270. pShareInstance->dwNextInList = mpShareHeader->dwInstanceHeader;
  271. mpShareHeader->dwInstanceHeader = (pShareInstance -
  272. (PSHARE_INSTANCE) (mpShareHeader + 1));
  273. mpShareHeader->dwNumberOfInstances++;
  274. //
  275. // Initialize the instance.
  276. //
  277. ZeroMemory(pShareInstance->Data, MAX_BYTES_FOR_INSTANCE_COUNTERS);
  278. pShareInstance->wszInstanceName[MAX_INSTANCE_NAME_LENGTH] = 0;
  279. wcsncpy(pShareInstance->wszInstanceName,
  280. wszInstanceName,
  281. MAX_INSTANCE_NAME_LENGTH);
  282. pShareInstance->dwFirstCounter = dwFirstCounter;
  283. pShareInstance->dwDataSize = dwDataSize;
  284. //
  285. // Throw the instance onto our local in use list.
  286. //
  287. pShareInstance->pNextUsedByClient = mpShareInstance;
  288. mpShareInstance = pShareInstance;
  289. this->Unlock();
  290. return(mpShareInstance->Data);
  291. }
  292. PVOID CPerfShare::AllocateCounters(PWCHAR wszServiceName,
  293. PWCHAR wszInstanceName,
  294. DWORD dwDataSize)
  295. {
  296. DWORD dwFirstCounter;
  297. PVOID pTemp;
  298. //
  299. // We need some kind of tracking ID in the DLL to differentiate
  300. // between different objects. We require the tool to give us
  301. // the service name, and we'll use the FirstCounter Id as our
  302. // unique value. Since this could fail, we do it first so that
  303. // we know things later are ok.
  304. //
  305. if (FALSE == this->GetFirstCounterValueW(wszServiceName, &dwFirstCounter))
  306. return(this->AllocateLocalCounters(dwDataSize));
  307. pTemp = this->AllocateCounters(wszInstanceName,
  308. dwFirstCounter,
  309. dwDataSize);
  310. return(pTemp);
  311. }
  312. PVOID CPerfShare::AllocateCounters(PCHAR szServiceName,
  313. PCHAR szInstanceName,
  314. DWORD dwDataSize)
  315. {
  316. PVOID pTemp;
  317. WCHAR wszInstanceName[MAX_INSTANCE_NAME_LENGTH + 4];
  318. DWORD dwFirstCounter;
  319. INT i;
  320. if (FALSE == this->GetFirstCounterValueA(szServiceName, &dwFirstCounter))
  321. return(this->AllocateLocalCounters(dwDataSize));
  322. i = MultiByteToWideChar(
  323. CP_ACP, // Source code page
  324. 0, // Flags
  325. szInstanceName, // Source
  326. -1, // NULL terminated
  327. wszInstanceName, // Destination
  328. MAX_INSTANCE_NAME_LENGTH + 1);
  329. if (0 == i)
  330. {
  331. return(NULL);
  332. }
  333. pTemp = this->AllocateCounters(wszInstanceName,
  334. dwFirstCounter,
  335. dwDataSize);
  336. return(pTemp);
  337. }
  338. VOID CPerfShare::FreeCounters(PVOID pvCounters)
  339. {
  340. PSHARE_INSTANCE pInstance, pLoop, pPrev;
  341. DWORD *pdwLoop, dwFind;
  342. if (FALSE == this->Lock())
  343. return;
  344. //
  345. // Find the element in our list.
  346. //
  347. pPrev = NULL;
  348. for(pLoop = mpShareInstance; NULL != pLoop;
  349. pLoop = pLoop->pNextUsedByClient)
  350. {
  351. if (pLoop->Data == pvCounters)
  352. break;
  353. pPrev = pLoop;
  354. }
  355. if (NULL == pLoop)
  356. {
  357. this->Unlock();
  358. return;
  359. }
  360. //
  361. // Now remove it from our internal list.
  362. //
  363. if (NULL == pPrev)
  364. mpShareInstance = pLoop->pNextUsedByClient;
  365. else
  366. pPrev->pNextUsedByClient = pLoop->pNextUsedByClient;
  367. pLoop->pNextUsedByClient = NULL;
  368. //
  369. // Find the counter element on the use list and remove it.
  370. //
  371. pInstance = (PSHARE_INSTANCE) (mpShareHeader + 1);
  372. dwFind = (pLoop - pInstance);
  373. for(pdwLoop = &(mpShareHeader->dwInstanceHeader); *pdwLoop != DWORD_NULL;
  374. pdwLoop = &(pInstance[*pdwLoop].dwNextInList))
  375. {
  376. if (*pdwLoop == dwFind)
  377. break;
  378. }
  379. //
  380. // Make sure we really found it.
  381. //
  382. if (DWORD_NULL == *pdwLoop)
  383. {
  384. this->Unlock();
  385. return;
  386. }
  387. *pdwLoop = pInstance[dwFind].dwNextInList;
  388. mpShareHeader->dwNumberOfInstances--;
  389. //
  390. // Add the node to the top of the free list.
  391. //
  392. pInstance[dwFind].dwNextInList = mpShareHeader->dwFreeHeader;
  393. mpShareHeader->dwFreeHeader = dwFind;
  394. this->Unlock();
  395. }
  396. PSHARE_HEADER CPerfShare::GetShareHeader()
  397. {
  398. return(mpShareHeader);
  399. }
  400. BOOL CPerfShare::Initialized()
  401. {
  402. return(mpShareHeader != NULL);
  403. }