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.

1101 lines
31 KiB

  1. /*==========================================================================*\
  2. Module: exprflib.cpp
  3. Copyright Microsoft Corporation 1998, All Rights Reserved.
  4. Author: WayneC
  5. Descriptions: This is the implentation for exprflib, a perf library. This
  6. is the code that runs in the app exporting the counters.
  7. \*==========================================================================*/
  8. #include "stdlib.h"
  9. #include "snprflib.h"
  10. #include "dbgtrace.h"
  11. DWORD InitializeBasicSecurityDescriptor (PSECURITY_DESCRIPTOR *ppSd);
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Forward declaration of shared memory functions.
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17. BOOL FCreateFileMapping (SharedMemorySegment * pSMS,
  18. LPCWSTR pcwstrInstanceName,
  19. DWORD dwIndex,
  20. DWORD cbSize);
  21. void CloseFileMapping (SharedMemorySegment * pSMS);
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // PerfLibrary class declaration. There is one perf library instance per linkee.
  25. //
  26. ///////////////////////////////////////////////////////////////////////////////
  27. PerfLibrary::PerfLibrary (LPCWSTR pcwstrPerfName)
  28. {
  29. wcsncpy (m_wszPerfName, pcwstrPerfName, MAX_PERF_NAME);
  30. m_wszPerfName[MAX_PERF_NAME-1] = L'\0'; // Ensure NULL termination
  31. ZeroMemory (m_rgpObjDef, sizeof (m_rgpObjDef));
  32. m_dwObjDef = 0;
  33. m_hMap = 0;
  34. m_pbMap = 0;
  35. }
  36. PerfLibrary::~PerfLibrary (void)
  37. {
  38. DeInit ();
  39. }
  40. void
  41. PerfLibrary::DeInit (void)
  42. {
  43. DWORD i;
  44. // Destroy the PerfObjectDefinition's we owned.
  45. for (i = 0; i < m_dwObjDef; i++)
  46. {
  47. delete m_rgpObjDef[i];
  48. m_rgpObjDef[i] = NULL;
  49. }
  50. m_dwObjDef = 0;
  51. // Destroy our shared memory mapping.
  52. if (m_pbMap)
  53. {
  54. UnmapViewOfFile ((void*) m_pbMap);
  55. m_pbMap = 0;
  56. }
  57. if (m_hMap)
  58. {
  59. CloseHandle (m_hMap);
  60. m_hMap = 0;
  61. }
  62. }
  63. PerfObjectDefinition*
  64. PerfLibrary::AddPerfObjectDefinition (LPCWSTR pcwstrObjectName,
  65. DWORD dwObjectNameIndex,
  66. BOOL fInstances)
  67. {
  68. PerfObjectDefinition* ppod = NULL;
  69. if (m_dwObjDef < MAX_PERF_OBJECTS)
  70. {
  71. ppod = new PerfObjectDefinition (pcwstrObjectName,
  72. dwObjectNameIndex,
  73. fInstances);
  74. if (NULL == ppod)
  75. goto Exit;
  76. m_rgpObjDef[m_dwObjDef++] = ppod;
  77. }
  78. Exit:
  79. return ppod;
  80. }
  81. BOOL
  82. PerfLibrary::Init (void)
  83. {
  84. DWORD i = 0;
  85. WCHAR wszPerformanceKey[256] = {L'\0'};
  86. HKEY hKey = NULL;
  87. LONG status = 0;
  88. DWORD size, type = 0;
  89. BOOL fRet = FALSE;
  90. DWORD dwErr = ERROR_SUCCESS;
  91. PSECURITY_DESCRIPTOR pSd = NULL;
  92. SECURITY_ATTRIBUTES sa;
  93. //
  94. // Get counter and help index base values from registry and
  95. // update static data structures by adding base to offset values
  96. // that are statically defined in the structure initialization
  97. //
  98. swprintf (wszPerformanceKey,
  99. L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance",
  100. m_wszPerfName );
  101. status = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  102. wszPerformanceKey,
  103. 0L,
  104. KEY_READ,
  105. &hKey);
  106. if (status != ERROR_SUCCESS)
  107. goto Exit;
  108. //
  109. // Get FirstCounter RegValue
  110. //
  111. size = sizeof(DWORD);
  112. status = RegQueryValueEx (hKey,
  113. "First Counter",
  114. 0L,
  115. &type,
  116. (LPBYTE)&m_dwFirstCounter,
  117. &size);
  118. if (status != ERROR_SUCCESS)
  119. goto Exit;
  120. //
  121. // Get FirstHelp RegValue
  122. //
  123. size = sizeof(DWORD);
  124. status = RegQueryValueEx( hKey,
  125. "First Help",
  126. 0L,
  127. &type,
  128. (LPBYTE)&m_dwFirstHelp,
  129. &size);
  130. if (status != ERROR_SUCCESS)
  131. goto Exit;
  132. //
  133. // Initialize the security descriptor with completely open access
  134. //
  135. dwErr = InitializeBasicSecurityDescriptor (&pSd);
  136. if (dwErr) {
  137. fRet = FALSE;
  138. goto Exit;
  139. }
  140. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  141. sa.lpSecurityDescriptor = pSd;
  142. sa.bInheritHandle = TRUE;
  143. //
  144. // Create the shared memory object for the list of object names.
  145. // Return error if it already exists as we cannot operate if this
  146. // is the second instance of the app.
  147. //
  148. m_hMap = CreateFileMappingW (INVALID_HANDLE_VALUE,
  149. &sa,
  150. PAGE_READWRITE,
  151. 0,
  152. (MAX_PERF_OBJECTS * MAX_OBJECT_NAME *
  153. sizeof (WCHAR) + sizeof (DWORD)),
  154. m_wszPerfName);
  155. if (m_hMap == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
  156. goto Exit;
  157. //
  158. // Map the file into memory
  159. //
  160. m_pbMap = (BYTE*) MapViewOfFile (m_hMap, FILE_MAP_WRITE, 0, 0, 0);
  161. if (!m_pbMap)
  162. goto Exit;
  163. //
  164. // Assign pointers into the shared memory region
  165. //
  166. m_pdwObjectNames = (DWORD*) m_pbMap;
  167. m_prgObjectNames = (OBJECTNAME*) (m_pbMap+sizeof(DWORD));
  168. //
  169. // Copy the object names into the shared memory
  170. //
  171. *m_pdwObjectNames = m_dwObjDef;
  172. for (i = 0; i < m_dwObjDef; i++)
  173. {
  174. if (m_rgpObjDef[i]->Init( this ))
  175. wcscpy (m_prgObjectNames[i], m_rgpObjDef[i]->m_wszObjectName);
  176. }
  177. fRet = TRUE;
  178. Exit:
  179. if (hKey)
  180. RegCloseKey (hKey);
  181. if (!fRet)
  182. {
  183. if (m_pbMap)
  184. {
  185. UnmapViewOfFile ((PVOID)m_pbMap);
  186. m_pbMap = 0;
  187. }
  188. if (m_hMap)
  189. {
  190. CloseHandle (m_hMap);
  191. m_hMap = 0;
  192. }
  193. }
  194. if (pSd)
  195. delete [] (BYTE *) pSd;
  196. return fRet;
  197. }
  198. ///////////////////////////////////////////////////////////////////////////////
  199. //
  200. // PerfObjectDefinition class implementation. There is one of these for each
  201. // perfmon object exported. Generally there is just one, but not neccessarily.
  202. //
  203. ///////////////////////////////////////////////////////////////////////////////
  204. PerfObjectDefinition::PerfObjectDefinition (LPCWSTR pcwstrObjectName,
  205. DWORD dwObjectNameIndex,
  206. BOOL fInstances) :
  207. m_dwObjectNameIndex (dwObjectNameIndex),
  208. m_fInstances (fInstances),
  209. m_dwCounters (0)
  210. {
  211. wcsncpy (m_wszObjectName, pcwstrObjectName, MAX_OBJECT_NAME);
  212. m_wszObjectName[MAX_OBJECT_NAME-1] = L'\0'; // Ensure NULL Terminated
  213. ZeroMemory (m_rgpCounterDef, sizeof(m_rgpCounterDef));
  214. m_dwActiveInstances = 0;
  215. m_pSMS = NULL;
  216. m_dwShmemMappingSize = SHMEM_MAPPING_SIZE;
  217. m_fCSInit = FALSE;
  218. m_pPoiTotal = NULL;
  219. m_pPerfObjectType = NULL;
  220. }
  221. PerfObjectDefinition::~PerfObjectDefinition (void)
  222. {
  223. DeInit();
  224. }
  225. void
  226. PerfObjectDefinition::DeInit (void)
  227. {
  228. SharedMemorySegment *pSMS, *pSMSNext;
  229. DWORD i;
  230. // First destroy the _Total instance.
  231. if (m_pPoiTotal)
  232. {
  233. delete m_pPoiTotal;
  234. m_pPoiTotal = NULL;
  235. }
  236. //
  237. // Reset these values in the shared memory so that before we unmap the memory,
  238. // perfmon won't think that we still have instances & counters running.
  239. //
  240. if (m_pPerfObjectType)
  241. {
  242. m_pPerfObjectType->NumCounters = 0;
  243. m_pPerfObjectType->NumInstances = 0;
  244. }
  245. // Destroy the PerfCounterDefinition's we owned.
  246. for (i = 0; i < m_dwCounters; i++)
  247. {
  248. delete m_rgpCounterDef[i];
  249. m_rgpCounterDef[i] = NULL;
  250. }
  251. pSMS = m_pSMS;
  252. m_pSMS = NULL;
  253. // Enumerate through all the memory mappings we created and destroy them.
  254. while (pSMS)
  255. {
  256. pSMSNext = pSMS->m_pSMSNext;
  257. CloseFileMapping (pSMS);
  258. delete (pSMS);
  259. pSMS = pSMSNext;
  260. }
  261. // Destroy the critical section.
  262. if (m_fCSInit)
  263. {
  264. m_fCSInit = FALSE;
  265. DeleteCriticalSection (&m_csPerfObjInst);
  266. }
  267. }
  268. PerfCounterDefinition*
  269. PerfObjectDefinition::AddPerfCounterDefinition (
  270. DWORD dwCounterNameIndex,
  271. DWORD dwCounterType,
  272. LONG lDefaultScale)
  273. {
  274. PerfCounterDefinition* ppcd = NULL;
  275. if (m_dwCounters < MAX_OBJECT_COUNTERS)
  276. {
  277. ppcd = new PerfCounterDefinition (dwCounterNameIndex,
  278. dwCounterType,
  279. lDefaultScale);
  280. if (NULL == ppcd)
  281. goto Exit;
  282. m_rgpCounterDef[m_dwCounters++] = ppcd;
  283. }
  284. Exit:
  285. return ppcd;
  286. }
  287. PerfCounterDefinition*
  288. PerfObjectDefinition::AddPerfCounterDefinition (
  289. PerfCounterDefinition* pCtrRef,
  290. DWORD dwCounterNameIndex,
  291. DWORD dwCounterType,
  292. LONG lDefaultScale)
  293. {
  294. PerfCounterDefinition* ppcd = NULL;
  295. if (m_dwCounters < MAX_OBJECT_COUNTERS)
  296. {
  297. ppcd = new PerfCounterDefinition (pCtrRef,
  298. dwCounterNameIndex,
  299. dwCounterType,
  300. lDefaultScale);
  301. if (NULL == ppcd)
  302. goto Exit;
  303. m_rgpCounterDef[m_dwCounters++] = ppcd;
  304. }
  305. Exit:
  306. return ppcd;
  307. }
  308. BOOL
  309. PerfObjectDefinition::Init (PerfLibrary* pPerfLib)
  310. {
  311. DWORD i = 0;
  312. DWORD dwOffset = 0;
  313. DWORD dwDefinitionLength= 0;
  314. BOOL fRet = FALSE;
  315. //
  316. // Compute the size of the shared memory for this object definition
  317. //
  318. // Start with the basics:
  319. // we need a PERF_OBJECT_TYPE for the object information and
  320. // we need a PERF_COUNTER_DEFINITION for each counter in the object
  321. dwDefinitionLength = (sizeof(PERF_OBJECT_TYPE) +
  322. m_dwCounters * sizeof(PERF_COUNTER_DEFINITION));
  323. // We also keep a DWORD in the shared memory to give the DLL
  324. // our pre-computed value for m_dwCounterData
  325. m_dwDefinitionLength = dwDefinitionLength + sizeof(DWORD);
  326. // Compute the counter data space
  327. m_dwCounterData = sizeof(PERF_COUNTER_BLOCK);
  328. for (i = 0; i < m_dwCounters; i++)
  329. {
  330. m_dwCounterData += m_rgpCounterDef[i]->m_dwCounterSize;
  331. }
  332. // Compute the per instance space
  333. m_dwPerInstanceData = (sizeof(INSTANCE_DATA) + m_dwCounterData);
  334. // Make sure our memory mapping is large enough
  335. while (m_dwShmemMappingSize < m_dwDefinitionLength || m_dwShmemMappingSize < m_dwPerInstanceData)
  336. m_dwShmemMappingSize *= 2;
  337. // Compute the number of instances can be stored in one shmem mapping.
  338. m_dwInstancesPerMapping = (DWORD)(m_dwShmemMappingSize / m_dwPerInstanceData);
  339. m_dwInstances1stMapping = (DWORD)((m_dwShmemMappingSize - m_dwDefinitionLength) / m_dwPerInstanceData);
  340. //
  341. // Create the shared memory object for the list of object names. If it
  342. // already exists, abort!
  343. //
  344. m_pSMS = new SharedMemorySegment;
  345. if (!m_pSMS)
  346. goto Exit;
  347. if (!FCreateFileMapping (m_pSMS, m_wszObjectName, 0, m_dwShmemMappingSize))
  348. goto Exit;
  349. //
  350. // Set the pointers to the PERF API structures
  351. //
  352. m_pPerfObjectType = (PERF_OBJECT_TYPE*) m_pSMS->m_pbMap;
  353. m_rgPerfCounterDefinition =
  354. (PERF_COUNTER_DEFINITION*) (m_pPerfObjectType+1);
  355. //
  356. // Initialize the PERF API structures
  357. //
  358. m_pPerfObjectType->TotalByteLength = dwDefinitionLength;
  359. m_pPerfObjectType->DefinitionLength = dwDefinitionLength;
  360. m_pPerfObjectType->HeaderLength = sizeof (PERF_OBJECT_TYPE);
  361. m_pPerfObjectType->ObjectNameTitleIndex = m_dwObjectNameIndex +
  362. pPerfLib->m_dwFirstCounter ;
  363. m_pPerfObjectType->ObjectNameTitle = 0;
  364. m_pPerfObjectType->ObjectHelpTitleIndex = m_dwObjectNameIndex +
  365. pPerfLib->m_dwFirstHelp;
  366. m_pPerfObjectType->ObjectHelpTitle = 0;
  367. m_pPerfObjectType->DetailLevel = PERF_DETAIL_NOVICE;
  368. m_pPerfObjectType->NumCounters = m_dwCounters;
  369. m_pPerfObjectType->CodePage = (DWORD) 0xffffffff;
  370. m_pPerfObjectType->DefaultCounter = 0;
  371. if( !m_fInstances )
  372. m_pPerfObjectType->NumInstances = PERF_NO_INSTANCES;
  373. else
  374. m_pPerfObjectType->NumInstances = 0;
  375. //
  376. // Have all of the PerfCounterDefinition's in this object intialize their
  377. // PERF_COUNTER_DEFINITION structures in the shared memory
  378. //
  379. dwOffset = sizeof (PERF_COUNTER_BLOCK);
  380. for (i = 0; i < m_dwCounters; i++)
  381. m_rgpCounterDef[i]->Init(pPerfLib, m_rgPerfCounterDefinition + i, &dwOffset);
  382. // Save value for dwCounterData in shared memory for DLL
  383. *((DWORD*) (m_pSMS->m_pbMap + dwDefinitionLength)) = m_dwCounterData;
  384. //
  385. // Initialzie the critical section to protects the creation/deletion of
  386. // perf object instances. Use AndSpinCount variation to avoid exception
  387. // handling.
  388. //
  389. if (!InitializeCriticalSectionAndSpinCount(&m_csPerfObjInst, 0x80000000))
  390. goto Exit;
  391. m_fCSInit = TRUE;
  392. // Create the _Total instance as the 1st instance if there will be multiple instances
  393. if (m_fInstances)
  394. {
  395. m_pPoiTotal = AddPerfObjectInstance (L"_Total");
  396. if (!m_pPoiTotal)
  397. goto Exit;
  398. }
  399. fRet = TRUE;
  400. Exit:
  401. if (!fRet)
  402. {
  403. if (m_pPoiTotal)
  404. {
  405. delete m_pPoiTotal;
  406. m_pPoiTotal = NULL;
  407. }
  408. if (m_fCSInit)
  409. {
  410. DeleteCriticalSection (&m_csPerfObjInst);
  411. m_fCSInit = FALSE;
  412. }
  413. if (m_pSMS)
  414. {
  415. CloseFileMapping (m_pSMS);
  416. delete (m_pSMS);
  417. m_pSMS = NULL;
  418. }
  419. }
  420. return fRet;
  421. }
  422. DWORD
  423. PerfObjectDefinition::GetCounterOffset (DWORD dwId)
  424. {
  425. for (DWORD i = 0; i < m_dwCounters; i++)
  426. if (m_rgpCounterDef[i]->m_dwCounterNameIndex == dwId)
  427. return m_rgpCounterDef[i]->m_dwOffset;
  428. return 0;
  429. }
  430. PerfObjectInstance*
  431. PerfObjectDefinition::AddPerfObjectInstance (LPCWSTR pwcstrInstanceName)
  432. {
  433. PerfObjectInstance* ppoi = NULL;
  434. char* pCounterData = NULL;
  435. INSTANCE_DATA* pInstData = 0;
  436. LONG lID = 0;
  437. SharedMemorySegment* pSMS = NULL;
  438. SharedMemorySegment* pSMSPrev = NULL;
  439. SharedMemorySegment* pSMSNew = NULL;
  440. DWORD dwInstances = 0;
  441. DWORD dwInstIndex = 0;
  442. DWORD dwSMS = 0;
  443. BOOL fCSEntered = FALSE;
  444. BOOL fSuccess = FALSE;
  445. //
  446. // Make sure we've been initialized
  447. //
  448. if (!m_pSMS || !m_fCSInit)
  449. goto Exit;
  450. //
  451. // Instances may be created in different threads. Need to protect the following code.
  452. //
  453. EnterCriticalSection (&m_csPerfObjInst);
  454. fCSEntered = TRUE;
  455. if (!m_fInstances)
  456. {
  457. // See if we have already created the single instance of this object
  458. if (m_dwActiveInstances != 0)
  459. goto Exit;
  460. pCounterData = (char *)(m_pSMS->m_pbMap) + m_dwDefinitionLength;
  461. }
  462. else
  463. {
  464. //
  465. // Find a free instance in current mapped segments.
  466. //
  467. pSMS = m_pSMS;
  468. lID = 0;
  469. while (pSMS)
  470. {
  471. if (0 == dwSMS++)
  472. {
  473. //
  474. // If this is the first mapping, offset pCounterData by m_dwDefinitionLength.
  475. //
  476. pCounterData = (char *)(pSMS->m_pbMap) + m_dwDefinitionLength;
  477. dwInstances = m_dwInstances1stMapping;
  478. }
  479. else
  480. {
  481. //
  482. // Otherwise, pCounterData starts from the 1st byte of the mapping.
  483. //
  484. pCounterData = (char *)(pSMS->m_pbMap);
  485. dwInstances = m_dwInstancesPerMapping;
  486. }
  487. for (dwInstIndex = 0;
  488. dwInstIndex < dwInstances;
  489. pCounterData += sizeof (INSTANCE_DATA) + m_dwCounterData, dwInstIndex++)
  490. {
  491. if (!((INSTANCE_DATA*) pCounterData)->fActive)
  492. {
  493. pInstData = (INSTANCE_DATA*) pCounterData;
  494. pCounterData = pCounterData + sizeof (INSTANCE_DATA);
  495. goto Found;
  496. }
  497. lID++;
  498. }
  499. pSMSPrev = pSMS;
  500. pSMS = pSMS->m_pSMSNext;
  501. }
  502. //
  503. // If cannot find a free instance, create a new segment.
  504. //
  505. pSMSNew = new SharedMemorySegment;
  506. if (!pSMSNew)
  507. goto Exit;
  508. if (!FCreateFileMapping (pSMSNew, m_wszObjectName, dwSMS, m_dwShmemMappingSize))
  509. goto Exit;
  510. pInstData = (INSTANCE_DATA*) (pSMSNew->m_pbMap);
  511. pCounterData = (char*) (pSMSNew->m_pbMap) + sizeof (INSTANCE_DATA);
  512. //
  513. // Add the new segment to our segment linked list.
  514. //
  515. pSMSPrev->m_pSMSNext = pSMSNew;
  516. }
  517. Found:
  518. //
  519. // We successfully found a free space for new instance.
  520. //
  521. ppoi = new PerfObjectInstance (this, pwcstrInstanceName);
  522. if (!ppoi)
  523. goto Exit;
  524. ppoi->Init(pCounterData, pInstData, lID);
  525. m_pPerfObjectType->NumInstances++;
  526. m_dwActiveInstances++;
  527. fSuccess = TRUE;
  528. Exit:
  529. if (fCSEntered)
  530. LeaveCriticalSection (&m_csPerfObjInst);
  531. if (!fSuccess)
  532. {
  533. if (pSMSNew)
  534. {
  535. CloseFileMapping (pSMSNew);
  536. delete (pSMSNew);
  537. }
  538. if (ppoi)
  539. {
  540. delete ppoi;
  541. ppoi = NULL;
  542. }
  543. }
  544. return ppoi;
  545. }
  546. void PerfObjectDefinition::DeletePerfObjectInstance ()
  547. {
  548. EnterCriticalSection (&m_csPerfObjInst);
  549. m_dwActiveInstances--;
  550. m_pPerfObjectType->NumInstances--;
  551. LeaveCriticalSection (&m_csPerfObjInst);
  552. }
  553. ///////////////////////////////////////////////////////////////////////////////
  554. //
  555. // PerfCounterDefinition class declaration. There is one of these per counter.
  556. //
  557. ///////////////////////////////////////////////////////////////////////////////
  558. PerfCounterDefinition::PerfCounterDefinition (DWORD dwCounterNameIndex,
  559. DWORD dwCounterType,
  560. LONG lDefaultScale) :
  561. m_pCtrRef (NULL),
  562. m_dwCounterNameIndex (dwCounterNameIndex),
  563. m_lDefaultScale (lDefaultScale),
  564. m_dwCounterType (dwCounterType)
  565. {
  566. if (m_dwCounterType & PERF_SIZE_LARGE)
  567. m_dwCounterSize = sizeof (LARGE_INTEGER);
  568. else
  569. m_dwCounterSize = sizeof (DWORD);
  570. }
  571. PerfCounterDefinition::PerfCounterDefinition (PerfCounterDefinition* pCtrRef,
  572. DWORD dwCounterNameIndex,
  573. DWORD dwCounterType,
  574. LONG lDefaultScale) :
  575. m_pCtrRef (pCtrRef),
  576. m_dwCounterNameIndex (dwCounterNameIndex),
  577. m_lDefaultScale (lDefaultScale),
  578. m_dwCounterType (dwCounterType),
  579. m_dwCounterSize (0)
  580. {
  581. }
  582. void
  583. PerfCounterDefinition::Init (PerfLibrary* pPerfLib,
  584. PERF_COUNTER_DEFINITION* pdef, PDWORD pdwOffset)
  585. {
  586. pdef->ByteLength = sizeof (PERF_COUNTER_DEFINITION);
  587. pdef->CounterNameTitleIndex = m_dwCounterNameIndex +
  588. pPerfLib->m_dwFirstCounter ;
  589. pdef->CounterNameTitle = 0;
  590. pdef->CounterHelpTitleIndex = m_dwCounterNameIndex +
  591. pPerfLib->m_dwFirstHelp ;
  592. pdef->CounterHelpTitle = 0;
  593. pdef->DefaultScale = m_lDefaultScale;
  594. pdef->DetailLevel = PERF_DETAIL_NOVICE;
  595. pdef->CounterType = m_dwCounterType;
  596. if (m_pCtrRef)
  597. {
  598. //
  599. // This counter uses the data of another counter.
  600. //
  601. pdef->CounterSize = m_pCtrRef->m_dwCounterSize;
  602. pdef->CounterOffset = m_pCtrRef->m_dwOffset;
  603. }
  604. else
  605. {
  606. //
  607. // This counter has its own data.
  608. //
  609. pdef->CounterSize = m_dwCounterSize;
  610. pdef->CounterOffset = *pdwOffset;
  611. // Save offset
  612. m_dwOffset = *pdwOffset;
  613. // Increment offset for next counter definition
  614. *pdwOffset += m_dwCounterSize;
  615. }
  616. }
  617. ///////////////////////////////////////////////////////////////////////////////
  618. //
  619. // PerfObjectInstance class implementation. There is one of these per instance
  620. // of an object. There is one if there are no instances (the global instance.)
  621. //
  622. ///////////////////////////////////////////////////////////////////////////////
  623. PerfObjectInstance::PerfObjectInstance (PerfObjectDefinition* pObjDef,
  624. LPCWSTR pcwstrInstanceName)
  625. {
  626. m_pObjDef = pObjDef;
  627. if (pcwstrInstanceName)
  628. {
  629. wcsncpy (m_wszInstanceName, pcwstrInstanceName, MAX_INSTANCE_NAME);
  630. m_wszInstanceName[MAX_INSTANCE_NAME-1] = L'\0'; // Ensure NULL termination!
  631. }
  632. else
  633. *m_wszInstanceName = L'\0';
  634. m_fInitialized = FALSE;
  635. }
  636. void
  637. PerfObjectInstance::Init (char* pCounterData, INSTANCE_DATA* pInstData, LONG lID)
  638. {
  639. int cchNameLength = 0;
  640. m_pCounterData = pCounterData;
  641. m_pInstanceData = pInstData;
  642. // Clear all the counter data
  643. ZeroMemory( m_pCounterData, m_pObjDef->m_dwCounterData );
  644. // Set the counter block length
  645. ((PERF_COUNTER_BLOCK*)m_pCounterData)->ByteLength =
  646. m_pObjDef->m_dwCounterData;
  647. if (m_pInstanceData)
  648. {
  649. m_pInstanceData->perfInstDef.ByteLength = sizeof (PERF_INSTANCE_DEFINITION);
  650. m_pInstanceData->perfInstDef.ParentObjectTitleIndex = 0;
  651. m_pInstanceData->perfInstDef.ParentObjectInstance = 0;
  652. m_pInstanceData->perfInstDef.UniqueID = PERF_NO_UNIQUE_ID;
  653. m_pInstanceData->perfInstDef.NameOffset =
  654. sizeof (PERF_INSTANCE_DEFINITION);
  655. //
  656. // The instance-name is copied to wszInstanceName. This is a variable
  657. // length NULL terminated unicode string. wszInstanceName must end on
  658. // a 32-bit boundary, so that the perf-data that follows this string
  659. // is 32-bit aligned. Therefore, if wszInstance contains an odd number
  660. // of WCHARS, we add an extra WCHAR to 32-bit align it. The length of
  661. // the instance name in bytes, including the terminating NULL and the
  662. // padding byte (if present) is written to perfInstDef.NameLength.
  663. //
  664. cchNameLength = wcslen(m_wszInstanceName) + 1;
  665. if(cchNameLength > MAX_INSTANCE_NAME)
  666. {
  667. // MAX_INSTANCE_NAME is already 32 bit aligned
  668. _ASSERT(0 == (MAX_INSTANCE_NAME & 1));
  669. cchNameLength = MAX_INSTANCE_NAME;
  670. }
  671. else if(cchNameLength & 1)
  672. {
  673. cchNameLength++;
  674. }
  675. m_pInstanceData->perfInstDef.NameLength = cchNameLength * sizeof(WCHAR);
  676. m_pInstanceData->perfInstDef.ByteLength += cchNameLength * sizeof(WCHAR);
  677. CopyMemory(m_pInstanceData->wszInstanceName, m_wszInstanceName,
  678. cchNameLength * sizeof(WCHAR));
  679. // If the name got truncated, there may not have been a terminating NULL
  680. m_pInstanceData->wszInstanceName[MAX_INSTANCE_NAME - 1] = L'\0';
  681. m_pInstanceData->fActive = TRUE;
  682. }
  683. m_fInitialized = TRUE;
  684. }
  685. VOID
  686. PerfObjectInstance::DeInit (void)
  687. {
  688. if (m_fInitialized)
  689. {
  690. m_fInitialized = FALSE;
  691. if (m_pInstanceData)
  692. {
  693. m_pInstanceData->fActive = FALSE;
  694. m_pInstanceData = NULL;
  695. }
  696. }
  697. m_pObjDef->DeletePerfObjectInstance();
  698. }
  699. DWORD* PerfObjectInstance::GetDwordCounter (DWORD dwId)
  700. {
  701. DWORD dwOffset;
  702. if (m_fInitialized)
  703. {
  704. if (dwOffset = m_pObjDef->GetCounterOffset(dwId))
  705. return (DWORD*) (m_pCounterData + dwOffset);
  706. }
  707. return 0;
  708. }
  709. LARGE_INTEGER* PerfObjectInstance::GetLargeIntegerCounter (DWORD dwId)
  710. {
  711. DWORD dwOffset;
  712. if (m_fInitialized)
  713. {
  714. if (dwOffset = m_pObjDef->GetCounterOffset(dwId))
  715. return (LARGE_INTEGER*) (m_pCounterData + dwOffset);
  716. }
  717. return 0;
  718. }
  719. QWORD* PerfObjectInstance::GetQwordCounter (DWORD dwId)
  720. {
  721. DWORD dwOffset;
  722. if (m_fInitialized)
  723. {
  724. if (dwOffset = m_pObjDef->GetCounterOffset(dwId))
  725. return (QWORD*) (m_pCounterData + dwOffset);
  726. }
  727. return 0;
  728. }
  729. //---------------------------------------------------------------------------
  730. // Description:
  731. // Allocates and returns a SECURITY_DESCRIPTOR structure initialized to
  732. // allow all users access. This security descriptor is used to set the
  733. // security for the shared memory objects created by snprflib.
  734. // Arguments:
  735. // OUT pSd Pass in a pointer to SECURITY_DESCRIPTOR, on success this will
  736. // be set to a suitably initialized SECURITY_DESCRIPTOR. Caller frees
  737. // memory pointed to by pSd.
  738. // Returns:
  739. // ERROR_SUCCESS on success.
  740. // Win32 error to indicate failure.
  741. //---------------------------------------------------------------------------
  742. DWORD InitializeBasicSecurityDescriptor (PSECURITY_DESCRIPTOR *ppSd)
  743. {
  744. DWORD dwErr = ERROR_SUCCESS;
  745. PSID pSidWorld = NULL;
  746. PSID pSidCreator = NULL;
  747. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  748. SID_IDENTIFIER_AUTHORITY CreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  749. ACL *pAcl = NULL;
  750. DWORD dwAclSize = 0;
  751. *ppSd = NULL;
  752. if (!AllocateAndInitializeSid (
  753. &WorldAuthority,
  754. 1,
  755. SECURITY_WORLD_RID,
  756. 0,0,0,0,0,0,0,
  757. &pSidWorld)){
  758. dwErr = GetLastError ();
  759. goto Exit;
  760. }
  761. if (!AllocateAndInitializeSid (
  762. &CreatorAuthority,
  763. 1,
  764. SECURITY_CREATOR_OWNER_RID,
  765. 0,0,0,0,0,0,0,
  766. &pSidCreator)){
  767. dwErr = GetLastError ();
  768. goto Exit;
  769. }
  770. dwAclSize = sizeof (ACL) +
  771. (sizeof (ACCESS_ALLOWED_ACE) - sizeof (LONG)) +
  772. GetLengthSid (pSidWorld) +
  773. (sizeof (ACCESS_ALLOWED_ACE) - sizeof (LONG)) +
  774. GetLengthSid (pSidCreator);
  775. //
  776. // Allocate SD and ACL with a single alloc
  777. //
  778. *ppSd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize];
  779. if (!*ppSd) {
  780. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  781. goto Exit;
  782. }
  783. if (!InitializeSecurityDescriptor (*ppSd, SECURITY_DESCRIPTOR_REVISION)) {
  784. dwErr = GetLastError ();
  785. goto Exit;
  786. }
  787. pAcl = (ACL *) ((BYTE *) *ppSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  788. if (!InitializeAcl (
  789. pAcl,
  790. dwAclSize,
  791. ACL_REVISION)) {
  792. dwErr = GetLastError ();
  793. goto Exit;
  794. }
  795. if (!AddAccessAllowedAce (
  796. pAcl,
  797. ACL_REVISION,
  798. GENERIC_WRITE,
  799. pSidCreator)
  800. ||
  801. !AddAccessAllowedAce (
  802. pAcl,
  803. ACL_REVISION,
  804. GENERIC_READ,
  805. pSidWorld)) {
  806. dwErr = GetLastError ();
  807. goto Exit;
  808. }
  809. if (!SetSecurityDescriptorDacl (*ppSd, TRUE, pAcl, FALSE))
  810. dwErr = GetLastError ();
  811. Exit:
  812. if (pSidWorld)
  813. FreeSid (pSidWorld);
  814. if (pSidCreator)
  815. FreeSid (pSidCreator);
  816. return dwErr;
  817. }
  818. ///////////////////////////////////////////////////////////////////////////////
  819. //
  820. // Shared memory management functions
  821. //
  822. ///////////////////////////////////////////////////////////////////////////////
  823. BOOL FCreateFileMapping (SharedMemorySegment * pSMS,
  824. LPCWSTR pcwstrInstanceName,
  825. DWORD dwIndex,
  826. DWORD cbSize)
  827. {
  828. WCHAR pwstrShMem[MAX_PATH];
  829. WCHAR pwstrIndex[MAX_PATH];
  830. PSECURITY_DESCRIPTOR pSd = NULL;
  831. SECURITY_ATTRIBUTES sa;
  832. HANDLE hMap = NULL;
  833. PVOID pvMap = NULL;
  834. BOOL fSuccess = FALSE;
  835. DWORD dwErr = ERROR_SUCCESS;
  836. //
  837. // Check parameter
  838. //
  839. if (!pSMS)
  840. goto Exit;
  841. pSMS->m_hMap = NULL;
  842. pSMS->m_pbMap = NULL;
  843. pSMS->m_pSMSNext = NULL;
  844. //
  845. // Append dwIndex to instance name.
  846. //
  847. _ultow (dwIndex, pwstrIndex, 16);
  848. if (wcslen (pcwstrInstanceName) + wcslen (pwstrIndex) >= MAX_PATH)
  849. goto Exit;
  850. wcscpy (pwstrShMem, pcwstrInstanceName);
  851. wcscat (pwstrShMem, pwstrIndex);
  852. dwErr = InitializeBasicSecurityDescriptor (&pSd);
  853. if (dwErr)
  854. goto Exit;
  855. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  856. sa.lpSecurityDescriptor = pSd;
  857. sa.bInheritHandle = TRUE;
  858. //
  859. // Create the shared memory object. If it already exists, abort!
  860. //
  861. hMap = CreateFileMappingW (INVALID_HANDLE_VALUE,
  862. &sa,
  863. PAGE_READWRITE,
  864. 0,
  865. cbSize,
  866. pwstrShMem);
  867. if (hMap == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
  868. goto Exit;
  869. //
  870. // Map the file into memory
  871. //
  872. pvMap = MapViewOfFile (hMap, FILE_MAP_WRITE, 0, 0, 0);
  873. if (!pvMap)
  874. goto Exit;
  875. ZeroMemory (pvMap, cbSize);
  876. //
  877. // Succeeds. Now store the results into pSMS.
  878. //
  879. pSMS->m_hMap = hMap;
  880. pSMS->m_pbMap = (BYTE *)pvMap;
  881. fSuccess = TRUE;
  882. Exit:
  883. if (!fSuccess)
  884. {
  885. if (pvMap)
  886. UnmapViewOfFile (pvMap);
  887. if (hMap)
  888. CloseHandle (hMap);
  889. }
  890. if (pSd)
  891. delete [] (BYTE *) pSd;
  892. return fSuccess;
  893. }
  894. void CloseFileMapping (SharedMemorySegment * pSMS)
  895. {
  896. if (pSMS)
  897. {
  898. if (pSMS->m_pbMap)
  899. {
  900. UnmapViewOfFile ((PVOID)pSMS->m_pbMap);
  901. pSMS->m_pbMap = NULL;
  902. }
  903. if (pSMS->m_hMap)
  904. {
  905. CloseHandle (pSMS->m_hMap);
  906. pSMS->m_hMap = NULL;
  907. }
  908. pSMS->m_pSMSNext = NULL;
  909. }
  910. }