Source code of Windows XP (NT5)
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.

1517 lines
43 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. perfdisk.c
  5. Abstract:
  6. Author:
  7. Bob Watson (a-robw) Aug 95
  8. Revision History:
  9. --*/
  10. // define the WMI Guids for this program
  11. #ifndef INITGUID
  12. #define INITGUID 1
  13. #endif
  14. //
  15. // Force everything to be UNICODE
  16. //
  17. #ifndef UNICODE
  18. #define UNICODE
  19. #endif
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include <ntexapi.h>
  24. #include <windows.h>
  25. #include <ole2.h>
  26. #pragma warning ( disable : 4201 )
  27. #include <wmium.h>
  28. #pragma warning ( default : 4201 )
  29. #include <wmiguid.h>
  30. #include <winperf.h>
  31. #if DBG
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #endif
  35. #include <ntprfctr.h>
  36. #include <perfutil.h>
  37. #include <assert.h>
  38. #include "perfdisk.h"
  39. #include "diskmsg.h"
  40. // define this symbol to test if diskperf has installed itself
  41. // as an upper filter
  42. // if this symbol is undefined, then check for diskperf before
  43. // returning any logical disk counters
  44. #define _DONT_CHECK_FOR_VOLUME_FILTER
  45. #ifndef _DONT_CHECK_FOR_VOLUME_FILTER
  46. #include <regstr.h> // for REGSTR_VAL_UPPERFILTERS
  47. #endif
  48. // bit field definitions for collect function flags
  49. #define POS_COLLECT_PDISK_DATA ((DWORD)0x00000001)
  50. #define POS_COLLECT_LDISK_DATA ((DWORD)0x00000003)
  51. #define POS_COLLECT_IGNORE ((DWORD)0x80000000)
  52. #define POS_COLLECT_GLOBAL_DATA ((DWORD)0x00000003)
  53. #define POS_COLLECT_FOREIGN_DATA ((DWORD)0)
  54. #define POS_COLLECT_COSTLY_DATA ((DWORD)0)
  55. // global variables to this DLL
  56. HANDLE ThisDLLHandle = NULL;
  57. HANDLE hEventLog = NULL;
  58. HANDLE hLibHeap = NULL;
  59. BOOL bShownDiskPerfMessage = FALSE;
  60. BOOL bShownDiskVolumeMessage = FALSE;
  61. LPWSTR wszTotal = NULL;
  62. const WCHAR cszNT4InstanceNames[] = {L"NT4 Instance Names"};
  63. const WCHAR cszRegKeyPath[] = {L"System\\CurrentControlSet\\Services\\PerfDisk\\Performance"};
  64. const WCHAR cszVolumeKey[] = {L"SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}"};
  65. const WCHAR cszRefreshInterval[] = {L"VolumeSpaceRefreshInterval"};
  66. #define DISKPERF_SERVICE_NAME L"DiskPerf"
  67. ULONG CheckVolumeFilter();
  68. PDRIVE_VOLUME_ENTRY pPhysDiskList = NULL;
  69. DWORD dwNumPhysDiskListEntries = 0;
  70. PDRIVE_VOLUME_ENTRY pVolumeList = NULL;
  71. DWORD dwNumVolumeListEntries = 0;
  72. DWORD dwWmiDriveCount = 0;
  73. BOOL bRemapDriveLetters = TRUE;
  74. DWORD dwMaxVolumeNumber = 0;
  75. // start off with a big buffer then size according to return values
  76. DWORD WmiBufSize = 0x10000; // this can be smaller when the Diskperf.sys
  77. DWORD WmiAllocSize = 0x10000; // function is fixed to return the right status
  78. LPBYTE WmiBuffer = NULL;
  79. // variables local to this module
  80. static POS_FUNCTION_INFO posDataFuncInfo[] = {
  81. {LOGICAL_DISK_OBJECT_TITLE_INDEX, POS_COLLECT_LDISK_DATA, 0, CollectLDiskObjectData},
  82. {PHYSICAL_DISK_OBJECT_TITLE_INDEX, POS_COLLECT_PDISK_DATA, 0, CollectPDiskObjectData}
  83. };
  84. #define POS_NUM_FUNCS (sizeof(posDataFuncInfo) / sizeof(posDataFuncInfo[1]))
  85. static bInitOk = FALSE;
  86. static DWORD dwOpenCount = 0;
  87. WMIHANDLE hWmiDiskPerf = NULL;
  88. PM_OPEN_PROC OpenDiskObject;
  89. PM_COLLECT_PROC CollecDiskObjectData;
  90. PM_CLOSE_PROC CloseDiskObject;
  91. DOUBLE dSysTickTo100Ns;
  92. #if DBG
  93. const WCHAR cszDebugPrintLevel[] = {L"DebugPrintLevel"};
  94. #define DEBUG_BUFFER_LENGTH MAX_PATH*2
  95. ULONG_PTR HeapUsed = 0;
  96. ULONG oldPLSize = 0;
  97. ULONG oldVLSize = 0;
  98. ULONG wszSize = 0;
  99. ULONG PerfDiskDebug = 0;
  100. UCHAR PerfDiskDebugBuffer[DEBUG_BUFFER_LENGTH];
  101. #endif
  102. BOOL
  103. WriteNewBootTimeEntry (
  104. LONGLONG *pBootTime
  105. )
  106. {
  107. LONG lStatus;
  108. HKEY hKeyPerfDiskPerf;
  109. DWORD dwType, dwSize;
  110. BOOL bReturn = FALSE;
  111. // try to read the registry value of the last time
  112. // this error was reported
  113. lStatus = RegOpenKeyExW (
  114. HKEY_LOCAL_MACHINE,
  115. cszRegKeyPath,
  116. (DWORD)0,
  117. KEY_WRITE,
  118. &hKeyPerfDiskPerf);
  119. if (lStatus == ERROR_SUCCESS) {
  120. // read the key value
  121. dwType = REG_BINARY;
  122. dwSize = sizeof (*pBootTime);
  123. lStatus = RegSetValueExW (
  124. hKeyPerfDiskPerf,
  125. (LPCWSTR)L"SystemStartTimeOfLastErrorMsg",
  126. 0L, // reserved
  127. dwType,
  128. (LPBYTE)pBootTime,
  129. dwSize);
  130. if (lStatus == ERROR_SUCCESS) {
  131. bReturn = TRUE;
  132. } else {
  133. // the value hasn't been written and
  134. SetLastError (lStatus);
  135. } // else assume the value hasn't been written and
  136. // return FALSE
  137. RegCloseKey (hKeyPerfDiskPerf);
  138. } else {
  139. // assume the value hasn't been written and
  140. SetLastError (lStatus);
  141. }
  142. return bReturn;
  143. }
  144. BOOL
  145. NT4NamesAreDefault ()
  146. {
  147. LONG lStatus;
  148. HKEY hKeyPerfDiskPerf;
  149. DWORD dwType, dwSize;
  150. DWORD dwValue;
  151. BOOL bReturn = FALSE;
  152. // try to read the registry value of the last time
  153. // this error was reported
  154. lStatus = RegOpenKeyExW (
  155. HKEY_LOCAL_MACHINE,
  156. cszRegKeyPath,
  157. (DWORD)0,
  158. KEY_READ,
  159. &hKeyPerfDiskPerf);
  160. if (lStatus == ERROR_SUCCESS) {
  161. // read the key value
  162. dwType = 0;
  163. dwSize = sizeof (dwValue);
  164. lStatus = RegQueryValueExW (
  165. hKeyPerfDiskPerf,
  166. cszNT4InstanceNames,
  167. 0L, // reserved
  168. &dwType,
  169. (LPBYTE)&dwValue,
  170. &dwSize);
  171. if ((lStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  172. if (dwValue != 0) {
  173. bReturn = TRUE;
  174. }
  175. } else {
  176. // the key is not present or not accessible so
  177. // leave default as is and
  178. // return FALSE
  179. }
  180. RegCloseKey (hKeyPerfDiskPerf);
  181. } else {
  182. // the key could not be opened.
  183. SetLastError (lStatus);
  184. }
  185. return bReturn;
  186. }
  187. BOOL
  188. SystemHasBeenRestartedSinceLastEntry (
  189. DWORD dwReserved, // just in case we want to have multiple tests in the future
  190. LONGLONG *pBootTime // a buffer to receive the current boot time
  191. )
  192. {
  193. BOOL bReturn = TRUE;
  194. NTSTATUS ntStatus = ERROR_SUCCESS;
  195. SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo;
  196. DWORD dwReturnedBufferSize = 0;
  197. HKEY hKeyPerfDiskPerf;
  198. LONG lStatus;
  199. DWORD dwType;
  200. DWORD dwSize;
  201. LONGLONG llLastErrorStartTime;
  202. DBG_UNREFERENCED_PARAMETER(dwReserved);
  203. // get the current system boot time (as a filetime)
  204. memset ((LPVOID)&SysTimeInfo, 0, sizeof(SysTimeInfo));
  205. ntStatus = NtQuerySystemInformation(
  206. SystemTimeOfDayInformation,
  207. &SysTimeInfo,
  208. sizeof(SysTimeInfo),
  209. &dwReturnedBufferSize
  210. );
  211. if (NT_SUCCESS(ntStatus)) {
  212. // try to read the registry value of the last time
  213. // this error was reported
  214. lStatus = RegOpenKeyExW (
  215. HKEY_LOCAL_MACHINE,
  216. cszRegKeyPath,
  217. (DWORD)0,
  218. KEY_READ,
  219. &hKeyPerfDiskPerf);
  220. if (lStatus == ERROR_SUCCESS) {
  221. // read the key value
  222. dwType = 0;
  223. dwSize = sizeof (llLastErrorStartTime);
  224. lStatus = RegQueryValueExW (
  225. hKeyPerfDiskPerf,
  226. (LPCWSTR)L"SystemStartTimeOfLastErrorMsg",
  227. 0L, // reserved
  228. &dwType,
  229. (LPBYTE)&llLastErrorStartTime,
  230. &dwSize);
  231. if (lStatus == ERROR_SUCCESS) {
  232. assert (dwType == REG_BINARY); // this should be a binary type
  233. assert (dwSize == sizeof (LONGLONG)); // and it should be 8 bytes long
  234. // compare times
  235. // if the times are the same, then this message has already been
  236. // written since the last boot so we don't need to do it again.
  237. if (SysTimeInfo.BootTime.QuadPart ==
  238. llLastErrorStartTime) {
  239. bReturn = FALSE;
  240. } // else they are the different times so return FALSE
  241. } // else assume the value hasn't been written and
  242. // return TRUE
  243. RegCloseKey (hKeyPerfDiskPerf);
  244. } // else assume the value hasn't been written and
  245. // return TRUE
  246. // return the boot time if a buffer was passed in
  247. if (pBootTime != NULL) {
  248. // save the time
  249. *pBootTime = SysTimeInfo.BootTime.QuadPart;
  250. }
  251. } // else assume that it has been rebooted and return TRUE
  252. return bReturn;
  253. }
  254. static
  255. BOOL
  256. DllProcessAttach (
  257. IN HANDLE DllHandle
  258. )
  259. /*++
  260. Description:
  261. perform any initialization function that apply to all object
  262. modules
  263. --*/
  264. {
  265. BOOL bReturn = TRUE;
  266. WCHAR wszTempBuffer[512];
  267. LONG lStatus;
  268. DWORD dwBufferSize;
  269. HKEY hKeyPerfDiskPerf;
  270. LARGE_INTEGER liSysTick;
  271. UNREFERENCED_PARAMETER(DllHandle);
  272. // create heap for this library
  273. if (hLibHeap == NULL) hLibHeap = HeapCreate (0, 1, 0);
  274. assert (hLibHeap != NULL);
  275. if (hLibHeap == NULL) {
  276. return FALSE;
  277. }
  278. // open handle to the event log
  279. if (hEventLog == NULL) hEventLog = MonOpenEventLog((LPWSTR)L"PerfDisk");
  280. assert (hEventLog != NULL);
  281. lStatus = GetPerflibKeyValue (
  282. szTotalValue,
  283. REG_SZ,
  284. sizeof(wszTempBuffer),
  285. (LPVOID)&wszTempBuffer[0],
  286. DEFAULT_TOTAL_STRING_LEN,
  287. (LPVOID)&szDefaultTotalString[0]);
  288. if (lStatus == ERROR_SUCCESS) {
  289. // then a string was returned in the temp buffer
  290. dwBufferSize = lstrlenW (wszTempBuffer) + 1;
  291. dwBufferSize *= sizeof (WCHAR);
  292. wszTotal = ALLOCMEM (hLibHeap, HEAP_ZERO_MEMORY, dwBufferSize);
  293. if (wszTotal == NULL) {
  294. // unable to allocate buffer so use static buffer
  295. wszTotal = (LPWSTR)&szDefaultTotalString[0];
  296. } else {
  297. memcpy (wszTotal, wszTempBuffer, dwBufferSize);
  298. #if DBG
  299. HeapUsed += dwBufferSize;
  300. wszSize = dwBufferSize;
  301. DebugPrint((4,
  302. "DllAttach: wszTotal add %d to %d\n",
  303. dwBufferSize, HeapUsed));
  304. #endif
  305. }
  306. } else {
  307. // unable to get string from registry so just use static buffer
  308. wszTotal = (LPWSTR)&szDefaultTotalString[0];
  309. }
  310. QueryPerformanceFrequency (&liSysTick);
  311. dSysTickTo100Ns = (DOUBLE)liSysTick.QuadPart;
  312. dSysTickTo100Ns /= 10000000.0;
  313. lStatus = RegOpenKeyExW (
  314. HKEY_LOCAL_MACHINE,
  315. cszRegKeyPath,
  316. (DWORD)0,
  317. KEY_READ,
  318. &hKeyPerfDiskPerf);
  319. if (lStatus == ERROR_SUCCESS) {
  320. DWORD dwType = REG_DWORD;
  321. DWORD dwSize = sizeof(DWORD);
  322. ULONG interval;
  323. lStatus = RegQueryValueExW (
  324. hKeyPerfDiskPerf,
  325. cszRefreshInterval,
  326. 0L, // reserved
  327. &dwType,
  328. (LPBYTE)&interval,
  329. &dwSize);
  330. if ((lStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  331. g_lRefreshInterval = interval;
  332. }
  333. #if DBG
  334. dwSize = sizeof(DWORD);
  335. dwType = REG_DWORD;
  336. lStatus = RegQueryValueExW (
  337. hKeyPerfDiskPerf,
  338. cszDebugPrintLevel,
  339. 0L,
  340. &dwType,
  341. (LPBYTE) &interval,
  342. &dwSize);
  343. if ((lStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  344. PerfDiskDebug = interval;
  345. }
  346. #endif
  347. RegCloseKey (hKeyPerfDiskPerf);
  348. }
  349. return bReturn;
  350. }
  351. static
  352. BOOL
  353. DllProcessDetach (
  354. IN HANDLE DllHandle
  355. )
  356. {
  357. UNREFERENCED_PARAMETER(DllHandle);
  358. if (dwOpenCount > 0) {
  359. // then close the object now, since the DLL's being discarded
  360. // prematurely, this is our last chance.
  361. // this is to insure the object is closed.
  362. dwOpenCount = 1;
  363. CloseDiskObject();
  364. }
  365. if ((wszTotal != NULL) && (wszTotal != &szDefaultTotalString[0])) {
  366. FREEMEM (hLibHeap, 0, wszTotal);
  367. #if DBG
  368. HeapUsed -= wszSize;
  369. DebugPrint((4,
  370. "DllDetach: wsz freed %d to %d\n",
  371. wszSize, HeapUsed));
  372. wszSize = 0;
  373. #endif
  374. wszTotal = NULL;
  375. }
  376. if (HeapDestroy (hLibHeap)) {
  377. hLibHeap = NULL;
  378. pVolumeList = NULL;
  379. pPhysDiskList = NULL;
  380. dwNumVolumeListEntries = 0;
  381. dwNumPhysDiskListEntries = 0;
  382. }
  383. if (hEventLog != NULL) {
  384. MonCloseEventLog ();
  385. }
  386. return TRUE;
  387. }
  388. BOOL
  389. __stdcall
  390. DllInit(
  391. IN HANDLE DLLHandle,
  392. IN DWORD Reason,
  393. IN LPVOID ReservedAndUnused
  394. )
  395. {
  396. ReservedAndUnused;
  397. // this will prevent the DLL from getting
  398. // the DLL_THREAD_* messages
  399. DisableThreadLibraryCalls (DLLHandle);
  400. switch(Reason) {
  401. case DLL_PROCESS_ATTACH:
  402. return DllProcessAttach (DLLHandle);
  403. case DLL_PROCESS_DETACH:
  404. return DllProcessDetach (DLLHandle);
  405. case DLL_THREAD_ATTACH:
  406. case DLL_THREAD_DETACH:
  407. default:
  408. return TRUE;
  409. }
  410. }
  411. DWORD APIENTRY
  412. MapDriveLetters()
  413. {
  414. DWORD status = ERROR_SUCCESS;
  415. DWORD dwLoopCount;
  416. PDRIVE_VOLUME_ENTRY pTempPtr;
  417. DWORD dwDriveCount;
  418. DWORD dwThisEntry;
  419. PVOID pOldBuffer;
  420. #if DBG
  421. LONG64 startTime, endTime;
  422. LONG elapsed;
  423. #endif
  424. if (pPhysDiskList != NULL) {
  425. FREEMEM (hLibHeap, 0, pPhysDiskList);
  426. #if DBG
  427. HeapUsed -= oldPLSize;
  428. DebugPrint((4,"MapDriveLetters: PL Freed %d to %d\n",
  429. oldPLSize, HeapUsed));
  430. oldPLSize = 0;
  431. #endif
  432. pPhysDiskList = NULL;
  433. }
  434. #ifdef DBG
  435. GetSystemTimeAsFileTime((LPFILETIME) &startTime);
  436. DebugPrint((1, "BEGIN MapDriveLetters:\n",
  437. status));
  438. #endif
  439. dwNumPhysDiskListEntries = INITIAL_NUM_VOL_LIST_ENTRIES;
  440. // Initially allocate enough entries for drives A through Z
  441. pPhysDiskList = (PDRIVE_VOLUME_ENTRY)ALLOCMEM (
  442. hLibHeap, HEAP_ZERO_MEMORY,
  443. (dwNumPhysDiskListEntries * sizeof (DRIVE_VOLUME_ENTRY)));
  444. #if DBG
  445. if (pPhysDiskList == NULL) {
  446. DebugPrint((2,
  447. "MapDriveLetters: pPhysDiskList alloc failure\n"));
  448. }
  449. #endif
  450. if (pPhysDiskList != NULL) {
  451. // try until we get a big enough buffer
  452. #if DBG
  453. ULONG oldsize = dwNumPhysDiskListEntries * sizeof(DRIVE_VOLUME_ENTRY);
  454. HeapUsed += oldsize;
  455. oldPLSize = oldsize;
  456. DebugPrint((4, "MapDriveLetter: Alloc %d to %d\n",
  457. oldsize, HeapUsed));
  458. #endif
  459. dwLoopCount = 10; // no more than 10 retries to get the right size
  460. while ((status = BuildPhysDiskList (
  461. hWmiDiskPerf,
  462. pPhysDiskList,
  463. &dwNumPhysDiskListEntries)) == ERROR_INSUFFICIENT_BUFFER) {
  464. DebugPrint ((3,
  465. "MapDriveLetters: BuildPhysDiskList returns: %d, requesting %d entries\n",
  466. status, dwNumPhysDiskListEntries));
  467. #if DBG
  468. if (!HeapValidate(hLibHeap, 0, pPhysDiskList)) {
  469. DebugPrint((2,
  470. "\tERROR! pPhysDiskList %X corrupted BuildPhysDiskList\n",
  471. pPhysDiskList));
  472. DbgBreakPoint();
  473. }
  474. #endif
  475. // if ERROR_INSUFFICIENT_BUFFER, then
  476. // dwNumPhysDiskListEntries should contain the required size
  477. pOldBuffer = pPhysDiskList;
  478. pPhysDiskList = (PDRIVE_VOLUME_ENTRY)REALLOCMEM (
  479. hLibHeap, HEAP_ZERO_MEMORY,
  480. pPhysDiskList, (dwNumPhysDiskListEntries * sizeof (DRIVE_VOLUME_ENTRY)));
  481. if (pPhysDiskList == NULL) {
  482. // bail if the allocation failed
  483. DebugPrint((2,
  484. "MapDriveLetters: pPhysDiskList realloc failure\n"));
  485. status = ERROR_OUTOFMEMORY;
  486. FREEMEM(hLibHeap, 0, pOldBuffer);
  487. break;
  488. }
  489. #if DBG
  490. else {
  491. HeapUsed -= oldsize; // subtract the old size and add new size
  492. oldPLSize = dwNumPhysDiskListEntries*sizeof(DRIVE_VOLUME_ENTRY);
  493. HeapUsed += oldPLSize;
  494. DebugPrint((4,
  495. "MapDriveLetter: Realloc old %d new %d to %d\n",
  496. oldsize, oldPLSize, HeapUsed));
  497. }
  498. #endif
  499. dwLoopCount--;
  500. if (!dwLoopCount) {
  501. status = ERROR_OUTOFMEMORY;
  502. break;
  503. }
  504. DebugPrint ((3,
  505. "MapDriveLetters: %d retrying BuildPhysDiskList with %d entries\n",
  506. status, dwNumPhysDiskListEntries));
  507. }
  508. }
  509. else { // do not bother going any further if no memory
  510. return ERROR_OUTOFMEMORY;
  511. }
  512. DebugPrint ((4,
  513. "MapDriveLetters: BuildPhysDiskList returns: %d\n", status));
  514. #if DBG
  515. if (pPhysDiskList != NULL) {
  516. if (!HeapValidate(hLibHeap, 0, pPhysDiskList)) {
  517. DebugPrint((2, "\tERROR! pPhysDiskList %X corrupted after Builds\n",
  518. pPhysDiskList));
  519. DbgBreakPoint();
  520. }
  521. }
  522. #endif
  523. if (pVolumeList != NULL) {
  524. // close any open handles
  525. dwThisEntry = dwNumVolumeListEntries;
  526. while (dwThisEntry != 0) {
  527. dwThisEntry--;
  528. if (pVolumeList[dwThisEntry].hVolume != NULL) {
  529. NtClose (pVolumeList[dwThisEntry].hVolume);
  530. }
  531. }
  532. #if DBG
  533. HeapUsed -= oldVLSize;
  534. DebugPrint((4,"MapDriveLetters: VL Freed %d to %d\n",
  535. oldVLSize, HeapUsed));
  536. oldVLSize = 0;
  537. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  538. DebugPrint((2, "\tERROR! pVolumeList %X is corrupted before free\n",
  539. pVolumeList));
  540. DbgBreakPoint();
  541. }
  542. #endif
  543. FREEMEM (hLibHeap, 0, pVolumeList);
  544. pVolumeList = NULL;
  545. }
  546. dwNumVolumeListEntries = INITIAL_NUM_VOL_LIST_ENTRIES;
  547. // Initially allocate enough entries for letters C through Z
  548. pVolumeList = (PDRIVE_VOLUME_ENTRY)ALLOCMEM (
  549. hLibHeap, HEAP_ZERO_MEMORY,
  550. (dwNumVolumeListEntries * sizeof (DRIVE_VOLUME_ENTRY)));
  551. #if DBG
  552. if (pVolumeList == NULL) {
  553. DebugPrint((2,
  554. "MapDriveLetters: pPhysVolumeList alloc failure\n"));
  555. }
  556. #endif
  557. if (pVolumeList != NULL) {
  558. // try until we get a big enough buffer
  559. #if DBG
  560. ULONG oldsize = dwNumVolumeListEntries * sizeof (DRIVE_VOLUME_ENTRY);
  561. HeapUsed += oldsize;
  562. oldVLSize = oldsize;
  563. DebugPrint((4,
  564. "MapDriveLetter: Add %d HeapUsed %d\n", oldsize, HeapUsed));
  565. #endif
  566. dwLoopCount = 10; // no more than 10 retries to get the right size
  567. while ((status = BuildVolumeList (
  568. pVolumeList,
  569. &dwNumVolumeListEntries)) == ERROR_INSUFFICIENT_BUFFER) {
  570. // if ERROR_INSUFFICIENT_BUFFER, then
  571. DebugPrint ((3,
  572. "MapDriveLetters: BuildVolumeList returns: %d, requesting %d entries\n",
  573. status, dwNumVolumeListEntries));
  574. #if DBG
  575. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  576. DebugPrint((2, "\tERROR! pVolumeList %X corrupted in while\n",
  577. pVolumeList));
  578. DbgBreakPoint();
  579. }
  580. #endif
  581. // dwNumVolumeListEntries should contain the required size
  582. pOldBuffer = pVolumeList;
  583. pVolumeList = (PDRIVE_VOLUME_ENTRY)REALLOCMEM (
  584. hLibHeap, HEAP_ZERO_MEMORY,
  585. pVolumeList, (dwNumVolumeListEntries * sizeof (DRIVE_VOLUME_ENTRY)));
  586. if (pVolumeList == NULL) {
  587. // bail if the allocation failed
  588. DebugPrint((2,
  589. "MapDriveLetters: pPhysVolumeList realloc failure\n"));
  590. status = ERROR_OUTOFMEMORY;
  591. FREEMEM(hLibHeap, 0, pOldBuffer);
  592. break;
  593. }
  594. #if DBG
  595. else {
  596. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  597. DebugPrint((2, "\tpVolumeList %X corrupted - realloc\n",
  598. pVolumeList));
  599. DbgBreakPoint();
  600. }
  601. HeapUsed -= oldsize; // subtract the old size and add new size
  602. oldVLSize = dwNumVolumeListEntries*sizeof(DRIVE_VOLUME_ENTRY);
  603. HeapUsed += oldVLSize;
  604. DebugPrint((4,
  605. "MapDriveLetter: Realloc old %d new %d to %d\n",
  606. oldsize, oldVLSize, HeapUsed));
  607. }
  608. #endif
  609. dwLoopCount--;
  610. if (!dwLoopCount) {
  611. status = ERROR_OUTOFMEMORY;
  612. break;
  613. }
  614. DebugPrint ((3,
  615. "MapDriveLetters: retrying BuildVolumeList with %d entries\n",
  616. status, dwNumVolumeListEntries));
  617. }
  618. DebugPrint ((4, "MapDriveLetters: BuildVolumeList returns %d\n", status));
  619. #if DBG
  620. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  621. DebugPrint((2, "\tpVolumeList %X corrupted after build\n",
  622. pVolumeList));
  623. DbgBreakPoint();
  624. }
  625. #endif
  626. if (status == ERROR_SUCCESS) {
  627. status = FindNewVolumes(
  628. &pPhysDiskList,
  629. &dwNumPhysDiskListEntries,
  630. pVolumeList,
  631. dwNumVolumeListEntries);
  632. }
  633. // now map the disks to their drive letters
  634. if (status == ERROR_SUCCESS) {
  635. status = MapLoadedDisks (
  636. hWmiDiskPerf,
  637. pVolumeList,
  638. &dwNumVolumeListEntries,
  639. &dwMaxVolumeNumber,
  640. &dwWmiDriveCount
  641. );
  642. DebugPrint ((4,
  643. "MapDriveLetters: MapLoadedDisks returns status %d %d MaxVol %d WmiDrive\n",
  644. status, dwNumVolumeListEntries,
  645. dwMaxVolumeNumber, dwWmiDriveCount));
  646. }
  647. #if DBG
  648. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  649. DebugPrint((2, "\tpVolumeList %X corrupted by MapLoadedDisks\n",
  650. pVolumeList));
  651. DbgBreakPoint();
  652. }
  653. #endif
  654. if (status == ERROR_SUCCESS) {
  655. // now assign drive letters to the phys disk list
  656. dwDriveCount = 0;
  657. status = MakePhysDiskInstanceNames (
  658. pPhysDiskList,
  659. dwNumPhysDiskListEntries,
  660. &dwDriveCount,
  661. pVolumeList,
  662. dwNumVolumeListEntries);
  663. #if DBG
  664. if (!HeapValidate(hLibHeap, 0, pPhysDiskList)) {
  665. DebugPrint((2, "\tpPhysList %X corrupted by MakePhysDiskInst\n",
  666. pPhysDiskList));
  667. DbgBreakPoint();
  668. }
  669. #endif
  670. if (status == ERROR_SUCCESS) {
  671. // then compress this into an indexed table
  672. // save original pointer
  673. pTempPtr = pPhysDiskList;
  674. // the function returns the last Drive ID
  675. // so we need to add 1 here to the count to include
  676. // the "0" drive
  677. dwDriveCount += 1;
  678. DebugPrint ((4, "\tDrive count now = %d\n",
  679. dwDriveCount));
  680. // and allocate just enough for the actual physical drives
  681. pPhysDiskList = (PDRIVE_VOLUME_ENTRY)ALLOCMEM (
  682. hLibHeap, HEAP_ZERO_MEMORY,
  683. (dwDriveCount * sizeof (DRIVE_VOLUME_ENTRY)));
  684. if (pPhysDiskList != NULL) {
  685. status = CompressPhysDiskTable (
  686. pTempPtr,
  687. dwNumPhysDiskListEntries,
  688. pPhysDiskList,
  689. dwDriveCount);
  690. #if DBG
  691. if (!HeapValidate(hLibHeap, 0, pPhysDiskList)) {
  692. DebugPrint((2, "\tpPhysList %X corrupted by CompressPhys\n",
  693. pPhysDiskList));
  694. DbgBreakPoint();
  695. }
  696. #endif
  697. if (status == ERROR_SUCCESS) {
  698. dwNumPhysDiskListEntries = dwDriveCount;
  699. }
  700. else { // free if cannot compress
  701. FREEMEM(hLibHeap, 0, pPhysDiskList);
  702. #if DBG
  703. HeapUsed -= dwDriveCount * sizeof(DRIVE_VOLUME_ENTRY);
  704. DebugPrint((4,
  705. "MapDriveLetters: Compress freed %d to %d\n",
  706. dwDriveCount*sizeof(DRIVE_VOLUME_ENTRY), HeapUsed));
  707. #endif
  708. pPhysDiskList = NULL;
  709. }
  710. } else {
  711. DebugPrint((2,"MapDriveLetters: pPhysDiskList alloc fail for compress\n"));
  712. status = ERROR_OUTOFMEMORY;
  713. }
  714. if (pTempPtr) { // Free the previous list
  715. FREEMEM(hLibHeap, 0, pTempPtr);
  716. #if DBG
  717. HeapUsed -= oldPLSize;
  718. DebugPrint((4,
  719. "MapDriveLetters: tempPtr freed %d to %d\n",
  720. oldPLSize, HeapUsed));
  721. oldPLSize = 0;
  722. #endif
  723. }
  724. #if DBG
  725. if (status == ERROR_SUCCESS) {
  726. oldPLSize = dwDriveCount * sizeof(DRIVE_VOLUME_ENTRY);
  727. HeapUsed += oldPLSize;
  728. DebugPrint((4,
  729. "MapDriveLetters: Compress add %d to %d\n",
  730. oldPLSize, HeapUsed));
  731. }
  732. #endif
  733. }
  734. }
  735. if (status == ERROR_SUCCESS) {
  736. // clear the remap flag
  737. bRemapDriveLetters = FALSE;
  738. }
  739. } else {
  740. status = ERROR_OUTOFMEMORY;
  741. }
  742. #if DBG
  743. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  744. elapsed = (LONG) ((endTime - startTime) / 10000);
  745. DebugPrint((1, "END MapDriveLetters: %d msec\n\n", elapsed));
  746. #endif
  747. // TODO: Need to keep track of different status for PhysDisk & Volumes
  748. // If Physdisk succeeds whereas Volume fails, need to log event
  749. // and try and continue with Physdisk counters
  750. // TODO Post W2K: Free stuff if status != ERROR_SUCCESS
  751. return status;
  752. }
  753. DWORD APIENTRY
  754. OpenDiskObject (
  755. LPWSTR lpDeviceNames
  756. )
  757. /*++
  758. Routine Description:
  759. This routine will initialize the data structures used to pass
  760. data back to the registry
  761. Arguments:
  762. Pointer to object ID of each device to be opened (PerfGen)
  763. Return Value:
  764. None.
  765. --*/
  766. {
  767. DWORD status = ERROR_SUCCESS;
  768. LONGLONG llLastBootTime;
  769. BOOL bWriteMessage;
  770. #if DBG
  771. LONG64 startTime, endTime;
  772. LONG elapsed;
  773. #endif
  774. UNREFERENCED_PARAMETER (lpDeviceNames);
  775. #ifdef DBG
  776. GetSystemTimeAsFileTime((LPFILETIME) &startTime);
  777. DebugPrint((1, "BEGIN OpenDiskObject:\n",
  778. status));
  779. #endif
  780. if (dwOpenCount == 0) {
  781. status = WmiOpenBlock (
  782. (GUID *)&DiskPerfGuid,
  783. GENERIC_READ,
  784. &hWmiDiskPerf);
  785. #if DBG
  786. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  787. elapsed = (LONG) ((endTime - startTime) / 10000);
  788. DebugPrint((3, "WmiOpenBlock returns: %d in %d msec after BEGIN\n",
  789. status, elapsed));
  790. #endif
  791. if (status == ERROR_SUCCESS) {
  792. // build drive map
  793. status = MapDriveLetters();
  794. DebugPrint((3,
  795. "OpenDiskObject: MapDriveLetters returns: %d\n", status));
  796. }
  797. // determine instance name format
  798. bUseNT4InstanceNames = NT4NamesAreDefault();
  799. #if DBG
  800. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  801. elapsed = (LONG) ((endTime - startTime) / 10000);
  802. DebugPrint((3,
  803. "OpenDiskObject: NT4Names - %d msec after BEGIN\n", status));
  804. #endif
  805. if (status == ERROR_SUCCESS) {
  806. bInitOk = TRUE;
  807. }
  808. }
  809. if (status != ERROR_SUCCESS) {
  810. // check to see if this is a WMI error and if so only
  811. // write the error once per boot cycle
  812. if (status == ERROR_WMI_GUID_NOT_FOUND) {
  813. bWriteMessage = SystemHasBeenRestartedSinceLastEntry (
  814. 0, &llLastBootTime);
  815. if (bWriteMessage) {
  816. // update registry time
  817. WriteNewBootTimeEntry (&llLastBootTime);
  818. ReportEvent (hEventLog,
  819. EVENTLOG_ERROR_TYPE,
  820. 0,
  821. PERFDISK_UNABLE_QUERY_DISKPERF_INFO,
  822. NULL,
  823. 0,
  824. sizeof(DWORD),
  825. NULL,
  826. (LPVOID)&status);
  827. } // else it's already been written
  828. } else {
  829. // always write other messages
  830. ReportEvent (hEventLog,
  831. EVENTLOG_ERROR_TYPE,
  832. 0,
  833. PERFDISK_UNABLE_OPEN,
  834. NULL,
  835. 0,
  836. sizeof(DWORD),
  837. NULL,
  838. (LPVOID)&status);
  839. }
  840. } else {
  841. dwOpenCount++;
  842. #ifndef _DONT_CHECK_FOR_VOLUME_FILTER
  843. if (!CheckVolumeFilter()) {
  844. posDataFuncInfo[0].dwCollectFunctionBit |= POS_COLLECT_IGNORE;
  845. }
  846. #if DBG
  847. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  848. elapsed = (LONG) ((endTime - startTime) / 10000);
  849. DebugPrint((3,
  850. "OpenDiskObject: CheckVolFilter - %d msec after BEGIN\n", status));
  851. #endif
  852. #endif
  853. }
  854. #if DBG
  855. if (status == ERROR_SUCCESS) {
  856. if (pPhysDiskList) {
  857. DebugPrint((4, "\t Validating pPhysDiskList %X at end Open\n",
  858. pPhysDiskList));
  859. if (!HeapValidate(hLibHeap, 0, pPhysDiskList)) {
  860. DebugPrint((2, "OpenDiskObject: PhysDiskList heap corrupt!\n"));
  861. DbgBreakPoint();
  862. }
  863. }
  864. if (pVolumeList) {
  865. DebugPrint((4, "\t Validating pVolumeList %X at end Open\n",
  866. pVolumeList));
  867. if (!HeapValidate(hLibHeap, 0, pVolumeList)) {
  868. DebugPrint((2, "OpenDiskObject: VolumeList heap corrupt!\n"));
  869. DbgBreakPoint();
  870. }
  871. }
  872. if (WmiBuffer) {
  873. DebugPrint((4, "\t Validating WmiBuffer %X at end Open\n",
  874. WmiBuffer));
  875. if (!HeapValidate(hLibHeap, 0, WmiBuffer)) {
  876. DebugPrint((2, "OpenDiskObject: WmiBuffer heap corrupt!\n"));
  877. DbgBreakPoint();
  878. }
  879. }
  880. }
  881. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  882. elapsed = (LONG) ((endTime - startTime) / 10000);
  883. DebugPrint((1, "END OpenDiskObject: %d msec\n\n", elapsed));
  884. #endif
  885. return status;
  886. }
  887. DWORD APIENTRY
  888. CollectDiskObjectData (
  889. IN LPWSTR lpValueName,
  890. IN OUT LPVOID *lppData,
  891. IN OUT LPDWORD lpcbTotalBytes,
  892. IN OUT LPDWORD lpNumObjectTypes
  893. )
  894. /*++
  895. Routine Description:
  896. This routine will return the data for the processor object
  897. Arguments:
  898. IN LPWSTR lpValueName
  899. pointer to a wide character string passed by registry.
  900. IN OUT LPVOID *lppData
  901. IN: pointer to the address of the buffer to receive the completed
  902. PerfDataBlock and subordinate structures. This routine will
  903. append its data to the buffer starting at the point referenced
  904. by *lppData.
  905. OUT: points to the first byte after the data structure added by this
  906. routine. This routine updated the value at lppdata after appending
  907. its data.
  908. IN OUT LPDWORD lpcbTotalBytes
  909. IN: the address of the DWORD that tells the size in bytes of the
  910. buffer referenced by the lppData argument
  911. OUT: the number of bytes added by this routine is writted to the
  912. DWORD pointed to by this argument
  913. IN OUT LPDWORD NumObjectTypes
  914. IN: the address of the DWORD to receive the number of objects added
  915. by this routine
  916. OUT: the number of objects added by this routine is writted to the
  917. DWORD pointed to by this argument
  918. Returns:
  919. 0 if successful, else Win 32 error code of failure
  920. --*/
  921. {
  922. LONG lReturn = ERROR_SUCCESS;
  923. NTSTATUS Status;
  924. // build bit mask of functions to call
  925. DWORD dwQueryType;
  926. DWORD FunctionCallMask = 0;
  927. DWORD FunctionIndex;
  928. DWORD dwNumObjectsFromFunction;
  929. DWORD dwOrigBuffSize;
  930. DWORD dwByteSize;
  931. #if DBG
  932. LONG64 startTime, endTime;
  933. LONG elapsed;
  934. GetSystemTimeAsFileTime((LPFILETIME) &startTime);
  935. DebugPrint((1, "BEGIN CollectDiskObject:\n"));
  936. #endif
  937. if (!bInitOk) {
  938. *lpcbTotalBytes = (DWORD) 0;
  939. *lpNumObjectTypes = (DWORD) 0;
  940. lReturn = ERROR_SUCCESS;
  941. bShownDiskPerfMessage = TRUE;
  942. goto COLLECT_BAIL_OUT;
  943. }
  944. dwQueryType = GetQueryType (lpValueName);
  945. switch (dwQueryType) {
  946. case QUERY_ITEMS:
  947. for (FunctionIndex = 0; FunctionIndex < POS_NUM_FUNCS; FunctionIndex++) {
  948. if (IsNumberInUnicodeList (
  949. posDataFuncInfo[FunctionIndex].dwObjectId, lpValueName)) {
  950. FunctionCallMask |=
  951. posDataFuncInfo[FunctionIndex].dwCollectFunctionBit;
  952. }
  953. }
  954. break;
  955. case QUERY_GLOBAL:
  956. FunctionCallMask = POS_COLLECT_GLOBAL_DATA;
  957. break;
  958. case QUERY_FOREIGN:
  959. FunctionCallMask = POS_COLLECT_FOREIGN_DATA;
  960. break;
  961. case QUERY_COSTLY:
  962. FunctionCallMask = POS_COLLECT_COSTLY_DATA;
  963. break;
  964. default:
  965. FunctionCallMask = POS_COLLECT_COSTLY_DATA;
  966. break;
  967. }
  968. // collect data
  969. // if either bit is set, collect data
  970. if (FunctionCallMask & POS_COLLECT_GLOBAL_DATA) {
  971. __try {
  972. // read the data from the diskperf driver
  973. // only one call at a time is permitted. This should be
  974. // throttled by the perflib, but just in case we'll test it
  975. assert (WmiBuffer == NULL);
  976. if (WmiBuffer != NULL) {
  977. ReportEvent (hEventLog,
  978. EVENTLOG_ERROR_TYPE,
  979. 0,
  980. PERFDISK_BUSY,
  981. NULL,
  982. 0,
  983. 0,
  984. NULL,
  985. NULL);
  986. *lpcbTotalBytes = (DWORD) 0;
  987. *lpNumObjectTypes = (DWORD) 0;
  988. lReturn = ERROR_SUCCESS;
  989. goto COLLECT_BAIL_OUT;
  990. } else {
  991. WmiBuffer = ALLOCMEM (hLibHeap, HEAP_ZERO_MEMORY, WmiAllocSize);
  992. #if DBG
  993. if (WmiBuffer != NULL) {
  994. HeapUsed += WmiAllocSize;
  995. DebugPrint((4,
  996. "CollecDiskObjectData: WmiBuffer added %d to %d\n",
  997. WmiAllocSize, HeapUsed));
  998. }
  999. #endif
  1000. }
  1001. // the buffer pointer should NOT be null if here
  1002. if ( WmiBuffer == NULL ) {
  1003. ReportEvent (hEventLog,
  1004. EVENTLOG_WARNING_TYPE,
  1005. 0,
  1006. PERFDISK_UNABLE_ALLOC_BUFFER,
  1007. NULL,
  1008. 0,
  1009. 0,
  1010. NULL,
  1011. NULL);
  1012. *lpcbTotalBytes = (DWORD) 0;
  1013. *lpNumObjectTypes = (DWORD) 0;
  1014. lReturn = ERROR_SUCCESS;
  1015. goto COLLECT_BAIL_OUT;
  1016. }
  1017. WmiBufSize = WmiAllocSize;
  1018. Status = WmiQueryAllDataW (
  1019. hWmiDiskPerf,
  1020. &WmiBufSize,
  1021. WmiBuffer);
  1022. // if buffer size attempted is too big or too small, resize
  1023. if ((WmiBufSize > 0) && (WmiBufSize != WmiAllocSize)) {
  1024. WmiBuffer = REALLOCMEM (hLibHeap,
  1025. HEAP_ZERO_MEMORY,
  1026. WmiBuffer, WmiBufSize);
  1027. if (WmiBuffer == NULL) {
  1028. // reallocation failed so bail out
  1029. Status = ERROR_OUTOFMEMORY;
  1030. } else {
  1031. // if the required buffer is larger than
  1032. // originally planned, bump it up some
  1033. #if DBG
  1034. HeapUsed += (WmiBufSize - WmiAllocSize);
  1035. DebugPrint((4,
  1036. "CollectDiskObjectData: Realloc old %d new %d to %d\n",
  1037. WmiAllocSize, WmiBufSize, HeapUsed));
  1038. #endif
  1039. if (WmiBufSize > WmiAllocSize) {
  1040. WmiAllocSize = WmiBufSize;
  1041. }
  1042. }
  1043. }
  1044. if (Status == ERROR_INSUFFICIENT_BUFFER) {
  1045. // if it didn't work because it was too small the first time
  1046. // try one more time
  1047. Status = WmiQueryAllDataW (
  1048. hWmiDiskPerf,
  1049. &WmiBufSize,
  1050. WmiBuffer);
  1051. } else {
  1052. // it either worked the fisrt time or it failed because of
  1053. // something other than a buffer size problem
  1054. }
  1055. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1056. DebugPrint((2, "\tWmiBuffer %X size %d set to NULL\n",
  1057. WmiBuffer, WmiAllocSize));
  1058. if (WmiBuffer != NULL) {
  1059. if (HeapValidate(hLibHeap, 0, WmiBuffer)) {
  1060. FREEMEM(hLibHeap, 0, WmiBuffer);
  1061. }
  1062. } // else we are really in trouble with WmiBuffer!!
  1063. WmiBuffer = NULL;
  1064. Status = ERROR_OUTOFMEMORY;
  1065. }
  1066. DebugPrint((3,
  1067. "WmiQueryAllData status return: %x Buffer %d bytes\n",
  1068. Status, WmiBufSize));
  1069. } else {
  1070. // no data required so these counter objects must not be in
  1071. // the query list
  1072. *lpcbTotalBytes = (DWORD) 0;
  1073. *lpNumObjectTypes = (DWORD) 0;
  1074. lReturn = ERROR_SUCCESS;
  1075. goto COLLECT_BAIL_OUT;
  1076. }
  1077. if (Status == ERROR_SUCCESS) {
  1078. *lpNumObjectTypes = 0;
  1079. dwOrigBuffSize = dwByteSize = *lpcbTotalBytes;
  1080. *lpcbTotalBytes = 0;
  1081. for (FunctionIndex = 0; FunctionIndex < POS_NUM_FUNCS; FunctionIndex++) {
  1082. if (posDataFuncInfo[FunctionIndex].dwCollectFunctionBit &
  1083. POS_COLLECT_IGNORE)
  1084. continue;
  1085. if (posDataFuncInfo[FunctionIndex].dwCollectFunctionBit &
  1086. FunctionCallMask) {
  1087. dwNumObjectsFromFunction = 0;
  1088. lReturn = (*posDataFuncInfo[FunctionIndex].pCollectFunction) (
  1089. lppData,
  1090. &dwByteSize,
  1091. &dwNumObjectsFromFunction);
  1092. if (lReturn == ERROR_SUCCESS) {
  1093. *lpNumObjectTypes += dwNumObjectsFromFunction;
  1094. *lpcbTotalBytes += dwByteSize;
  1095. dwOrigBuffSize -= dwByteSize;
  1096. dwByteSize = dwOrigBuffSize;
  1097. } else {
  1098. break;
  1099. }
  1100. }
  1101. #if DBG
  1102. dwQueryType = HeapValidate(hLibHeap, 0, WmiBuffer);
  1103. DebugPrint((4,
  1104. "CollectDiskObjectData: Index %d HeapValid %d lReturn %d\n",
  1105. FunctionIndex, dwQueryType, lReturn));
  1106. if (!dwQueryType)
  1107. DbgBreakPoint();
  1108. #endif
  1109. }
  1110. } else {
  1111. ReportEvent (hEventLog,
  1112. EVENTLOG_WARNING_TYPE,
  1113. 0,
  1114. PERFDISK_UNABLE_QUERY_DISKPERF_INFO,
  1115. NULL,
  1116. 0,
  1117. sizeof(DWORD),
  1118. NULL,
  1119. (LPVOID)&Status);
  1120. *lpcbTotalBytes = (DWORD) 0;
  1121. *lpNumObjectTypes = (DWORD) 0;
  1122. lReturn = ERROR_SUCCESS;
  1123. }
  1124. // *lppData is updated by each function
  1125. // *lpcbTotalBytes is updated after each successful function
  1126. // *lpNumObjects is updated after each successful function
  1127. COLLECT_BAIL_OUT:
  1128. if (WmiBuffer != NULL) {
  1129. FREEMEM (hLibHeap, 0, WmiBuffer);
  1130. #if DBG
  1131. HeapUsed -= WmiBufSize;
  1132. DebugPrint((4, "CollectDiskObjectData: Freed %d to %d\n",
  1133. WmiBufSize, HeapUsed));
  1134. #endif
  1135. WmiBuffer = NULL;
  1136. }
  1137. #if DBG
  1138. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  1139. elapsed = (LONG) ((endTime - startTime) / 10000);
  1140. DebugPrint((1, "END CollectDiskObject: %d msec\n\n", elapsed));
  1141. #endif
  1142. return lReturn;
  1143. }
  1144. DWORD APIENTRY
  1145. CloseDiskObject (
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. This routine closes the open handles to the Signal Gen counters.
  1150. Arguments:
  1151. None.
  1152. Return Value:
  1153. ERROR_SUCCESS
  1154. --*/
  1155. {
  1156. DWORD status = ERROR_SUCCESS;
  1157. DWORD dwThisEntry;
  1158. #if DBG
  1159. LONG64 startTime, endTime;
  1160. LONG elapsed;
  1161. GetSystemTimeAsFileTime((LPFILETIME) &startTime);
  1162. DebugPrint((1, "BEGIN CloseDiskObject:\n"));
  1163. #endif
  1164. if (--dwOpenCount == 0) {
  1165. if (pVolumeList != NULL) {
  1166. // close handles in volume list
  1167. dwThisEntry = dwNumVolumeListEntries;
  1168. while (dwThisEntry != 0) {
  1169. dwThisEntry--;
  1170. if (pVolumeList[dwThisEntry].hVolume != NULL) {
  1171. NtClose (pVolumeList[dwThisEntry].hVolume);
  1172. }
  1173. if (pVolumeList[dwThisEntry].DeviceName.Buffer) {
  1174. FREEMEM(hLibHeap, 0,
  1175. pVolumeList[dwThisEntry].DeviceName.Buffer);
  1176. }
  1177. }
  1178. FREEMEM (hLibHeap, 0, pVolumeList);
  1179. #if DBG
  1180. HeapUsed -= oldVLSize;
  1181. DebugPrint((4, "CloseDiskObject: Freed VL %d to %d\n",
  1182. oldVLSize, HeapUsed));
  1183. oldVLSize = 0;
  1184. #endif
  1185. pVolumeList = NULL;
  1186. dwNumVolumeListEntries = 0;
  1187. }
  1188. if (pPhysDiskList != NULL) {
  1189. FREEMEM (hLibHeap, 0, pPhysDiskList);
  1190. #if DBG
  1191. HeapUsed -= oldPLSize;
  1192. DebugPrint((4, "CloseDiskObject: Freed PL %d to %d\n",
  1193. oldVLSize, HeapUsed));
  1194. oldPLSize = 0;
  1195. #endif
  1196. pPhysDiskList = NULL;
  1197. dwNumPhysDiskListEntries = 0;
  1198. }
  1199. // close PDisk object
  1200. if (hWmiDiskPerf != NULL) {
  1201. status = WmiCloseBlock (hWmiDiskPerf);
  1202. hWmiDiskPerf = NULL;
  1203. }
  1204. }
  1205. #if DBG
  1206. GetSystemTimeAsFileTime((LPFILETIME) &endTime);
  1207. elapsed = (LONG) ((endTime - startTime) / 10000);
  1208. DebugPrint((1, "END CloseDiskObject %d msec\n\n", elapsed));
  1209. #endif
  1210. return status;
  1211. }
  1212. #ifndef _DONT_CHECK_FOR_VOLUME_FILTER
  1213. ULONG
  1214. CheckVolumeFilter(
  1215. )
  1216. /*++
  1217. Routine Description:
  1218. This routine checks to see if diskperf is set to be an upper filter
  1219. for Storage Volumes
  1220. Arguments:
  1221. None.
  1222. Return Value:
  1223. TRUE if there is a filter
  1224. --*/
  1225. {
  1226. WCHAR Buffer[MAX_PATH+1];
  1227. WCHAR *string = Buffer;
  1228. DWORD dwSize = sizeof(Buffer);
  1229. ULONG stringLength, diskperfLen, result, status;
  1230. HKEY hKey;
  1231. status = RegOpenKeyExW(
  1232. HKEY_LOCAL_MACHINE,
  1233. cszVolumeKey,
  1234. (DWORD) 0,
  1235. KEY_QUERY_VALUE,
  1236. &hKey
  1237. );
  1238. if (status != ERROR_SUCCESS) {
  1239. return FALSE;
  1240. }
  1241. status = RegQueryValueExW(
  1242. hKey,
  1243. (LPCWSTR)REGSTR_VAL_UPPERFILTERS,
  1244. NULL,
  1245. NULL,
  1246. (LPBYTE) Buffer,
  1247. &dwSize);
  1248. if (status != ERROR_SUCCESS) {
  1249. RegCloseKey(hKey);
  1250. return FALSE;
  1251. }
  1252. stringLength = wcslen(string);
  1253. diskperfLen = wcslen((LPCWSTR)DISKPERF_SERVICE_NAME);
  1254. result = FALSE;
  1255. while(stringLength != 0) {
  1256. if (diskperfLen == stringLength) {
  1257. if(_wcsicmp(string, (LPCWSTR)DISKPERF_SERVICE_NAME) == 0) {
  1258. result = TRUE;
  1259. break;
  1260. }
  1261. } else {
  1262. string += stringLength + 1;
  1263. stringLength = wcslen(string);
  1264. }
  1265. }
  1266. RegCloseKey(hKey);
  1267. return result;
  1268. }
  1269. #endif
  1270. #if DBG
  1271. VOID
  1272. PerfDiskDebugPrint(
  1273. ULONG DebugPrintLevel,
  1274. PCCHAR DebugMessage,
  1275. ...
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. Debug print for all PerfDisk
  1280. Arguments:
  1281. Debug print level between 0 and 3, with 3 being the most verbose.
  1282. Return Value:
  1283. None
  1284. --*/
  1285. {
  1286. va_list ap;
  1287. if ((DebugPrintLevel <= (PerfDiskDebug & 0x0000ffff)) ||
  1288. ((1 << (DebugPrintLevel + 15)) & PerfDiskDebug)) {
  1289. DbgPrint("%d:Perfdisk!", GetCurrentThreadId());
  1290. }
  1291. else
  1292. return;
  1293. va_start(ap, DebugMessage);
  1294. if ((DebugPrintLevel <= (PerfDiskDebug & 0x0000ffff)) ||
  1295. ((1 << (DebugPrintLevel + 15)) & PerfDiskDebug)) {
  1296. _vsnprintf((LPSTR)PerfDiskDebugBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap);
  1297. DbgPrint((LPSTR)PerfDiskDebugBuffer);
  1298. }
  1299. va_end(ap);
  1300. }
  1301. #endif