mirror of
https://github.com/reactos/reactos.git
synced 2024-08-22 03:12:51 +00:00
618 lines
20 KiB
C
618 lines
20 KiB
C
/*
|
|
* PROJECT: ReactOS HAL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: hal/halx86/generic/usage.c
|
|
* PURPOSE: HAL Resource Report Routines
|
|
* PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include <hal.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
VOID
|
|
NTAPI
|
|
HalpGetResourceSortValue(
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
|
|
OUT PULONG Scale,
|
|
OUT PLARGE_INTEGER Value
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
HalpBuildPartialFromIdt(
|
|
IN ULONG Entry,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
HalpBuildPartialFromAddress(
|
|
IN INTERFACE_TYPE Interface,
|
|
IN PADDRESS_USAGE CurrentAddress,
|
|
IN ULONG Element,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor
|
|
);
|
|
|
|
#if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
|
|
#pragma alloc_text(INIT, HalpBuildPartialFromAddress)
|
|
#pragma alloc_text(INIT, HalpBuildPartialFromIdt)
|
|
#pragma alloc_text(INIT, HalpEnableInterruptHandler)
|
|
#pragma alloc_text(INIT, HalpGetNMICrashFlag)
|
|
#pragma alloc_text(INIT, HalpGetResourceSortValue)
|
|
#pragma alloc_text(INIT, HalpRegisterVector)
|
|
#pragma alloc_text(INIT, HalpReportResourceUsage)
|
|
#endif
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
BOOLEAN HalpGetInfoFromACPI;
|
|
BOOLEAN HalpNMIDumpFlag;
|
|
PUCHAR KdComPortInUse;
|
|
PADDRESS_USAGE HalpAddressUsageList;
|
|
IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR+1];
|
|
IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR+1];
|
|
|
|
USHORT HalpComPortIrqMapping[5][2] =
|
|
{
|
|
{0x3F8, 4},
|
|
{0x2F8, 3},
|
|
{0x3E8, 4},
|
|
{0x2E8, 3},
|
|
{0, 0}
|
|
};
|
|
|
|
ADDRESS_USAGE HalpComIoSpace =
|
|
{
|
|
NULL, CmResourceTypePort, IDT_INTERNAL,
|
|
{
|
|
{0x2F8, 0x8}, /* COM 1 */
|
|
{0,0},
|
|
}
|
|
};
|
|
|
|
ADDRESS_USAGE HalpDefaultIoSpace =
|
|
{
|
|
NULL, CmResourceTypePort, IDT_INTERNAL,
|
|
{
|
|
{0x00, 0x20}, /* DMA 1 */
|
|
{0xC0, 0x20}, /* DMA 2 */
|
|
{0x80, 0x10}, /* DMA EPAR */
|
|
{0x20, 0x2}, /* PIC 1 */
|
|
{0xA0, 0x2}, /* PIC 2 */
|
|
{0x40, 0x4}, /* PIT 1 */
|
|
{0x48, 0x4}, /* PIT 2 */
|
|
{0x92, 0x1}, /* System Control Port A */
|
|
{0x70, 0x2}, /* CMOS */
|
|
{0xF0, 0x10}, /* x87 Coprocessor */
|
|
{0xCF8, 0x8}, /* PCI 0 */
|
|
{0,0},
|
|
}
|
|
};
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
#ifndef _MINIHAL_
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
|
|
OUT PULONG Scale,
|
|
OUT PLARGE_INTEGER Value)
|
|
{
|
|
/* Sorting depends on resource type */
|
|
switch (Descriptor->Type)
|
|
{
|
|
case CmResourceTypeInterrupt:
|
|
|
|
/* Interrupt goes by level */
|
|
*Scale = 0;
|
|
*Value = RtlConvertUlongToLargeInteger(Descriptor->u.Interrupt.Level);
|
|
break;
|
|
|
|
case CmResourceTypePort:
|
|
|
|
/* Port goes by port address */
|
|
*Scale = 1;
|
|
*Value = Descriptor->u.Port.Start;
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
/* Memory goes by base address */
|
|
*Scale = 2;
|
|
*Value = Descriptor->u.Memory.Start;
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Anything else */
|
|
*Scale = 4;
|
|
*Value = RtlConvertUlongToLargeInteger(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpBuildPartialFromIdt(IN ULONG Entry,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor)
|
|
{
|
|
/* Exclusive interrupt entry */
|
|
RawDescriptor->Type = CmResourceTypeInterrupt;
|
|
RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
|
|
|
|
/* Check the interrupt type */
|
|
if (HalpIDTUsageFlags[Entry].Flags & IDT_LATCHED)
|
|
{
|
|
/* Latched */
|
|
RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
}
|
|
else
|
|
{
|
|
/* Level */
|
|
RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|
}
|
|
|
|
/* Get vector and level from IDT usage */
|
|
RawDescriptor->u.Interrupt.Vector = HalpIDTUsage[Entry].BusReleativeVector;
|
|
RawDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].BusReleativeVector;
|
|
|
|
/* Affinity is all the CPUs */
|
|
RawDescriptor->u.Interrupt.Affinity = HalpActiveProcessors;
|
|
|
|
/* The translated copy is identical */
|
|
RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
/* But the vector and IRQL must be set correctly */
|
|
TranslatedDescriptor->u.Interrupt.Vector = Entry;
|
|
TranslatedDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].Irql;
|
|
}
|
|
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface,
|
|
IN PADDRESS_USAGE CurrentAddress,
|
|
IN ULONG Element,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor)
|
|
{
|
|
ULONG AddressSpace;
|
|
|
|
/* Set the type and make it exclusive */
|
|
RawDescriptor->Type = CurrentAddress->Type;
|
|
RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
|
|
|
|
/* Check what this is */
|
|
if (RawDescriptor->Type == CmResourceTypePort)
|
|
{
|
|
/* Write out port data */
|
|
AddressSpace = 1;
|
|
RawDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
RawDescriptor->u.Port.Start.HighPart = 0;
|
|
RawDescriptor->u.Port.Start.LowPart = CurrentAddress->Element[Element].Start;
|
|
RawDescriptor->u.Port.Length = CurrentAddress->Element[Element].Length;
|
|
|
|
/* Determine if 16-bit port addresses are allowed */
|
|
RawDescriptor->Flags |= HalpIs16BitPortDecodeSupported();
|
|
}
|
|
else
|
|
{
|
|
/* Write out memory data */
|
|
AddressSpace = 0;
|
|
RawDescriptor->Flags = (CurrentAddress->Flags & IDT_READ_ONLY) ?
|
|
CM_RESOURCE_MEMORY_READ_ONLY :
|
|
CM_RESOURCE_MEMORY_READ_WRITE;
|
|
RawDescriptor->u.Memory.Start.HighPart = 0;
|
|
RawDescriptor->u.Memory.Start.LowPart = CurrentAddress->Element[Element].Start;
|
|
RawDescriptor->u.Memory.Length = CurrentAddress->Element[Element].Length;
|
|
}
|
|
|
|
/* Make an identical copy to begin with */
|
|
RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|
|
|
/* Check what this is */
|
|
if (RawDescriptor->Type == CmResourceTypePort)
|
|
{
|
|
/* Translate the port */
|
|
HalTranslateBusAddress(Interface,
|
|
0,
|
|
RawDescriptor->u.Port.Start,
|
|
&AddressSpace,
|
|
&TranslatedDescriptor->u.Port.Start);
|
|
|
|
/* If it turns out this is memory once translated, flag it */
|
|
if (AddressSpace == 0) TranslatedDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Translate the memory */
|
|
HalTranslateBusAddress(Interface,
|
|
0,
|
|
RawDescriptor->u.Memory.Start,
|
|
&AddressSpace,
|
|
&TranslatedDescriptor->u.Memory.Start);
|
|
}
|
|
}
|
|
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpReportResourceUsage(IN PUNICODE_STRING HalName,
|
|
IN INTERFACE_TYPE InterfaceType)
|
|
{
|
|
PCM_RESOURCE_LIST RawList, TranslatedList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR RawFull, TranslatedFull;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR CurrentRaw, CurrentTranslated, SortedRaw, SortedTranslated;
|
|
CM_PARTIAL_RESOURCE_DESCRIPTOR RawPartial, TranslatedPartial;
|
|
PCM_PARTIAL_RESOURCE_LIST RawPartialList = NULL, TranslatedPartialList = NULL;
|
|
INTERFACE_TYPE Interface;
|
|
ULONG i, j, k, ListSize, Count, Port, Element, CurrentScale, SortScale, ReportType, FlagMatch;
|
|
ADDRESS_USAGE *CurrentAddress;
|
|
LARGE_INTEGER CurrentSortValue, SortValue;
|
|
DbgPrint("%wZ Detected\n", HalName);
|
|
|
|
/* Check if KD is using a COM port */
|
|
if (KdComPortInUse)
|
|
{
|
|
/* Enter it into the I/O space */
|
|
HalpComIoSpace.Element[0].Start = PtrToUlong(KdComPortInUse);
|
|
HalpComIoSpace.Next = HalpAddressUsageList;
|
|
HalpAddressUsageList = &HalpComIoSpace;
|
|
|
|
/* Use the debug port table if we have one */
|
|
HalpGetInfoFromACPI = HalpGetDebugPortTable();
|
|
|
|
/* Check if we're using ACPI */
|
|
if (!HalpGetInfoFromACPI)
|
|
{
|
|
/* No, so use our local table */
|
|
for (i = 0, Port = HalpComPortIrqMapping[i][0];
|
|
Port;
|
|
i++, Port = HalpComPortIrqMapping[i][0])
|
|
{
|
|
/* Is this the port we want? */
|
|
if (Port == (ULONG_PTR)KdComPortInUse)
|
|
{
|
|
/* Register it */
|
|
HalpRegisterVector(IDT_DEVICE | IDT_LATCHED,
|
|
HalpComPortIrqMapping[i][1],
|
|
HalpComPortIrqMapping[i][1] +
|
|
PRIMARY_VECTOR_BASE,
|
|
HIGH_LEVEL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* On non-ACPI systems, we need to build an address map */
|
|
HalpBuildAddressMap();
|
|
|
|
/* Allocate the master raw and translated lists */
|
|
RawList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, TAG_HAL);
|
|
TranslatedList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, TAG_HAL);
|
|
if (!(RawList) || !(TranslatedList))
|
|
{
|
|
/* Bugcheck the system */
|
|
KeBugCheckEx(HAL_MEMORY_ALLOCATION,
|
|
4 * PAGE_SIZE,
|
|
1,
|
|
(ULONG_PTR)__FILE__,
|
|
__LINE__);
|
|
}
|
|
|
|
/* Zero out the lists */
|
|
RtlZeroMemory(RawList, PAGE_SIZE * 2);
|
|
RtlZeroMemory(TranslatedList, PAGE_SIZE * 2);
|
|
|
|
/* Set the interface type to begin with */
|
|
RawList->List[0].InterfaceType = InterfaceTypeUndefined;
|
|
|
|
/* Loop all IDT entries that are not IRQs */
|
|
for (i = 0; i < PRIMARY_VECTOR_BASE; i++)
|
|
{
|
|
/* Check if the IDT isn't owned */
|
|
if (!(HalpIDTUsageFlags[i].Flags & IDT_REGISTERED))
|
|
{
|
|
/* Then register it for internal usage */
|
|
HalpIDTUsageFlags[i].Flags = IDT_INTERNAL;
|
|
HalpIDTUsage[i].BusReleativeVector = (UCHAR)i;
|
|
}
|
|
}
|
|
|
|
/* Our full raw descriptors start here */
|
|
RawFull = RawList->List;
|
|
|
|
/* Keep track of the current partial raw and translated descriptors */
|
|
CurrentRaw = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)RawList->List;
|
|
CurrentTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)TranslatedList->List;
|
|
|
|
/* Do two passes */
|
|
for (ReportType = 0; ReportType < 2; ReportType++)
|
|
{
|
|
/* Pass 0 is for device usage */
|
|
if (ReportType == 0)
|
|
{
|
|
FlagMatch = IDT_DEVICE & ~IDT_REGISTERED;
|
|
Interface = InterfaceType;
|
|
}
|
|
else
|
|
{
|
|
/* Past 1 is for internal HAL usage */
|
|
FlagMatch = IDT_INTERNAL & ~IDT_REGISTERED;
|
|
Interface = Internal;
|
|
}
|
|
|
|
/* Reset loop variables */
|
|
i = Element = 0;
|
|
|
|
/* Start looping our address uage list and interrupts */
|
|
CurrentAddress = HalpAddressUsageList;
|
|
while (TRUE)
|
|
{
|
|
/* Check for valid vector number */
|
|
if (i <= MAXIMUM_IDTVECTOR)
|
|
{
|
|
/* Check if this entry should be parsed */
|
|
if ((HalpIDTUsageFlags[i].Flags & FlagMatch))
|
|
{
|
|
/* Parse it */
|
|
HalpBuildPartialFromIdt(i, &RawPartial, &TranslatedPartial);
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
/* Skip this entry */
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* This is an address instead */
|
|
if (!CurrentAddress) break;
|
|
|
|
/* Check if the address should be reported */
|
|
if (!(CurrentAddress->Flags & FlagMatch) ||
|
|
!(CurrentAddress->Element[Element].Length))
|
|
{
|
|
/* Nope, skip it */
|
|
Element = 0;
|
|
CurrentAddress = CurrentAddress->Next;
|
|
continue;
|
|
}
|
|
|
|
/* Otherwise, parse the entry */
|
|
HalpBuildPartialFromAddress(Interface,
|
|
CurrentAddress,
|
|
Element,
|
|
&RawPartial,
|
|
&TranslatedPartial);
|
|
Element++;
|
|
}
|
|
|
|
/* Check for interface change */
|
|
if (RawFull->InterfaceType != Interface)
|
|
{
|
|
/* We need to add another full descriptor */
|
|
RawList->Count++;
|
|
TranslatedList->Count++;
|
|
|
|
/* The full descriptor follows wherever we were */
|
|
RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw;
|
|
TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated;
|
|
|
|
/* And it is of this new interface type */
|
|
RawFull->InterfaceType = Interface;
|
|
TranslatedFull->InterfaceType = Interface;
|
|
|
|
/* And its partial descriptors begin here */
|
|
RawPartialList = &RawFull->PartialResourceList;
|
|
TranslatedPartialList = &TranslatedFull->PartialResourceList;
|
|
|
|
/* And our next full descriptor should follow here */
|
|
CurrentRaw = RawFull->PartialResourceList.PartialDescriptors;
|
|
CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors;
|
|
}
|
|
|
|
/* We have written a new partial descriptor */
|
|
RawPartialList->Count++;
|
|
TranslatedPartialList->Count++;
|
|
|
|
/* Copy our local descriptors into the actual list */
|
|
RtlCopyMemory(CurrentRaw, &RawPartial, sizeof(RawPartial));
|
|
RtlCopyMemory(CurrentTranslated, &TranslatedPartial, sizeof(TranslatedPartial));
|
|
|
|
/* Move to the next partial descriptor */
|
|
CurrentRaw++;
|
|
CurrentTranslated++;
|
|
}
|
|
}
|
|
|
|
/* Get the final list of the size for the kernel call later */
|
|
ListSize = (ULONG)((ULONG_PTR)CurrentRaw - (ULONG_PTR)RawList);
|
|
|
|
/* Now reset back to the first full descriptor */
|
|
RawFull = RawList->List;
|
|
TranslatedFull = TranslatedList->List;
|
|
|
|
/* And loop all the full descriptors */
|
|
for (i = 0; i < RawList->Count; i++)
|
|
{
|
|
/* Get the first partial descriptor in this list */
|
|
CurrentRaw = RawFull->PartialResourceList.PartialDescriptors;
|
|
CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors;
|
|
|
|
/* Get the count of partials in this list */
|
|
Count = RawFull->PartialResourceList.Count;
|
|
|
|
/* Loop all the partials in this list */
|
|
for (j = 0; j < Count; j++)
|
|
{
|
|
/* Get the sort value at this point */
|
|
HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue);
|
|
|
|
/* Save the current sort pointer */
|
|
SortedRaw = CurrentRaw;
|
|
SortedTranslated = CurrentTranslated;
|
|
|
|
/* Loop all descriptors starting from this one */
|
|
for (k = j; k < Count; k++)
|
|
{
|
|
/* Get the sort value at the sort point */
|
|
HalpGetResourceSortValue(SortedRaw, &SortScale, &SortValue);
|
|
|
|
/* Check if a swap needs to occur */
|
|
if ((SortScale < CurrentScale) ||
|
|
((SortScale == CurrentScale) &&
|
|
(SortValue.QuadPart <= CurrentSortValue.QuadPart)))
|
|
{
|
|
/* Swap raw partial with the sort location partial */
|
|
RtlCopyMemory(&RawPartial, CurrentRaw, sizeof(RawPartial));
|
|
RtlCopyMemory(CurrentRaw, SortedRaw, sizeof(RawPartial));
|
|
RtlCopyMemory(SortedRaw, &RawPartial, sizeof(RawPartial));
|
|
|
|
/* Swap translated partial in the same way */
|
|
RtlCopyMemory(&TranslatedPartial, CurrentTranslated, sizeof(TranslatedPartial));
|
|
RtlCopyMemory(CurrentTranslated, SortedTranslated, sizeof(TranslatedPartial));
|
|
RtlCopyMemory(SortedTranslated, &TranslatedPartial, sizeof(TranslatedPartial));
|
|
|
|
/* Update the sort value at this point */
|
|
HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue);
|
|
}
|
|
|
|
/* The sort location has been updated */
|
|
SortedRaw++;
|
|
SortedTranslated++;
|
|
}
|
|
|
|
/* Move to the next partial */
|
|
CurrentRaw++;
|
|
CurrentTranslated++;
|
|
}
|
|
|
|
/* Move to the next full descriptor */
|
|
RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw;
|
|
TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated;
|
|
}
|
|
|
|
/* Mark this is an ACPI system, if it is */
|
|
HalpMarkAcpiHal();
|
|
|
|
/* Tell the kernel about all this */
|
|
IoReportHalResourceUsage(HalName,
|
|
RawList,
|
|
TranslatedList,
|
|
ListSize);
|
|
|
|
/* Free our lists */
|
|
ExFreePool(RawList);
|
|
ExFreePool(TranslatedList);
|
|
|
|
/* Get the machine's serial number */
|
|
HalpReportSerialNumber();
|
|
}
|
|
#endif
|
|
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpRegisterVector(IN UCHAR Flags,
|
|
IN ULONG BusVector,
|
|
IN ULONG SystemVector,
|
|
IN KIRQL Irql)
|
|
{
|
|
/* Save the vector flags */
|
|
HalpIDTUsageFlags[SystemVector].Flags = Flags;
|
|
|
|
/* Save the vector data */
|
|
HalpIDTUsage[SystemVector].Irql = Irql;
|
|
HalpIDTUsage[SystemVector].BusReleativeVector = (UCHAR)BusVector;
|
|
}
|
|
|
|
#ifndef _MINIHAL_
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpEnableInterruptHandler(IN UCHAR Flags,
|
|
IN ULONG BusVector,
|
|
IN ULONG SystemVector,
|
|
IN KIRQL Irql,
|
|
IN PVOID Handler,
|
|
IN KINTERRUPT_MODE Mode)
|
|
{
|
|
/* Set the IDT_LATCHED flag for latched interrupts */
|
|
if (Mode == Latched) Flags |= IDT_LATCHED;
|
|
|
|
/* Register the vector */
|
|
HalpRegisterVector(Flags, BusVector, SystemVector, Irql);
|
|
|
|
/* Connect the interrupt */
|
|
KeRegisterInterruptHandler(SystemVector, Handler);
|
|
|
|
/* Enable the interrupt */
|
|
HalEnableSystemInterrupt(SystemVector, Irql, Mode);
|
|
}
|
|
|
|
INIT_SECTION
|
|
VOID
|
|
NTAPI
|
|
HalpGetNMICrashFlag(VOID)
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CrashControl");
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
ULONG ResultLength;
|
|
HANDLE Handle;
|
|
NTSTATUS Status;
|
|
KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
|
|
|
/* Set default */
|
|
HalpNMIDumpFlag = 0;
|
|
|
|
/* Initialize attributes */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
/* Open crash key */
|
|
Status = ZwOpenKey(&Handle, KEY_READ, &ObjectAttributes);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Query key value */
|
|
RtlInitUnicodeString(&ValueName, L"NMICrashDump");
|
|
Status = ZwQueryValueKey(Handle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
&KeyValueInformation,
|
|
sizeof(KeyValueInformation),
|
|
&ResultLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Check for valid data */
|
|
if (ResultLength == sizeof(KEY_VALUE_PARTIAL_INFORMATION))
|
|
{
|
|
/* Read the flag */
|
|
HalpNMIDumpFlag = KeyValueInformation.Data[0];
|
|
}
|
|
}
|
|
|
|
/* We're done */
|
|
ZwClose(Handle);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* EOF */
|
|
|