Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
11 KiB

  1. /*
  2. - PERFAPP.CPP
  3. -
  4. * Purpose:
  5. * Implements the GLOBCNTR object used by Apps to initialize, update,
  6. * and deinitialize the PerfMon counters.
  7. *
  8. *
  9. * References:
  10. *
  11. */
  12. #include <windows.h>
  13. #include <winperf.h>
  14. #include <winerror.h>
  15. #include <perfutil.h>
  16. #include <perfapp.h>
  17. #include <tchar.h>
  18. static const DWORD g_cMaxInst = 128;
  19. // ---------------------------------------------------------------------------
  20. // Prototypes
  21. // ---------------------------------------------------------------------------
  22. static HRESULT HrLogEvent(HANDLE hEventLog, WORD wType, DWORD msgid);
  23. //-----------------------------------------------------------------------------
  24. // GLOBCNTR methods
  25. //-----------------------------------------------------------------------------
  26. HRESULT
  27. GLOBCNTR::HrInit(GLOBAL_CNTR cCounters, LPWSTR szGlobalSMName, LPWSTR szSvcName)
  28. {
  29. HRESULT hr = S_OK;
  30. HANDLE hEventLog = NULL;
  31. BOOL fExist;
  32. if (0 == cCounters ||
  33. NULL == szGlobalSMName ||
  34. NULL == szSvcName ||
  35. 128 < cCounters ) //We should not have more than 128 counters
  36. {
  37. return E_INVALIDARG;
  38. }
  39. if (m_fInit)
  40. {
  41. return E_FAIL;
  42. }
  43. m_cCounters = cCounters;
  44. hEventLog = RegisterEventSource(NULL, szSvcName);
  45. // This must be called before any calls to HrOpenSharedMemory()
  46. hr = HrInitializeSecurityAttribute(&m_sa);
  47. if (FAILED(hr))
  48. {
  49. goto ret;
  50. }
  51. // Open shared memory to the process wide Perf Counters. Our member
  52. // variable m_ppc will be mapped onto this address space and counters are
  53. // simply indexes into this address space.
  54. hr = HrOpenSharedMemory(szGlobalSMName,
  55. (sizeof(DWORD) * m_cCounters),
  56. &m_sa,
  57. &m_hsm,
  58. (LPVOID *) &m_rgdwPerfData,
  59. &fExist);
  60. if (FAILED(hr))
  61. {
  62. goto ret;
  63. }
  64. ZeroMemory(m_rgdwPerfData, (sizeof(DWORD) * m_cCounters));
  65. // Open for business!
  66. m_fInit = TRUE;
  67. ret:
  68. if (hEventLog)
  69. DeregisterEventSource(hEventLog);
  70. return hr;
  71. }
  72. /*
  73. - Shutdown
  74. -
  75. * Purpose:
  76. * Cleanup and shutdown the GLOBCNTR object
  77. */
  78. void
  79. GLOBCNTR::Shutdown(void)
  80. {
  81. if (m_fInit)
  82. {
  83. m_fInit = FALSE;
  84. if (m_rgdwPerfData)
  85. {
  86. // Set all counters to zero at shutdown time
  87. ZeroMemory(m_rgdwPerfData, (sizeof(DWORD) * m_cCounters));
  88. UnmapViewOfFile(m_rgdwPerfData);
  89. m_rgdwPerfData = NULL;
  90. }
  91. if (m_hsm)
  92. {
  93. CloseHandle(m_hsm);
  94. m_hsm = NULL;
  95. }
  96. }
  97. }
  98. //-----------------------------------------------------------------------------
  99. // INSTCNTR methods
  100. //-----------------------------------------------------------------------------
  101. /*
  102. - Destructor
  103. -
  104. * Purpose:
  105. * Object cleanup & verify consistency
  106. */
  107. INSTCNTR::~INSTCNTR()
  108. {
  109. if(m_sa.lpSecurityDescriptor)
  110. LocalFree(m_sa.lpSecurityDescriptor);
  111. }
  112. /*
  113. - HrInit
  114. -
  115. * Purpose:
  116. * Setup shared memory blocks
  117. * Prep Admin & Counter blocks for use
  118. */
  119. HRESULT
  120. INSTCNTR::HrInit(INST_CNTR cCounters,
  121. LPWSTR szInstSMName,
  122. LPWSTR szInstMutexName,
  123. LPWSTR szSvcName)
  124. {
  125. HRESULT hr = S_OK;
  126. DWORD cbAdm = 0;
  127. DWORD cbCntr = 0;
  128. WCHAR szAdmName[MAX_PATH]; // Admin SM Name
  129. WCHAR szCntrName[MAX_PATH]; // Counter SM Name
  130. LPVOID pv;
  131. HANDLE hEventLog;
  132. BOOL fExist;
  133. BOOL fInMutex = FALSE;
  134. // Validate args
  135. if (0 == cCounters || !szInstSMName || !szInstMutexName || !szSvcName)
  136. return E_INVALIDARG;
  137. // Save Number of Counters
  138. m_cCounters = cCounters;
  139. if (m_fInit)
  140. {
  141. return E_FAIL;
  142. }
  143. // Open Application Event Log
  144. hEventLog = RegisterEventSource(NULL, szSvcName);
  145. // This must be called before any calls to HrOpenSharedMemory() and
  146. // HrCreatePerfMutex() and must only be called once!!!
  147. hr = HrInitializeSecurityAttribute(&m_sa);
  148. if (FAILED(hr))
  149. {
  150. goto ret;
  151. }
  152. // Obtain Mutex. If call returns okay, we hold the mutex.
  153. hr = HrCreatePerfMutex(&m_sa, szInstMutexName, &m_hmtx);
  154. if (FAILED(hr))
  155. {
  156. goto ret;
  157. }
  158. fInMutex = TRUE;
  159. // Calc required memory sizes
  160. cbAdm = sizeof(INSTCNTR_DATA) + (sizeof(INSTREC) * g_cMaxInst);
  161. cbCntr = ((sizeof(DWORD) * cCounters) * g_cMaxInst);
  162. // Build names for the two shared memory blocks
  163. if(wcslen(szInstSMName) >= (MAX_PATH - 6)) // Enough space to wsprintf.
  164. {
  165. hr=E_FAIL;
  166. goto ret;
  167. }
  168. wsprintf(szAdmName, L"%s_ADM", szInstSMName);
  169. wsprintf(szCntrName,L"%s_CNTR", szInstSMName);
  170. // Open Admin Shared Memory Block
  171. hr = HrOpenSharedMemory(szAdmName,
  172. cbAdm,
  173. &m_sa,
  174. &m_hsmAdm,
  175. (LPVOID *) &pv,
  176. &fExist);
  177. if (FAILED(hr))
  178. {
  179. goto ret;
  180. }
  181. // Fixup Pointers
  182. m_picd = (INSTCNTR_DATA *) pv;
  183. m_rgInstRec = (INSTREC *) ((char *) pv + sizeof(INSTCNTR_DATA));
  184. if (!fExist)
  185. {
  186. ZeroMemory(pv, cbAdm);
  187. m_picd->cMaxInstRec = g_cMaxInst;
  188. m_picd->cInstRecInUse = 0;
  189. }
  190. // Open Counters Shared Memory Block
  191. hr = HrOpenSharedMemory(szCntrName,
  192. cbCntr,
  193. &m_sa,
  194. &m_hsmCntr,
  195. (LPVOID *) &m_rgdwCntr,
  196. &fExist);
  197. if (FAILED(hr))
  198. {
  199. goto ret;
  200. }
  201. if ( !fExist)
  202. {
  203. ZeroMemory(m_rgdwCntr, cbCntr);
  204. }
  205. // Open for business!
  206. m_fInit = TRUE;
  207. ret:
  208. if (hEventLog)
  209. DeregisterEventSource(hEventLog);
  210. if (m_hmtx && fInMutex)
  211. ReleaseMutex(m_hmtx);
  212. return hr;
  213. }
  214. /*
  215. - Shutdown
  216. -
  217. * Purpose:
  218. * Cleanup and shutdown the INSTCNTR object
  219. */
  220. void
  221. INSTCNTR::Shutdown(BOOL fWipeOut)
  222. {
  223. if (m_fInit)
  224. {
  225. m_fInit = FALSE;
  226. if (m_rgdwCntr)
  227. {
  228. // Zero out this shared memory block too. All counters should
  229. // start at zero.
  230. if ( fWipeOut )
  231. {
  232. ZeroMemory(m_rgdwCntr, (sizeof(DWORD) * m_cCounters) * g_cMaxInst);
  233. }
  234. UnmapViewOfFile(m_rgdwCntr);
  235. m_rgdwCntr = NULL;
  236. }
  237. // NOTE: m_picd points at the head of the
  238. // Admin shared memory block. Do not UnmapViewOfFile on
  239. // the m_rgInstRec pointer!
  240. if (m_picd)
  241. {
  242. // Zero out the shared memory block
  243. if ( fWipeOut )
  244. {
  245. ZeroMemory(m_picd, sizeof(INSTCNTR_DATA) + (sizeof(INSTREC) * g_cMaxInst));
  246. m_picd->cMaxInstRec = g_cMaxInst;
  247. m_picd->cInstRecInUse = 0;
  248. }
  249. UnmapViewOfFile(m_picd);
  250. m_picd = NULL;
  251. m_rgInstRec = NULL;
  252. }
  253. if (m_hsmAdm)
  254. {
  255. CloseHandle(m_hsmAdm);
  256. m_hsmAdm = NULL;
  257. }
  258. if (m_hsmCntr)
  259. {
  260. CloseHandle(m_hsmCntr);
  261. m_hsmCntr = NULL;
  262. }
  263. if (m_hmtx)
  264. {
  265. CloseHandle(m_hmtx);
  266. m_hmtx = NULL;
  267. }
  268. }
  269. }
  270. /*
  271. - HrCreateOrGetInstance
  272. -
  273. * Purpose:
  274. * Return a token corresponding to an Instance Counter Block
  275. * Returns:
  276. * S_OK ID Found; picid contains a valid INSTCNTR_ID
  277. * E_FAIL Object not initialized *OR* ID not found
  278. * E_INVALIDARG Bad parameter/NULL pointer
  279. */
  280. HRESULT
  281. INSTCNTR::HrCreateOrGetInstance(LPCWSTR wszInstName, INSTCNTR_ID *picid)
  282. {
  283. HRESULT hr = S_OK;
  284. if (!m_fInit)
  285. return E_FAIL;
  286. // Validate args
  287. if (!picid || !wszInstName)
  288. return E_INVALIDARG;
  289. *picid = INVALID_INST_ID;
  290. // Obtain exclusive access to SM blocks
  291. DWORD dwWait = WaitForSingleObject(m_hmtx, INFINITE);
  292. if (WAIT_OBJECT_0 != dwWait)
  293. {
  294. // No simple way to translate the return into an HRESULT
  295. return E_FAIL;
  296. }
  297. // We have the mutex; we must release before leaving
  298. // Linear probe through list looking for a matching or open slot
  299. for (unsigned int i = 0; i < m_picd->cMaxInstRec; i++)
  300. {
  301. if ( m_rgInstRec[i].fInUse && (0 == wcscmp(m_rgInstRec[i].szInstName, wszInstName)) )
  302. {
  303. // Found first instance with matching name.
  304. *picid = (INSTCNTR_ID) i;
  305. break;
  306. }
  307. else if (!m_rgInstRec[i].fInUse && (INVALID_INST_ID == *picid))
  308. {
  309. // Found the first free slot -- remember its number
  310. *picid = (INSTCNTR_ID) i;
  311. }
  312. }
  313. if (INVALID_INST_ID == *picid)
  314. {
  315. // No matching or free slots found
  316. hr = E_FAIL;
  317. goto Cleanup;
  318. }
  319. else if (!m_rgInstRec[*picid].fInUse)
  320. {
  321. // Found no matching slot, but found a free slot -- mark as
  322. // in use and set instance name
  323. wcsncpy(m_rgInstRec[*picid].szInstName, wszInstName, min((wcslen(wszInstName) + 1),MAX_PATH));
  324. m_rgInstRec[*picid].fInUse = TRUE;
  325. m_picd->cInstRecInUse++;
  326. // Zero out corresponding counter block
  327. ZeroMemory(&m_rgdwCntr[(m_cCounters * (*picid))], (sizeof(DWORD) * m_cCounters));
  328. }
  329. Cleanup:
  330. ReleaseMutex(m_hmtx);
  331. return hr;
  332. }
  333. /*
  334. - HrDestroyInstance
  335. -
  336. * Purpose:
  337. * Release Instance Counter Block associated with the token icid.
  338. */
  339. HRESULT
  340. INSTCNTR::HrDestroyInstance(INSTCNTR_ID icid)
  341. {
  342. HRESULT hr = S_OK;
  343. if (!m_fInit)
  344. return E_FAIL;
  345. // Get exclusive access to SM blocks
  346. DWORD dwWait = WaitForSingleObject(m_hmtx, INFINITE);
  347. if (WAIT_OBJECT_0 != dwWait)
  348. {
  349. // No simple way to translate the return into an HRESULT
  350. return E_FAIL;
  351. }
  352. if (m_rgInstRec[icid].fInUse)
  353. {
  354. // Mark the block as Not In Use
  355. m_rgInstRec[icid].fInUse = FALSE;
  356. // Zero out corresponding counter block
  357. ZeroMemory(&m_rgdwCntr[(m_cCounters * (icid))], (sizeof(DWORD) * m_cCounters));
  358. //Assert(m_picd->cInstRecInUse != 0);
  359. m_picd->cInstRecInUse--;
  360. } else
  361. {
  362. hr = E_FAIL;
  363. }
  364. ReleaseMutex(m_hmtx);
  365. return hr;
  366. }
  367. /*
  368. - HrLogEvent
  369. -
  370. * Purpose:
  371. * Wrap up the call to ReportEvent to make things look nicer.
  372. */
  373. HRESULT
  374. HrLogEvent(HANDLE hEventLog, WORD wType, DWORD msgid)
  375. {
  376. if (hEventLog)
  377. return ReportEvent(hEventLog,
  378. wType,
  379. (WORD)0,//facPerfMonDll,
  380. msgid,
  381. NULL,
  382. 0,
  383. 0,
  384. NULL,
  385. NULL);
  386. else
  387. return E_FAIL;
  388. }