|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
tracehw.c
Abstract:
This routine dumps the hardware configuration of the machine to the logfile.
Author:
04-Jul-2000 Melur Raghuraman
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h> // for ntutrl.h
#include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
#include <wtypes.h> // for LPGUID in wmium.h
#include <mountmgr.h>
#include <winioctl.h>
#include <ntddvol.h>
#include <ntddscsi.h>
#include "wmiump.h"
#include "evntrace.h"
#include "traceump.h"
#include "tracelib.h"
#include "trcapi.h"
#define DEFAULT_ALLOC_SIZE 4096
#define COMPUTERNAME_ROOT \
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
#define CPU_ROOT \
L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor"
#define COMPUTERNAME_VALUE_NAME \
L"ComputerName"
#define NETWORKCARDS_ROOT \
L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
#define MHZ_VALUE_NAME \
L"~MHz"
#define NIC_VALUE_NAME \
L"Description"
NTSTATUS WmipRegOpenKey( IN LPWSTR lpKeyName, OUT PHANDLE KeyHandle ) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; RtlInitUnicodeString( &KeyName, lpKeyName ); RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
return NtOpenKey( KeyHandle, KEY_READ, &ObjectAttributes ); }
NTSTATUS WmipRegQueryValueKey( IN HANDLE KeyHandle, IN LPWSTR lpValueName, IN ULONG Length, OUT PVOID KeyValue, OUT PULONG ResultLength ) { UNICODE_STRING ValueName; ULONG BufferLength; NTSTATUS Status; PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; RtlInitUnicodeString( &ValueName, lpValueName );
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + Length; KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) WmipAlloc(BufferLength); if (KeyValueInformation == NULL) { return STATUS_NO_MEMORY; }
Status = NtQueryValueKey( KeyHandle, &ValueName, KeyValuePartialInformation, KeyValueInformation, BufferLength, ResultLength ); if (NT_SUCCESS(Status)) {
RtlCopyMemory(KeyValue, KeyValueInformation->Data, KeyValueInformation->DataLength );
*ResultLength = KeyValueInformation->DataLength; if (KeyValueInformation->Type == REG_SZ) { if (KeyValueInformation->DataLength + sizeof(WCHAR) > Length) { KeyValueInformation->DataLength -= sizeof(WCHAR); } ((PUCHAR)KeyValue)[KeyValueInformation->DataLength++] = 0; ((PUCHAR)KeyValue)[KeyValueInformation->DataLength] = 0; *ResultLength = KeyValueInformation->DataLength + sizeof(WCHAR); } } WmipFree(KeyValueInformation); return Status; }
NTSTATUS WmipGetNetworkAdapters( IN PWMI_LOGGER_CONTEXT LoggerContext ) { PWCHAR Buffer = NULL; HANDLE Handle; NTSTATUS Status = STATUS_SUCCESS; ULONG SubKeyIndex; ULONG DataLength; LPWSTR NicName;
//
// Open NetworkCards registry key to obtain the cards
//
Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE); if (Buffer == NULL) { return STATUS_NO_MEMORY; }
swprintf(Buffer, NETWORKCARDS_ROOT);
Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
if (!NT_SUCCESS(Status)) { goto NicCleanup; }
for (SubKeyIndex=0; TRUE; SubKeyIndex++) { PKEY_BASIC_INFORMATION KeyInformation; ULONG RequiredLength; WCHAR Name[MAXSTR]; HANDLE SubKeyHandle;
KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
Status = NtEnumerateKey(Handle, SubKeyIndex, KeyBasicInformation, (PVOID) KeyInformation, 4096, &RequiredLength );
if (Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; break; }
if (!NT_SUCCESS(Status)) { break; }
if (KeyInformation->NameLength > MAXSTR) { #ifdef DBG
WmipDebugPrint(("WMI: Ignoring NIC with largename %d\n", KeyInformation->NameLength)); WmipAssert(KeyInformation->NameLength <= MAXSTR); #endif
continue; }
RtlCopyMemory(Name, (PWSTR)&(KeyInformation->Name[0]), KeyInformation->NameLength); Name[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
//
// Now Query To get the Description field
//
swprintf(Buffer, L"%ws\\%ws", NETWORKCARDS_ROOT, Name);
Status = WmipRegOpenKey((LPWSTR)Buffer, &SubKeyHandle); if (!NT_SUCCESS(Status)) { break; }
swprintf(Name, NIC_VALUE_NAME);
NicQuery: Status = WmipRegQueryValueKey(SubKeyHandle, Name, 4096, (PVOID)Buffer, &DataLength);
if (Status == STATUS_BUFFER_OVERFLOW) { WmipFree(Buffer); Buffer = WmipAlloc(DataLength); if (Buffer == NULL) { Status = STATUS_NO_MEMORY; NtClose(SubKeyHandle); break; } goto NicQuery; } if (!NT_SUCCESS(Status) ) { NtClose(SubKeyHandle); break; }
NicName = (LPWSTR) WmipGetTraceBuffer( LoggerContext, NULL, EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_NIC, DataLength);
if (NicName != NULL) { RtlCopyMemory(NicName, Buffer, DataLength); } NtClose(SubKeyHandle); } NtClose(Handle); NicCleanup: if (Buffer != NULL) { WmipFree(Buffer); } return Status; }
BOOL WmipIsVolumeName( LPWSTR Name ) { if (Name[0] == '\\' && (Name[1] == '?' || Name[1] == '\\') && Name[2] == '?' && Name[3] == '\\' && Name[4] == 'V' && Name[5] == 'o' && Name[6] == 'l' && Name[7] == 'u' && Name[8] == 'm' && Name[9] == 'e' && Name[10] == '{' && Name[19] == '-' && Name[24] == '-' && Name[29] == '-' && Name[34] == '-' && Name[47] == '}' ) {
return TRUE; } return FALSE; }
ULONG WmipGetCpuConfig( IN PWMI_LOGGER_CONTEXT LoggerContext ) { PWCHAR Buffer = NULL; WCHAR ComputerName[MAXSTR]; ULONG CpuNum; ULONG CpuSpeed; DWORD Size = MAXSTR; SYSTEM_INFO SysInfo; MEMORYSTATUS MemStatus; NTSTATUS Status; HANDLE Handle; ULONG DataLength; ULONG StringSize; ULONG SizeNeeded; PCPU_CONFIG_RECORD CpuConfig;
Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE); if (Buffer == NULL) { return STATUS_NO_MEMORY; }
WmipGlobalMemoryStatus(&MemStatus);
swprintf(Buffer, COMPUTERNAME_ROOT);
Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
if (!NT_SUCCESS(Status)) { goto CpuCleanup; }
swprintf(Buffer, COMPUTERNAME_VALUE_NAME); Size = MAXSTR;
CpuQuery: Status = WmipRegQueryValueKey(Handle, (LPWSTR) Buffer, Size, &ComputerName, &StringSize );
if (Status == STATUS_BUFFER_OVERFLOW) { WmipFree(Buffer); Buffer = WmipAlloc(StringSize); if (Buffer == NULL) { NtClose(Handle); return STATUS_NO_MEMORY; } goto CpuQuery; }
NtClose(Handle); if (!NT_SUCCESS(Status) ) { goto CpuCleanup; }
//
// Get Architecture Type, Processor Type and Level Stepping...
//
CpuNum = 0; CpuSpeed = 0; swprintf(Buffer, L"%ws\\%u", CPU_ROOT, CpuNum); Status = WmipRegOpenKey((LPWSTR)Buffer, &Handle);
if (NT_SUCCESS(Status)) { swprintf(Buffer, MHZ_VALUE_NAME); Size = sizeof(DWORD); Status = WmipRegQueryValueKey(Handle, (LPWSTR) Buffer, Size, &CpuSpeed, &DataLength ); NtClose(Handle); if (!NT_SUCCESS(Status)) { goto CpuCleanup; } }
WmipGetSystemInfo(&SysInfo);
//
// Create EventTrace record for CPU configuration and write it
//
SizeNeeded = sizeof(CPU_CONFIG_RECORD) + StringSize;
CpuConfig = (PCPU_CONFIG_RECORD) WmipGetTraceBuffer(LoggerContext, NULL, EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_CPU, SizeNeeded);
if (CpuConfig == NULL) { Status = STATUS_NO_MEMORY; goto CpuCleanup; } CpuConfig->NumberOfProcessors = SysInfo.dwNumberOfProcessors; CpuConfig->ProcessorSpeed = CpuSpeed; CpuConfig->MemorySize = (ULONG)(((MemStatus.dwTotalPhys + 512) / 1024) + 512) / 1024; CpuConfig->PageSize = SysInfo.dwPageSize; CpuConfig->AllocationGranularity = SysInfo.dwAllocationGranularity;
RtlCopyMemory(&CpuConfig->ComputerName, ComputerName, StringSize);
CpuConfig->ComputerName[StringSize/2] = 0; CpuCleanup: if (Buffer != NULL) { WmipFree(Buffer); }
return Status; }
NTSTATUS WmipGetDiskInfo( IN PWMI_LOGGER_CONTEXT LoggerContext ) { PUCHAR Buffer = NULL; STORAGE_DEVICE_NUMBER Number; PMOUNTMGR_MOUNT_POINTS mountPoints; MOUNTMGR_MOUNT_POINT mountPoint; ULONG returnSize, success; SYSTEM_DEVICE_INFORMATION DevInfo; NTSTATUS Status = STATUS_SUCCESS; ULONG NumberOfDisks; PWCHAR deviceNameBuffer; ULONG i; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus;
DISK_GEOMETRY disk_geometry; PDISK_CACHE_INFORMATION disk_cache; PSCSI_ADDRESS scsi_address; PWCHAR KeyName; HANDLE hDisk = INVALID_HANDLE_VALUE; UNICODE_STRING UnicodeName;
PPHYSICAL_DISK_RECORD Disk; PLOGICAL_DISK_EXTENTS LogicalDisk; ULONG SizeNeeded;
Buffer = WmipAlloc(DEFAULT_ALLOC_SIZE); if (Buffer == NULL) { return STATUS_NO_MEMORY; }
//
// Get the Number of Physical Disks
//
RtlZeroMemory(&DevInfo, sizeof(DevInfo));
Status = NtQuerySystemInformation( SystemDeviceInformation, &DevInfo, sizeof (DevInfo), NULL);
if (!NT_SUCCESS(Status)) { goto DiskCleanup; }
NumberOfDisks = DevInfo.NumberOfDisks;
//
// Open Each Physical Disk and get Disk Layout information
//
for (i=0; i < NumberOfDisks; i++) {
DISK_CACHE_INFORMATION cacheInfo; WCHAR driveBuffer[20];
HANDLE PartitionHandle; HANDLE KeyHandle; ULONG DataLength;
//
// Get Partition0 handle to get the Disk layout
//
deviceNameBuffer = (PWCHAR) Buffer; swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i);
RtlInitUnicodeString(&UnicodeName, deviceNameBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenFile( &PartitionHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE );
if (!NT_SUCCESS(Status)) { goto DiskCleanup; }
RtlZeroMemory(&disk_geometry, sizeof(DISK_GEOMETRY)); // get geomerty information, the caller wants this
Status = NtDeviceIoControlFile(PartitionHandle, 0, NULL, NULL, &IoStatus, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &disk_geometry, sizeof (DISK_GEOMETRY) ); if (!NT_SUCCESS(Status)) { NtClose(PartitionHandle); goto DiskCleanup; } scsi_address = (PSCSI_ADDRESS) Buffer; Status = NtDeviceIoControlFile(PartitionHandle, 0, NULL, NULL, &IoStatus, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_address, sizeof (SCSI_ADDRESS) );
NtClose(PartitionHandle);
if (!NT_SUCCESS(Status)) { goto DiskCleanup; }
//
// Get Manufacturer's name from Registry
// We need to get the SCSI Address and then query the Registry with it.
//
KeyName = (PWCHAR) Buffer; swprintf(KeyName, L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target ID %d\\Logical Unit Id %d", scsi_address->PortNumber, scsi_address->PathId, scsi_address->TargetId, scsi_address->Lun ); Status = WmipRegOpenKey(KeyName, &KeyHandle); if (!NT_SUCCESS(Status)) { goto DiskCleanup; } else { ULONG Size = MAXSTR; RtlZeroMemory(Buffer, Size); DiskQuery: Status = WmipRegQueryValueKey(KeyHandle, L"Identifier", Size, Buffer, &DataLength); if (Status == STATUS_BUFFER_OVERFLOW) { WmipFree(Buffer); Buffer = WmipAlloc(DataLength); if (Buffer == NULL) { return STATUS_NO_MEMORY; } goto DiskQuery; }
NtClose(KeyHandle); if (!NT_SUCCESS(Status) ) { goto DiskCleanup; } }
//
// Package all information about this disk and write an event record
//
SizeNeeded = sizeof(PHYSICAL_DISK_RECORD) + DataLength;
Disk = (PPHYSICAL_DISK_RECORD) WmipGetTraceBuffer( LoggerContext, NULL, EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_PHYSICALDISK, SizeNeeded);
if (Disk == NULL) { Status = STATUS_NO_MEMORY; goto DiskCleanup; }
Disk->DiskNumber = i; Disk->BytesPerSector = disk_geometry.BytesPerSector; Disk->SectorsPerTrack = disk_geometry.SectorsPerTrack; Disk->TracksPerCylinder = disk_geometry.TracksPerCylinder; Disk->Cylinders = disk_geometry.Cylinders.QuadPart; Disk->SCSIPortNumber = scsi_address->PortNumber; Disk->SCSIPathId = scsi_address->PathId; Disk->SCSITargetId = scsi_address->TargetId; Disk->SCSILun = scsi_address->Lun;
RtlCopyMemory(Disk->Manufacturer, Buffer, DataLength); Disk->Manufacturer[DataLength/2] = 0;
}
//
// Get Logical Disk Information
//
wcscpy((LPWSTR)Buffer, MOUNTMGR_DEVICE_NAME); RtlInitUnicodeString(&UnicodeName, (LPWSTR)Buffer); UnicodeName.MaximumLength = MAXSTR;
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtCreateFile( &hDisk, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE, NULL, 0);
if (!NT_SUCCESS(Status) ) { goto DiskCleanup; } RtlZeroMemory(Buffer, 4096); RtlZeroMemory(&mountPoint, sizeof(MOUNTMGR_MOUNT_POINT)); returnSize = 0; mountPoints = (PMOUNTMGR_MOUNT_POINTS) &Buffer[0];
Status = NtDeviceIoControlFile(hDisk, 0, NULL, NULL, &IoStatus, IOCTL_MOUNTMGR_QUERY_POINTS, mountPoints, sizeof(MOUNTMGR_MOUNT_POINT), mountPoints, 4096 );
if (NT_SUCCESS(Status)) { WCHAR name[MAXSTR]; CHAR OutBuffer[4096]; PMOUNTMGR_MOUNT_POINT point; UNICODE_STRING VolumePoint; PVOLUME_DISK_EXTENTS VolExt; PDISK_EXTENT DiskExt; ULONG i; for (i=0; i<mountPoints->NumberOfMountPoints; i++) { point = &mountPoints->MountPoints[i];
if (point->SymbolicLinkNameLength) { RtlCopyMemory(name, (PCHAR) mountPoints + point->SymbolicLinkNameOffset, point->SymbolicLinkNameLength); name[point->SymbolicLinkNameLength/sizeof(WCHAR)] = 0; if (WmipIsVolumeName(name)) { continue; } } if (point->DeviceNameLength) { HANDLE hVolume; ULONG dwBytesReturned; PSTORAGE_DEVICE_NUMBER Number; DWORD IErrorMode;
RtlCopyMemory(name, (PCHAR) mountPoints + point->DeviceNameOffset, point->DeviceNameLength); name[point->DeviceNameLength/sizeof(WCHAR)] = 0;
RtlInitUnicodeString(&UnicodeName, name); UnicodeName.MaximumLength = MAXSTR;
//
// If the device name does not have the harddisk prefix
// then it may be a floppy or cdrom and we want avoid
// calling NtCreateFile on them.
//
if(_wcsnicmp(name,L"\\device\\harddisk",16)) { continue; }
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL ); //
// We do not want any pop up dialog here in case we are unable to
// access the volume.
//
IErrorMode = WmipSetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); Status = NtCreateFile( &hVolume, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); WmipSetErrorMode(IErrorMode); if (!NT_SUCCESS(Status)) { continue; }
RtlZeroMemory(OutBuffer, 4096); dwBytesReturned = 0; VolExt = (PVOLUME_DISK_EXTENTS) &OutBuffer;
Status = NtDeviceIoControlFile(hVolume, 0, NULL, NULL, &IoStatus, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &OutBuffer, 4096 ); if (NT_SUCCESS(Status) ) { ULONG j; PLOGICAL_DISK_EXTENTS LogicalDisk; ULONG NumberOfExtents = VolExt->NumberOfDiskExtents; SizeNeeded = NumberOfExtents * sizeof(LOGICAL_DISK_EXTENTS);
LogicalDisk = (PLOGICAL_DISK_EXTENTS) WmipGetTraceBuffer( LoggerContext, NULL, EVENT_TRACE_GROUP_CONFIG + EVENT_TRACE_TYPE_CONFIG_LOGICALDISK, SizeNeeded);
if (LogicalDisk == NULL) { Status = STATUS_NO_MEMORY; } else {
for (j=0; j < NumberOfExtents; j++) {
DiskExt = &VolExt->Extents[j];
LogicalDisk->DiskNumber = DiskExt->DiskNumber; LogicalDisk->StartingOffset = DiskExt->StartingOffset.QuadPart; LogicalDisk->PartitionSize = DiskExt->ExtentLength.QuadPart; LogicalDisk++; } } } NtClose(hVolume); } } } NtClose(hDisk);
DiskCleanup: if (Buffer != NULL) { WmipFree(Buffer); } return Status; }
//
// This routine records the hardware configuration in the
// logfile during RunDown
//
ULONG WmipDumpHardwareConfig( IN PWMI_LOGGER_CONTEXT LoggerContext ) { NTSTATUS Status;
Status = WmipGetCpuConfig(LoggerContext);
if (!NT_SUCCESS(Status) ) return WmipSetNtStatus(Status);
Status = WmipGetDiskInfo(LoggerContext);
if (!NT_SUCCESS(Status) ) return WmipSetNtStatus(Status);
Status = WmipGetNetworkAdapters(LoggerContext);
if (!NT_SUCCESS(Status) ) return WmipSetNtStatus(Status);
return ERROR_SUCCESS; }
|