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.

803 lines
22 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. tracehw.c
  5. Abstract:
  6. This routine dumps the hardware configuration of the machine to the
  7. logfile.
  8. Author:
  9. 04-Jul-2000 Melur Raghuraman
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h> // for ntutrl.h
  14. #include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
  15. #include <wtypes.h> // for LPGUID in wmium.h
  16. #include <mountmgr.h>
  17. #include <winioctl.h>
  18. #include <ntddvol.h>
  19. #include <ntddscsi.h>
  20. #include "wmiump.h"
  21. #include "evntrace.h"
  22. #include "traceump.h"
  23. #include "tracelib.h"
  24. #include "trcapi.h"
  25. #define DEFAULT_ALLOC_SIZE 4096
  26. #define COMPUTERNAME_ROOT \
  27. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
  28. #define CPU_ROOT \
  29. L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor"
  30. #define COMPUTERNAME_VALUE_NAME \
  31. L"ComputerName"
  32. #define NETWORKCARDS_ROOT \
  33. L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
  34. #define MHZ_VALUE_NAME \
  35. L"~MHz"
  36. #define NIC_VALUE_NAME \
  37. L"Description"
  38. NTSTATUS
  39. WmipRegOpenKey(
  40. IN LPWSTR lpKeyName,
  41. OUT PHANDLE KeyHandle
  42. )
  43. {
  44. OBJECT_ATTRIBUTES ObjectAttributes;
  45. UNICODE_STRING KeyName;
  46. RtlInitUnicodeString( &KeyName, lpKeyName );
  47. RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
  48. InitializeObjectAttributes(
  49. &ObjectAttributes,
  50. &KeyName,
  51. OBJ_CASE_INSENSITIVE,
  52. NULL,
  53. NULL
  54. );
  55. return NtOpenKey( KeyHandle, KEY_READ, &ObjectAttributes );
  56. }
  57. NTSTATUS
  58. WmipRegQueryValueKey(
  59. IN HANDLE KeyHandle,
  60. IN LPWSTR lpValueName,
  61. IN ULONG Length,
  62. OUT PVOID KeyValue,
  63. OUT PULONG ResultLength
  64. )
  65. {
  66. UNICODE_STRING ValueName;
  67. ULONG BufferLength;
  68. NTSTATUS Status;
  69. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  70. RtlInitUnicodeString( &ValueName, lpValueName );
  71. BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + Length;
  72. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) WmipAlloc(BufferLength);
  73. if (KeyValueInformation == NULL) {
  74. return STATUS_NO_MEMORY;
  75. }
  76. Status = NtQueryValueKey(
  77. KeyHandle,
  78. &ValueName,
  79. KeyValuePartialInformation,
  80. KeyValueInformation,
  81. BufferLength,
  82. ResultLength
  83. );
  84. if (NT_SUCCESS(Status)) {
  85. RtlCopyMemory(KeyValue,
  86. KeyValueInformation->Data,
  87. KeyValueInformation->DataLength
  88. );
  89. *ResultLength = KeyValueInformation->DataLength;
  90. if (KeyValueInformation->Type == REG_SZ) {
  91. if (KeyValueInformation->DataLength + sizeof(WCHAR) > Length) {
  92. KeyValueInformation->DataLength -= sizeof(WCHAR);
  93. }
  94. ((PUCHAR)KeyValue)[KeyValueInformation->DataLength++] = 0;
  95. ((PUCHAR)KeyValue)[KeyValueInformation->DataLength] = 0;
  96. *ResultLength = KeyValueInformation->DataLength + sizeof(WCHAR);
  97. }
  98. }
  99. WmipFree(KeyValueInformation);
  100. return Status;
  101. }
  102. NTSTATUS
  103. WmipGetNetworkAdapters(
  104. IN PWMI_LOGGER_CONTEXT LoggerContext
  105. )
  106. {
  107. PWCHAR Buffer = NULL;
  108. HANDLE Handle;
  109. NTSTATUS Status = STATUS_SUCCESS;
  110. ULONG SubKeyIndex;
  111. ULONG DataLength;
  112. LPWSTR NicName;
  113. //
  114. // Open NetworkCards registry key to obtain the cards
  115. //
  116. Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE);
  117. if (Buffer == NULL) {
  118. return STATUS_NO_MEMORY;
  119. }
  120. swprintf(Buffer, NETWORKCARDS_ROOT);
  121. Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
  122. if (!NT_SUCCESS(Status)) {
  123. goto NicCleanup;
  124. }
  125. for (SubKeyIndex=0; TRUE; SubKeyIndex++) {
  126. PKEY_BASIC_INFORMATION KeyInformation;
  127. ULONG RequiredLength;
  128. WCHAR Name[MAXSTR];
  129. HANDLE SubKeyHandle;
  130. KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
  131. Status = NtEnumerateKey(Handle,
  132. SubKeyIndex,
  133. KeyBasicInformation,
  134. (PVOID) KeyInformation,
  135. 4096,
  136. &RequiredLength
  137. );
  138. if (Status == STATUS_NO_MORE_ENTRIES) {
  139. Status = STATUS_SUCCESS;
  140. break;
  141. }
  142. if (!NT_SUCCESS(Status)) {
  143. break;
  144. }
  145. if (KeyInformation->NameLength > MAXSTR) {
  146. #ifdef DBG
  147. WmipDebugPrint(("WMI: Ignoring NIC with largename %d\n", KeyInformation->NameLength));
  148. WmipAssert(KeyInformation->NameLength <= MAXSTR);
  149. #endif
  150. continue;
  151. }
  152. RtlCopyMemory(Name, (PWSTR)&(KeyInformation->Name[0]), KeyInformation->NameLength);
  153. Name[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
  154. //
  155. // Now Query To get the Description field
  156. //
  157. swprintf(Buffer, L"%ws\\%ws", NETWORKCARDS_ROOT, Name);
  158. Status = WmipRegOpenKey((LPWSTR)Buffer, &SubKeyHandle);
  159. if (!NT_SUCCESS(Status)) {
  160. break;
  161. }
  162. swprintf(Name, NIC_VALUE_NAME);
  163. NicQuery:
  164. Status = WmipRegQueryValueKey(SubKeyHandle, Name, 4096, (PVOID)Buffer, &DataLength);
  165. if (Status == STATUS_BUFFER_OVERFLOW) {
  166. WmipFree(Buffer);
  167. Buffer = WmipAlloc(DataLength);
  168. if (Buffer == NULL) {
  169. Status = STATUS_NO_MEMORY;
  170. NtClose(SubKeyHandle);
  171. break;
  172. }
  173. goto NicQuery;
  174. }
  175. if (!NT_SUCCESS(Status) ) {
  176. NtClose(SubKeyHandle);
  177. break;
  178. }
  179. NicName = (LPWSTR) WmipGetTraceBuffer( LoggerContext,
  180. NULL,
  181. EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_NIC,
  182. DataLength);
  183. if (NicName != NULL) {
  184. RtlCopyMemory(NicName, Buffer, DataLength);
  185. }
  186. NtClose(SubKeyHandle);
  187. }
  188. NtClose(Handle);
  189. NicCleanup:
  190. if (Buffer != NULL) {
  191. WmipFree(Buffer);
  192. }
  193. return Status;
  194. }
  195. BOOL
  196. WmipIsVolumeName(
  197. LPWSTR Name
  198. )
  199. {
  200. if (Name[0] == '\\' &&
  201. (Name[1] == '?' || Name[1] == '\\') &&
  202. Name[2] == '?' &&
  203. Name[3] == '\\' &&
  204. Name[4] == 'V' &&
  205. Name[5] == 'o' &&
  206. Name[6] == 'l' &&
  207. Name[7] == 'u' &&
  208. Name[8] == 'm' &&
  209. Name[9] == 'e' &&
  210. Name[10] == '{' &&
  211. Name[19] == '-' &&
  212. Name[24] == '-' &&
  213. Name[29] == '-' &&
  214. Name[34] == '-' &&
  215. Name[47] == '}' ) {
  216. return TRUE;
  217. }
  218. return FALSE;
  219. }
  220. ULONG
  221. WmipGetCpuConfig(
  222. IN PWMI_LOGGER_CONTEXT LoggerContext
  223. )
  224. {
  225. PWCHAR Buffer = NULL;
  226. WCHAR ComputerName[MAXSTR];
  227. ULONG CpuNum;
  228. ULONG CpuSpeed;
  229. DWORD Size = MAXSTR;
  230. SYSTEM_INFO SysInfo;
  231. MEMORYSTATUS MemStatus;
  232. NTSTATUS Status;
  233. HANDLE Handle;
  234. ULONG DataLength;
  235. ULONG StringSize;
  236. ULONG SizeNeeded;
  237. PCPU_CONFIG_RECORD CpuConfig;
  238. Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE);
  239. if (Buffer == NULL) {
  240. return STATUS_NO_MEMORY;
  241. }
  242. WmipGlobalMemoryStatus(&MemStatus);
  243. swprintf(Buffer, COMPUTERNAME_ROOT);
  244. Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
  245. if (!NT_SUCCESS(Status)) {
  246. goto CpuCleanup;
  247. }
  248. swprintf(Buffer, COMPUTERNAME_VALUE_NAME);
  249. Size = MAXSTR;
  250. CpuQuery:
  251. Status = WmipRegQueryValueKey(Handle,
  252. (LPWSTR) Buffer,
  253. Size,
  254. &ComputerName,
  255. &StringSize
  256. );
  257. if (Status == STATUS_BUFFER_OVERFLOW) {
  258. WmipFree(Buffer);
  259. Buffer = WmipAlloc(StringSize);
  260. if (Buffer == NULL) {
  261. NtClose(Handle);
  262. return STATUS_NO_MEMORY;
  263. }
  264. goto CpuQuery;
  265. }
  266. NtClose(Handle);
  267. if (!NT_SUCCESS(Status) ) {
  268. goto CpuCleanup;
  269. }
  270. //
  271. // Get Architecture Type, Processor Type and Level Stepping...
  272. //
  273. CpuNum = 0;
  274. CpuSpeed = 0;
  275. swprintf(Buffer, L"%ws\\%u", CPU_ROOT, CpuNum);
  276. Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
  277. if (NT_SUCCESS(Status)) {
  278. swprintf(Buffer, MHZ_VALUE_NAME);
  279. Size = sizeof(DWORD);
  280. Status = WmipRegQueryValueKey(Handle,
  281. (LPWSTR) Buffer,
  282. Size,
  283. &CpuSpeed,
  284. &DataLength
  285. );
  286. NtClose(Handle);
  287. if (!NT_SUCCESS(Status)) {
  288. goto CpuCleanup;
  289. }
  290. }
  291. WmipGetSystemInfo(&SysInfo);
  292. //
  293. // Create EventTrace record for CPU configuration and write it
  294. //
  295. SizeNeeded = sizeof(CPU_CONFIG_RECORD) + StringSize;
  296. CpuConfig = (PCPU_CONFIG_RECORD) WmipGetTraceBuffer(LoggerContext,
  297. NULL,
  298. EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_CPU,
  299. SizeNeeded);
  300. if (CpuConfig == NULL) {
  301. Status = STATUS_NO_MEMORY;
  302. goto CpuCleanup;
  303. }
  304. CpuConfig->NumberOfProcessors = SysInfo.dwNumberOfProcessors;
  305. CpuConfig->ProcessorSpeed = CpuSpeed;
  306. CpuConfig->MemorySize = (ULONG)(((MemStatus.dwTotalPhys + 512) / 1024) + 512) / 1024;
  307. CpuConfig->PageSize = SysInfo.dwPageSize;
  308. CpuConfig->AllocationGranularity = SysInfo.dwAllocationGranularity;
  309. RtlCopyMemory(&CpuConfig->ComputerName, ComputerName, StringSize);
  310. CpuConfig->ComputerName[StringSize/2] = 0;
  311. CpuCleanup:
  312. if (Buffer != NULL) {
  313. WmipFree(Buffer);
  314. }
  315. return Status;
  316. }
  317. NTSTATUS
  318. WmipGetDiskInfo(
  319. IN PWMI_LOGGER_CONTEXT LoggerContext
  320. )
  321. {
  322. PUCHAR Buffer = NULL;
  323. STORAGE_DEVICE_NUMBER Number;
  324. PMOUNTMGR_MOUNT_POINTS mountPoints;
  325. MOUNTMGR_MOUNT_POINT mountPoint;
  326. ULONG returnSize, success;
  327. SYSTEM_DEVICE_INFORMATION DevInfo;
  328. NTSTATUS Status = STATUS_SUCCESS;
  329. ULONG NumberOfDisks;
  330. PWCHAR deviceNameBuffer;
  331. ULONG i;
  332. OBJECT_ATTRIBUTES ObjectAttributes;
  333. IO_STATUS_BLOCK IoStatus;
  334. DISK_GEOMETRY disk_geometry;
  335. PDISK_CACHE_INFORMATION disk_cache;
  336. PSCSI_ADDRESS scsi_address;
  337. PWCHAR KeyName;
  338. HANDLE hDisk = INVALID_HANDLE_VALUE;
  339. UNICODE_STRING UnicodeName;
  340. PPHYSICAL_DISK_RECORD Disk;
  341. PLOGICAL_DISK_EXTENTS LogicalDisk;
  342. ULONG SizeNeeded;
  343. Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE);
  344. if (Buffer == NULL) {
  345. return STATUS_NO_MEMORY;
  346. }
  347. //
  348. // Get the Number of Physical Disks
  349. //
  350. RtlZeroMemory(&DevInfo, sizeof(DevInfo));
  351. Status = NtQuerySystemInformation(
  352. SystemDeviceInformation,
  353. &DevInfo, sizeof (DevInfo), NULL);
  354. if (!NT_SUCCESS(Status)) {
  355. goto DiskCleanup;
  356. }
  357. NumberOfDisks = DevInfo.NumberOfDisks;
  358. //
  359. // Open Each Physical Disk and get Disk Layout information
  360. //
  361. for (i=0; i < NumberOfDisks; i++) {
  362. DISK_CACHE_INFORMATION cacheInfo;
  363. WCHAR driveBuffer[20];
  364. HANDLE PartitionHandle;
  365. HANDLE KeyHandle;
  366. ULONG DataLength;
  367. //
  368. // Get Partition0 handle to get the Disk layout
  369. //
  370. deviceNameBuffer = (PWCHAR) Buffer;
  371. swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i);
  372. RtlInitUnicodeString(&UnicodeName, deviceNameBuffer);
  373. InitializeObjectAttributes(
  374. &ObjectAttributes,
  375. &UnicodeName,
  376. OBJ_CASE_INSENSITIVE,
  377. NULL,
  378. NULL
  379. );
  380. Status = NtOpenFile(
  381. &PartitionHandle,
  382. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  383. &ObjectAttributes,
  384. &IoStatus,
  385. FILE_SHARE_READ | FILE_SHARE_WRITE,
  386. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
  387. );
  388. if (!NT_SUCCESS(Status)) {
  389. goto DiskCleanup;
  390. }
  391. RtlZeroMemory(&disk_geometry, sizeof(DISK_GEOMETRY));
  392. // get geomerty information, the caller wants this
  393. Status = NtDeviceIoControlFile(PartitionHandle,
  394. 0,
  395. NULL,
  396. NULL,
  397. &IoStatus,
  398. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  399. NULL,
  400. 0,
  401. &disk_geometry,
  402. sizeof (DISK_GEOMETRY)
  403. );
  404. if (!NT_SUCCESS(Status)) {
  405. NtClose(PartitionHandle);
  406. goto DiskCleanup;
  407. }
  408. scsi_address = (PSCSI_ADDRESS) Buffer;
  409. Status = NtDeviceIoControlFile(PartitionHandle,
  410. 0,
  411. NULL,
  412. NULL,
  413. &IoStatus,
  414. IOCTL_SCSI_GET_ADDRESS,
  415. NULL,
  416. 0,
  417. scsi_address,
  418. sizeof (SCSI_ADDRESS)
  419. );
  420. NtClose(PartitionHandle);
  421. if (!NT_SUCCESS(Status)) {
  422. goto DiskCleanup;
  423. }
  424. //
  425. // Get Manufacturer's name from Registry
  426. // We need to get the SCSI Address and then query the Registry with it.
  427. //
  428. KeyName = (PWCHAR) Buffer;
  429. swprintf(KeyName,
  430. L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target ID %d\\Logical Unit Id %d",
  431. scsi_address->PortNumber, scsi_address->PathId, scsi_address->TargetId, scsi_address->Lun
  432. );
  433. Status = WmipRegOpenKey(KeyName, &KeyHandle);
  434. if (!NT_SUCCESS(Status)) {
  435. goto DiskCleanup;
  436. }
  437. else {
  438. ULONG Size = MAXSTR;
  439. RtlZeroMemory(Buffer, Size);
  440. DiskQuery:
  441. Status = WmipRegQueryValueKey(KeyHandle,
  442. L"Identifier",
  443. Size,
  444. Buffer, &DataLength);
  445. if (Status == STATUS_BUFFER_OVERFLOW) {
  446. WmipFree(Buffer);
  447. Buffer = WmipAlloc(DataLength);
  448. if (Buffer == NULL) {
  449. return STATUS_NO_MEMORY;
  450. }
  451. goto DiskQuery;
  452. }
  453. NtClose(KeyHandle);
  454. if (!NT_SUCCESS(Status) ) {
  455. goto DiskCleanup;
  456. }
  457. }
  458. //
  459. // Package all information about this disk and write an event record
  460. //
  461. SizeNeeded = sizeof(PHYSICAL_DISK_RECORD) + DataLength;
  462. Disk = (PPHYSICAL_DISK_RECORD) WmipGetTraceBuffer( LoggerContext,
  463. NULL,
  464. EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_PHYSICALDISK,
  465. SizeNeeded);
  466. if (Disk == NULL) {
  467. Status = STATUS_NO_MEMORY;
  468. goto DiskCleanup;
  469. }
  470. Disk->DiskNumber = i;
  471. Disk->BytesPerSector = disk_geometry.BytesPerSector;
  472. Disk->SectorsPerTrack = disk_geometry.SectorsPerTrack;
  473. Disk->TracksPerCylinder = disk_geometry.TracksPerCylinder;
  474. Disk->Cylinders = disk_geometry.Cylinders.QuadPart;
  475. Disk->SCSIPortNumber = scsi_address->PortNumber;
  476. Disk->SCSIPathId = scsi_address->PathId;
  477. Disk->SCSITargetId = scsi_address->TargetId;
  478. Disk->SCSILun = scsi_address->Lun;
  479. RtlCopyMemory(Disk->Manufacturer, Buffer, DataLength);
  480. Disk->Manufacturer[DataLength/2] = 0;
  481. }
  482. //
  483. // Get Logical Disk Information
  484. //
  485. wcscpy((LPWSTR)Buffer, MOUNTMGR_DEVICE_NAME);
  486. RtlInitUnicodeString(&UnicodeName, (LPWSTR)Buffer);
  487. UnicodeName.MaximumLength = MAXSTR;
  488. InitializeObjectAttributes(
  489. &ObjectAttributes,
  490. &UnicodeName,
  491. OBJ_CASE_INSENSITIVE,
  492. NULL,
  493. NULL );
  494. Status = NtCreateFile(
  495. &hDisk,
  496. GENERIC_READ | SYNCHRONIZE,
  497. &ObjectAttributes,
  498. &IoStatus,
  499. NULL,
  500. FILE_ATTRIBUTE_NORMAL,
  501. FILE_SHARE_READ | FILE_SHARE_WRITE,
  502. FILE_OPEN_IF,
  503. FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE,
  504. NULL, 0);
  505. if (!NT_SUCCESS(Status) ) {
  506. goto DiskCleanup;
  507. }
  508. RtlZeroMemory(Buffer, 4096);
  509. RtlZeroMemory(&mountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
  510. returnSize = 0;
  511. mountPoints = (PMOUNTMGR_MOUNT_POINTS) &Buffer[0];
  512. Status = NtDeviceIoControlFile(hDisk,
  513. 0,
  514. NULL,
  515. NULL,
  516. &IoStatus,
  517. IOCTL_MOUNTMGR_QUERY_POINTS,
  518. mountPoints,
  519. sizeof(MOUNTMGR_MOUNT_POINT),
  520. mountPoints,
  521. 4096
  522. );
  523. if (NT_SUCCESS(Status)) {
  524. WCHAR name[MAXSTR];
  525. CHAR OutBuffer[4096];
  526. PMOUNTMGR_MOUNT_POINT point;
  527. UNICODE_STRING VolumePoint;
  528. PVOLUME_DISK_EXTENTS VolExt;
  529. PDISK_EXTENT DiskExt;
  530. ULONG i;
  531. for (i=0; i<mountPoints->NumberOfMountPoints; i++) {
  532. point = &mountPoints->MountPoints[i];
  533. if (point->SymbolicLinkNameLength) {
  534. RtlCopyMemory(name,
  535. (PCHAR) mountPoints + point->SymbolicLinkNameOffset,
  536. point->SymbolicLinkNameLength);
  537. name[point->SymbolicLinkNameLength/sizeof(WCHAR)] = 0;
  538. if (WmipIsVolumeName(name)) {
  539. continue;
  540. }
  541. }
  542. if (point->DeviceNameLength) {
  543. HANDLE hVolume;
  544. ULONG dwBytesReturned;
  545. PSTORAGE_DEVICE_NUMBER Number;
  546. DWORD IErrorMode;
  547. RtlCopyMemory(name,
  548. (PCHAR) mountPoints + point->DeviceNameOffset,
  549. point->DeviceNameLength);
  550. name[point->DeviceNameLength/sizeof(WCHAR)] = 0;
  551. RtlInitUnicodeString(&UnicodeName, name);
  552. UnicodeName.MaximumLength = MAXSTR;
  553. //
  554. // If the device name does not have the harddisk prefix
  555. // then it may be a floppy or cdrom and we want avoid
  556. // calling NtCreateFile on them.
  557. //
  558. if(_wcsnicmp(name,L"\\device\\harddisk",16)) {
  559. continue;
  560. }
  561. InitializeObjectAttributes(
  562. &ObjectAttributes,
  563. &UnicodeName,
  564. OBJ_CASE_INSENSITIVE,
  565. NULL,
  566. NULL );
  567. //
  568. // We do not want any pop up dialog here in case we are unable to
  569. // access the volume.
  570. //
  571. IErrorMode = WmipSetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  572. Status = NtCreateFile(
  573. &hVolume,
  574. GENERIC_READ | SYNCHRONIZE,
  575. &ObjectAttributes,
  576. &IoStatus,
  577. NULL,
  578. FILE_ATTRIBUTE_NORMAL,
  579. FILE_SHARE_READ | FILE_SHARE_WRITE,
  580. FILE_OPEN_IF,
  581. FILE_SYNCHRONOUS_IO_NONALERT,
  582. NULL, 0);
  583. WmipSetErrorMode(IErrorMode);
  584. if (!NT_SUCCESS(Status)) {
  585. continue;
  586. }
  587. RtlZeroMemory(OutBuffer, 4096);
  588. dwBytesReturned = 0;
  589. VolExt = (PVOLUME_DISK_EXTENTS) &OutBuffer;
  590. Status = NtDeviceIoControlFile(hVolume,
  591. 0,
  592. NULL,
  593. NULL,
  594. &IoStatus,
  595. IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
  596. NULL,
  597. 0,
  598. &OutBuffer,
  599. 4096
  600. );
  601. if (NT_SUCCESS(Status) ) {
  602. ULONG j;
  603. PLOGICAL_DISK_EXTENTS LogicalDisk;
  604. ULONG NumberOfExtents = VolExt->NumberOfDiskExtents;
  605. SizeNeeded = NumberOfExtents * sizeof(LOGICAL_DISK_EXTENTS);
  606. LogicalDisk = (PLOGICAL_DISK_EXTENTS) WmipGetTraceBuffer( LoggerContext,
  607. NULL,
  608. EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_LOGICALDISK,
  609. SizeNeeded);
  610. if (LogicalDisk == NULL) {
  611. Status = STATUS_NO_MEMORY;
  612. }
  613. else {
  614. for (j=0; j < NumberOfExtents; j++) {
  615. DiskExt = &VolExt->Extents[j];
  616. LogicalDisk->DiskNumber = DiskExt->DiskNumber;
  617. LogicalDisk->StartingOffset = DiskExt->StartingOffset.QuadPart;
  618. LogicalDisk->PartitionSize = DiskExt->ExtentLength.QuadPart;
  619. LogicalDisk++;
  620. }
  621. }
  622. }
  623. NtClose(hVolume);
  624. }
  625. }
  626. }
  627. NtClose(hDisk);
  628. DiskCleanup:
  629. if (Buffer != NULL) {
  630. WmipFree(Buffer);
  631. }
  632. return Status;
  633. }
  634. //
  635. // This routine records the hardware configuration in the
  636. // logfile during RunDown
  637. //
  638. ULONG
  639. WmipDumpHardwareConfig(
  640. IN PWMI_LOGGER_CONTEXT LoggerContext
  641. )
  642. {
  643. NTSTATUS Status;
  644. Status = WmipGetCpuConfig(LoggerContext);
  645. if (!NT_SUCCESS(Status) )
  646. return WmipSetNtStatus(Status);
  647. Status = WmipGetDiskInfo(LoggerContext);
  648. if (!NT_SUCCESS(Status) )
  649. return WmipSetNtStatus(Status);
  650. Status = WmipGetNetworkAdapters(LoggerContext);
  651. if (!NT_SUCCESS(Status) )
  652. return WmipSetNtStatus(Status);
  653. return ERROR_SUCCESS;
  654. }