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.

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