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.
2510 lines
55 KiB
2510 lines
55 KiB
/*++
|
|
|
|
Copyright (c) 1990-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ops.c
|
|
|
|
Abstract:
|
|
|
|
video port stub routines for memory and io.
|
|
|
|
Author:
|
|
|
|
Andre Vachon (andreva) 22-Feb-1997
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
This module is a driver which implements OS dependant functions on the
|
|
behalf of the video drivers
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "videoprt.h"
|
|
|
|
#pragma alloc_text(PAGE,VideoPortGetAssociatedDeviceExtension)
|
|
#pragma alloc_text(PAGE,VideoPortGetAssociatedDeviceID)
|
|
#pragma alloc_text(PAGE,VideoPortAcquireDeviceLock)
|
|
#pragma alloc_text(PAGE,VideoPortReleaseDeviceLock)
|
|
#pragma alloc_text(PAGE,VideoPortGetRomImage)
|
|
#pragma alloc_text(PAGE,VpGetBusInterface)
|
|
#pragma alloc_text(PAGE,VideoPortGetVgaStatus)
|
|
#pragma alloc_text(PAGE,pVideoPortGetVgaStatusPci)
|
|
#pragma alloc_text(PAGE,VideoPortCheckForDeviceExistence)
|
|
#pragma alloc_text(PAGE,VpGetDeviceCount)
|
|
#pragma alloc_text(PAGE,VideoPortRegisterBugcheckCallback)
|
|
#pragma alloc_text(PAGE,VpAllocateNonPagedPoolPageAligned)
|
|
#pragma alloc_text(PAGE,VpAcquireLock)
|
|
#pragma alloc_text(PAGE,VpReleaseLock)
|
|
#pragma alloc_text(PAGE,pVpGeneralBugcheckHandler)
|
|
|
|
//
|
|
//ULONG
|
|
//VideoPortCompareMemory (
|
|
// PVOID Source1,
|
|
// PVOID Source2,
|
|
// ULONG Length
|
|
// )
|
|
//Forwarded to RtlCompareMemory(Source1,Source2,Length);
|
|
//
|
|
|
|
|
|
VP_STATUS
|
|
VideoPortDisableInterrupt(
|
|
IN PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortDisableInterrupt allows a miniport driver to disable interrupts
|
|
from its adapter. This means that the interrupts coming from the device
|
|
will be ignored by the operating system and therefore not forwarded to
|
|
the driver.
|
|
|
|
A call to this function is valid only if the interrupt is defined, in
|
|
other words, if the appropriate data was provided at initialization
|
|
time to set up the interrupt. Interrupts will remain disabled until
|
|
they are reenabled using the VideoPortEnableInterrupt function.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if the function completes successfully.
|
|
|
|
ERROR_INVALID_FUNCTION if the interrupt cannot be disabled because it
|
|
was not set up at initialization.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
//
|
|
// Only perform this operation if the interurpt is actually connected.
|
|
//
|
|
|
|
if (fdoExtension->InterruptObject) {
|
|
|
|
#if defined(_IA64_)
|
|
//
|
|
// The old code here would actually disable interrupts for
|
|
// the device's vector on whatever processor this thread
|
|
// happened to be running on. This would have a couple of
|
|
// possible outcomes:
|
|
//
|
|
// 1) All devices on this vector would stop interrupting.
|
|
// Remember that PCI and AGP require the possibility
|
|
// of interrupt sharing. This might mean, for instance
|
|
// that the SCSI controller would stop paging.
|
|
//
|
|
// 2) Some other processor would still handle interrupts
|
|
// for this device, meaning that the call would be
|
|
// meaningless.
|
|
//
|
|
// Additionally, there was no guarantee that
|
|
// VidePortDisableInterrupt would be called on the same
|
|
// processor as this function. So it could frequently
|
|
// be the case that this vector would never be re-enabled
|
|
// on this processor.
|
|
//
|
|
// Given all of this, I am just turning this function into
|
|
// a no-op, since it can't be made to work in an architec-
|
|
// turally coherent fashion. -- JakeO 11/1/2002
|
|
//
|
|
// Due to test limitation we disabling it just for IA64
|
|
// -- OlegK 1/9/2003
|
|
#else
|
|
HalDisableSystemInterrupt(fdoExtension->InterruptVector,
|
|
fdoExtension->InterruptIrql);
|
|
#endif // defined(_IA64_)
|
|
|
|
|
|
fdoExtension->InterruptsEnabled = FALSE;
|
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
return ERROR_INVALID_FUNCTION;
|
|
|
|
}
|
|
|
|
} // VideoPortDisableInterrupt()
|
|
|
|
|
|
VP_STATUS
|
|
VideoPortEnableInterrupt(
|
|
IN PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortEnableInterrupt allows a miniport driver to enable interrupts
|
|
from its adapter. A call to this function is valid only if the
|
|
interrupt is defined, in other words, if the appropriate data was
|
|
provided at initialization time to set up the interrupt.
|
|
|
|
This function is used to re-enable interrupts if they have been disabled
|
|
using VideoPortDisableInterrupt.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if the function completes successfully.
|
|
|
|
ERROR_INVALID_FUNCTION if the interrupt cannot be disabled because it
|
|
was not set up at initialization.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
//
|
|
// Only perform this operation if the interurpt is actually connected.
|
|
//
|
|
|
|
if (fdoExtension->InterruptObject) {
|
|
|
|
fdoExtension->InterruptsEnabled = TRUE;
|
|
|
|
#if defined(_IA64_)
|
|
//
|
|
// The old code here would actually disable interrupts for
|
|
// the device's vector on whatever processor this thread
|
|
// happened to be running on. This would have a couple of
|
|
// possible outcomes:
|
|
//
|
|
// 1) All devices on this vector would stop interrupting.
|
|
// Remember that PCI and AGP require the possibility
|
|
// of interrupt sharing. This might mean, for instance
|
|
// that the SCSI controller would stop paging.
|
|
//
|
|
// 2) Some other processor would still handle interrupts
|
|
// for this device, meaning that the call would be
|
|
// meaningless.
|
|
//
|
|
// Additionally, there was no guarantee that
|
|
// VidePortDisableInterrupt would be called on the same
|
|
// processor as this function. So it could frequently
|
|
// be the case that this vector would never be re-enabled
|
|
// on this processor.
|
|
//
|
|
// Given all of this, I am just turning this function into
|
|
// a no-op, since it can't be made to work in an architec-
|
|
// turally coherent fashion. -- JakeO 11/1/2002
|
|
//
|
|
// Due to test limitation we disabling it just for IA64
|
|
// -- OlegK 1/9/2003
|
|
#else
|
|
HalEnableSystemInterrupt(fdoExtension->InterruptVector,
|
|
fdoExtension->InterruptIrql,
|
|
fdoExtension->InterruptMode);
|
|
#endif // defined(_IA64_)
|
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
return ERROR_INVALID_FUNCTION;
|
|
|
|
}
|
|
|
|
} // VideoPortEnableInterrupt()
|
|
|
|
PVOID
|
|
VideoPortGetRomImage(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PVOID Unused1,
|
|
IN ULONG Unused2,
|
|
IN ULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allows a miniport driver to get a copy of its devices
|
|
ROM. This function returns the pointer to a buffer containing the
|
|
devices ROM.
|
|
|
|
Arguments;
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension.
|
|
|
|
Unused1 - Reserved for future use. Must be NULL. (Buffer)
|
|
|
|
Unused2 - Reserved for future use. Must be zero. (Offset)
|
|
|
|
Length - Number of bytes to return.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
#if DBG
|
|
if ((Unused1 != NULL) || (Unused2 != 0)) {
|
|
pVideoDebugPrint((0,"VideoPortGetRomImage - Unused1 and Unused2 must be zero\n"));
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Each time this routine is called the previous contents of the ROM
|
|
// image are dropped.
|
|
//
|
|
|
|
if (fdoExtension->RomImage) {
|
|
ExFreePool(fdoExtension->RomImage);
|
|
fdoExtension->RomImage = NULL;
|
|
}
|
|
|
|
//
|
|
// The caller should try to grab a buffer of length zero to free
|
|
// any ROM Image already returned.
|
|
//
|
|
|
|
if (Length == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// This entry point is only valid for PnP Drivers.
|
|
//
|
|
|
|
if (((fdoExtension->Flags & LEGACY_DRIVER) == 0) &&
|
|
fdoExtension->ValidBusInterface) {
|
|
|
|
NTSTATUS status;
|
|
PUCHAR Buffer;
|
|
ULONG len, len1;
|
|
PUCHAR outputBuffer;
|
|
|
|
//
|
|
// Allocate memory for our buffer
|
|
//
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
Length * sizeof(UCHAR),
|
|
VP_TAG);
|
|
|
|
if (!Buffer) {
|
|
|
|
pVideoDebugPrint((1, "VideoPortGetRomImage - could not allocate buffer\n"));
|
|
return NULL;
|
|
}
|
|
|
|
// Try ACPI _ROM method first
|
|
outputBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
(0x1000 + sizeof(ACPI_EVAL_OUTPUT_BUFFER))*sizeof(UCHAR),
|
|
VP_TAG);
|
|
if (!outputBuffer) {
|
|
ExFreePool(Buffer);
|
|
pVideoDebugPrint((1, "VideoPortGetRomImage - could not allocate buffer\n"));
|
|
return NULL;
|
|
}
|
|
|
|
for (len = 0; len < Length; len += len1)
|
|
{
|
|
// _ROM can transfer only 4K at one time
|
|
len1 = ((Length-len) < 0x1000) ? (Length-len) : 0x1000;
|
|
status = pVideoPortACPIIoctl(
|
|
fdoExtension->AttachedDeviceObject,
|
|
(ULONG) ('MOR_'),
|
|
&len,
|
|
&len1,
|
|
len1+sizeof(ACPI_EVAL_OUTPUT_BUFFER),
|
|
(PACPI_EVAL_OUTPUT_BUFFER) outputBuffer);
|
|
if (!NT_SUCCESS(status))
|
|
break;
|
|
RtlCopyMemory(Buffer+len,
|
|
((PACPI_EVAL_OUTPUT_BUFFER)outputBuffer)->Argument[0].Data,
|
|
len1 * sizeof(UCHAR));
|
|
}
|
|
|
|
ExFreePool(outputBuffer);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
fdoExtension->RomImage = Buffer;
|
|
return Buffer;
|
|
}
|
|
|
|
// If ACPI _ROM method failed
|
|
Length = fdoExtension->BusInterface.GetBusData(
|
|
fdoExtension->BusInterface.Context,
|
|
PCI_WHICHSPACE_ROM,
|
|
Buffer,
|
|
0,
|
|
Length);
|
|
|
|
if (Length) {
|
|
|
|
fdoExtension->RomImage = Buffer;
|
|
return Buffer;
|
|
|
|
} else {
|
|
|
|
ExFreePool(Buffer);
|
|
return NULL;
|
|
}
|
|
|
|
} else {
|
|
|
|
pVideoDebugPrint((0, "VideoPortGetRomImage - not supported on legacy devices\n"));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
ULONG
|
|
VideoPortGetBusData(
|
|
PVOID HwDeviceExtension,
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
if ((fdoExtension->Flags & LEGACY_DRIVER) ||
|
|
(BusDataType != PCIConfiguration)) {
|
|
|
|
#if defined(NO_LEGACY_DRIVERS)
|
|
pVideoDebugPrint((0, "VideoPortGetBusData: fdoExtension->Flags & LEGACY_DRIVER not supported for 64-bits.\n"));
|
|
|
|
return 0;
|
|
|
|
#else
|
|
return HalGetBusDataByOffset(BusDataType,
|
|
fdoExtension->SystemIoBusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
#endif // NO_LEGACY_DRIVERS
|
|
|
|
} else {
|
|
|
|
if (fdoExtension->ValidBusInterface) {
|
|
Length = fdoExtension->BusInterface.GetBusData(
|
|
fdoExtension->BusInterface.Context,
|
|
PCI_WHICHSPACE_CONFIG,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
|
|
return Length;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
} // end VideoPortGetBusData()
|
|
|
|
|
|
UCHAR
|
|
VideoPortGetCurrentIrql(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stub to get Current Irql.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return (KeGetCurrentIrql());
|
|
|
|
} // VideoPortGetCurrentIrql()
|
|
|
|
|
|
ULONG
|
|
VideoPortSetBusData(
|
|
PVOID HwDeviceExtension,
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
|
|
{
|
|
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
if ((fdoExtension->Flags & LEGACY_DRIVER) ||
|
|
(BusDataType != PCIConfiguration)) {
|
|
|
|
#if defined(NO_LEGACY_DRIVERS)
|
|
pVideoDebugPrint((0, "VideoPortSetBusData: fdoExtension->Flags & LEGACY_DRIVER not supported for 64-bits.\n"));
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return HalSetBusDataByOffset(BusDataType,
|
|
fdoExtension->SystemIoBusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
#endif // NO_LEGACY_DRIVERS
|
|
|
|
} else {
|
|
|
|
if (fdoExtension->ValidBusInterface) {
|
|
Length = fdoExtension->BusInterface.SetBusData(
|
|
fdoExtension->BusInterface.Context,
|
|
PCI_WHICHSPACE_CONFIG,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
|
|
return Length;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
} // end VideoPortSetBusData()
|
|
|
|
|
|
//
|
|
//VOID
|
|
//VideoPortStallExecution(
|
|
// IN ULONG Microseconds
|
|
// )
|
|
//
|
|
//Forwarded to KeStallExecutionProcessor(Microseconds);
|
|
//
|
|
|
|
|
|
//
|
|
//VOID
|
|
//VideoPortMoveMemory(
|
|
// IN PVOID Destination,
|
|
// IN PVOID Source,
|
|
// IN ULONG Length
|
|
// )
|
|
//
|
|
//Forwarded to RtlMoveMemory(Destination,Source,Length);
|
|
//
|
|
|
|
|
|
//
|
|
// ALL the functions to read ports and registers are forwarded on free
|
|
// builds on x86 to the appropriate kernel function.
|
|
// This saves time and memory
|
|
//
|
|
|
|
#if DBG || !defined(_X86_)
|
|
|
|
UCHAR
|
|
VideoPortReadPortUchar(
|
|
IN PUCHAR Port
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortUchar reads a byte from the specified port address.
|
|
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Return Value:
|
|
|
|
This function returns the byte read from the specified port address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UCHAR temp;
|
|
|
|
temp = READ_PORT_UCHAR(Port);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadPortUchar %x = %x\n", Port, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadPortUchar()
|
|
|
|
USHORT
|
|
VideoPortReadPortUshort(
|
|
IN PUSHORT Port
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortUshort reads a word from the specified port address.
|
|
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
|
|
Return Value:
|
|
|
|
This function returns the word read from the specified port address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
USHORT temp;
|
|
|
|
temp = READ_PORT_USHORT(Port);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadPortUshort %x = %x\n", Port, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadPortUshort()
|
|
|
|
ULONG
|
|
VideoPortReadPortUlong(
|
|
IN PULONG Port
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortUlong reads a double word from the specified port
|
|
address. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Return Value:
|
|
|
|
This function returns the double word read from the specified port address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG temp;
|
|
|
|
temp = READ_PORT_ULONG(Port);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadPortUlong %x = %x\n", Port, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadPortUlong()
|
|
|
|
VOID
|
|
VideoPortReadPortBufferUchar(
|
|
IN PUCHAR Port,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortBufferUchar reads a number of bytes from a single port
|
|
into a buffer. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of UCHAR values into which the values are
|
|
stored.
|
|
|
|
Count - Specifes the number of bytes to be read into the buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
pVideoDebugPrint((3,"VideoPortReadPortBufferUchar %x\n", Port));
|
|
|
|
READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
|
|
|
|
} // VideoPortReadPortBufferUchar()
|
|
|
|
VOID
|
|
VideoPortReadPortBufferUshort(
|
|
IN PUSHORT Port,
|
|
IN PUSHORT Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortBufferUshort reads a number of words from a single port
|
|
into a buffer. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of words into which the values are stored.
|
|
|
|
Count - Specifies the number of words to be read into the buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
pVideoDebugPrint((3,"VideoPortReadPortBufferUshort %x\n", Port));
|
|
|
|
READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
|
|
|
|
} // VideoPortReadPortBufferUshort()
|
|
|
|
VOID
|
|
VideoPortReadPortBufferUlong(
|
|
IN PULONG Port,
|
|
IN PULONG Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadPortBufferUlong reads a number of double words from a
|
|
single port into a buffer. It requires a logical port address obtained
|
|
from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of double words into which the values are
|
|
stored.
|
|
|
|
Count - Specifies the number of double words to be read into the buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadPortBufferUlong %x\n", Port));
|
|
|
|
READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
|
|
|
|
} // VideoPortReadPortBufferUlong()
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// ALL the functions to read ports and registers are forwarded on free
|
|
// builds on x86 to the appropriate kernel function.
|
|
// This saves time and memory
|
|
//
|
|
|
|
#if DBG || !defined(_X86_)
|
|
|
|
UCHAR
|
|
VideoPortReadRegisterUchar(
|
|
IN PUCHAR Register
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadRegisterUchar reads a byte from the specified register
|
|
address. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Return Value:
|
|
|
|
This function returns the byte read from the specified register address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UCHAR temp;
|
|
|
|
temp = READ_REGISTER_UCHAR(Register);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadRegisterUchar %x = %x\n", Register, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadRegisterUchar()
|
|
|
|
USHORT
|
|
VideoPortReadRegisterUshort(
|
|
IN PUSHORT Register
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadRegisterUshort reads a word from the specified register
|
|
address. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Return Value:
|
|
|
|
This function returns the word read from the specified register address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
USHORT temp;
|
|
|
|
temp = READ_REGISTER_USHORT(Register);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadRegisterUshort %x = %x\n", Register, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadRegisterUshort()
|
|
|
|
ULONG
|
|
VideoPortReadRegisterUlong(
|
|
IN PULONG Register
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortReadRegisterUlong reads a double word from the specified
|
|
register address. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Return Value:
|
|
|
|
This function returns the double word read from the specified register
|
|
address.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG temp;
|
|
|
|
temp = READ_REGISTER_ULONG(Register);
|
|
|
|
pVideoDebugPrint((3,"VideoPortReadRegisterUlong %x = %x\n", Register, temp));
|
|
|
|
return(temp);
|
|
|
|
} // VideoPortReadRegisterUlong()
|
|
|
|
VOID
|
|
VideoPortReadRegisterBufferUchar(
|
|
IN PUCHAR Register,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a buffer of unsigned bytes from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
|
|
}
|
|
|
|
VOID
|
|
VideoPortReadRegisterBufferUshort(
|
|
IN PUSHORT Register,
|
|
IN PUSHORT Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a buffer of unsigned shorts from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
|
|
}
|
|
|
|
VOID
|
|
VideoPortReadRegisterBufferUlong(
|
|
IN PULONG Register,
|
|
IN PULONG Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a buffer of unsigned longs from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
|
|
}
|
|
|
|
VOID
|
|
VideoPortWritePortUchar(
|
|
IN PUCHAR Port,
|
|
IN UCHAR Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortUchar writes a byte to the specified port address. It
|
|
requires a logical port address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Value - Specifies a byte to be written to the port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
pVideoDebugPrint((3,"VideoPortWritePortUchar %x %x\n", Port, Value));
|
|
|
|
WRITE_PORT_UCHAR(Port, Value);
|
|
|
|
} // VideoPortWritePortUchar()
|
|
|
|
VOID
|
|
VideoPortWritePortUshort(
|
|
IN PUSHORT Port,
|
|
IN USHORT Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortUshort writes a word to the specified port address. It
|
|
requires a logical port address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Value - Specifies a word to be written to the port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
pVideoDebugPrint((3,"VideoPortWritePortUhort %x %x\n", Port, Value));
|
|
|
|
WRITE_PORT_USHORT(Port, Value);
|
|
|
|
} // VideoPortWritePortUshort()
|
|
|
|
VOID
|
|
VideoPortWritePortUlong(
|
|
IN PULONG Port,
|
|
IN ULONG Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortUlong writes a double word to the specified port address.
|
|
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Value - Specifies a double word to be written to the port.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortUlong %x %x\n", Port, Value));
|
|
|
|
WRITE_PORT_ULONG(Port, Value);
|
|
|
|
} // VideoPortWritePortUlong()
|
|
|
|
VOID
|
|
VideoPortWritePortBufferUchar(
|
|
IN PUCHAR Port,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortBufferUchar writes a number of bytes to a
|
|
specific port. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of bytes to be written.
|
|
|
|
Count - Specifies the number of bytes to be written to the buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortBufferUchar %x \n", Port));
|
|
|
|
WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
|
|
|
|
} // VideoPortWritePortBufferUchar()
|
|
|
|
VOID
|
|
VideoPortWritePortBufferUshort(
|
|
IN PUSHORT Port,
|
|
IN PUSHORT Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortBufferUshort writes a number of words to a
|
|
specific port. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of words to be written.
|
|
|
|
Count - Specifies the number of words to be written to the buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortBufferUshort %x \n", Port));
|
|
|
|
WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
|
|
|
|
} // VideoPortWritePortBufferUshort()
|
|
|
|
VOID
|
|
VideoPortWritePortBufferUlong(
|
|
IN PULONG Port,
|
|
IN PULONG Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWritePortBufferUlong writes a number of double words to a
|
|
specific port. It requires a logical port address obtained from
|
|
VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Port - Specifies the port address.
|
|
|
|
Buffer - Points to an array of double word to be written.
|
|
|
|
Count - Specifies the number of double words to be written to the buffer.
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
pVideoDebugPrint((3,"VideoPortWriteBufferUlong %x \n", Port));
|
|
|
|
WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
|
|
|
|
} // VideoPortWritePortBufferUlong()
|
|
|
|
VOID
|
|
VideoPortWriteRegisterUchar(
|
|
IN PUCHAR Register,
|
|
IN UCHAR Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWriteRegisterUchar writes a byte to the specified
|
|
register address. It requires a logical port address obtained
|
|
from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Value - Specifies a byte to be written to the register.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortRegisterUchar %x \n", Register));
|
|
|
|
WRITE_REGISTER_UCHAR(Register, Value);
|
|
|
|
} // VideoPortWriteRegisterUchar()
|
|
|
|
VOID
|
|
VideoPortWriteRegisterUshort(
|
|
IN PUSHORT Register,
|
|
IN USHORT Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWriteRegisterUshort writes a word to the specified
|
|
register address. It requires a logical port address obtained
|
|
from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Value - Specifies a word to be written to the register.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortRegisterUshort %x \n", Register));
|
|
|
|
WRITE_REGISTER_USHORT(Register, Value);
|
|
|
|
} // VideoPortWriteRegisterUshort()
|
|
|
|
VOID
|
|
VideoPortWriteRegisterUlong(
|
|
IN PULONG Register,
|
|
IN ULONG Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortWriteRegisterUlong writes a double word to the
|
|
specified register address. It requires a logical port
|
|
address obtained from VideoPortGetDeviceBase.
|
|
|
|
Arguments:
|
|
|
|
Register - Specifies the register address.
|
|
|
|
Value - Specifies a double word to be written to the register.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
pVideoDebugPrint((3,"VideoPortWritePortRegisterUlong %x \n", Register));
|
|
|
|
WRITE_REGISTER_ULONG(Register, Value);
|
|
|
|
} // VideoPortWriteRegisterUlong()
|
|
|
|
|
|
VOID
|
|
VideoPortWriteRegisterBufferUchar(
|
|
IN PUCHAR Register,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write a buffer of unsigned bytes from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
|
|
}
|
|
|
|
VOID
|
|
VideoPortWriteRegisterBufferUshort(
|
|
IN PUSHORT Register,
|
|
IN PUSHORT Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write a buffer of unsigned shorts from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
|
|
}
|
|
|
|
VOID
|
|
VideoPortWriteRegisterBufferUlong(
|
|
IN PULONG Register,
|
|
IN PULONG Buffer,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write a buffer of unsigned longs from the specified register address.
|
|
|
|
Arguments:
|
|
|
|
Register - Supplies a pointer to the port address.
|
|
Buffer - Supplies a pointer to the data buffer area.
|
|
Count - The count of items to move.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
//
|
|
//VOID
|
|
//VideoPortZeroMemory(
|
|
// IN PVOID Destination,
|
|
// IN ULONG Length
|
|
// )
|
|
//
|
|
//Forwarded to RtlZeroMemory(Destination,Length);
|
|
//
|
|
|
|
PVOID
|
|
VideoPortGetAssociatedDeviceExtension(
|
|
IN PVOID DeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will return the HwDeviceExtension for the parent of the
|
|
given device object.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The child device object (PDO).
|
|
|
|
Notes:
|
|
|
|
This function is useful if you want to get the parent device extension
|
|
for a child device object. For example this is useful with I2C.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION DeviceExtension;
|
|
PCHILD_PDO_EXTENSION ChildDeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
ASSERT(NULL != DeviceObject);
|
|
|
|
ChildDeviceExtension = (PCHILD_PDO_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
|
|
|
|
if (!IS_PDO(ChildDeviceExtension)) {
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
DeviceExtension = (PFDO_EXTENSION)ChildDeviceExtension->pFdoExtension;
|
|
return (PVOID) DeviceExtension->HwDeviceExtension;
|
|
}
|
|
|
|
ULONG
|
|
VideoPortGetAssociatedDeviceID(
|
|
IN PVOID DeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will return the ChildId for the given device object.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The child device object (PDO).
|
|
|
|
Notes:
|
|
|
|
This function is useful if you want to get the child ID
|
|
for a child device object. For example this is useful with I2C.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHILD_PDO_EXTENSION ChildDeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
ASSERT(NULL != DeviceObject);
|
|
|
|
ChildDeviceExtension = (PCHILD_PDO_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
|
|
|
|
if (!IS_PDO(ChildDeviceExtension)) {
|
|
ASSERT(FALSE);
|
|
return VIDEO_INVALID_CHILD_ID;
|
|
}
|
|
|
|
return ChildDeviceExtension->ChildUId;
|
|
}
|
|
|
|
VOID
|
|
VideoPortAcquireDeviceLock(
|
|
IN PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine acquires the per device lock maintained by the videoprt.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the hardware device extension.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
ACQUIRE_DEVICE_LOCK(fdoExtension);
|
|
}
|
|
|
|
VOID
|
|
VideoPortReleaseDeviceLock(
|
|
IN PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine releases the per device lock maintained by the videoprt.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the hardware device extension.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
RELEASE_DEVICE_LOCK(fdoExtension);
|
|
}
|
|
|
|
PVOID
|
|
VpGetProcAddress(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PUCHAR FunctionName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allows a video miniport to get access to VideoPort
|
|
functions without linking to them directly. This will allow an NT 5.0
|
|
miniport to take advantage of NT 5.0 features while running on NT 5.0,
|
|
but still retain the ability to load on NT 4.0.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the hardware device extension.
|
|
|
|
FunctionName - pointer to a zero terminated ascii string which contains
|
|
the function name we are looking for.
|
|
|
|
Returns:
|
|
|
|
Pointer to the given function if it exists.
|
|
NULL otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
PPROC_ADDRESS ProcAddress = VideoPortEntryPoints;
|
|
|
|
//
|
|
// Since the list of exported functions is small, and this routine
|
|
// will not be called often we can get away with a linear search.
|
|
//
|
|
|
|
while (ProcAddress->FunctionName) {
|
|
|
|
if (strcmp(ProcAddress->FunctionName, FunctionName) == 0) {
|
|
return ProcAddress->FunctionAddress;
|
|
}
|
|
|
|
ProcAddress++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
NTSTATUS
|
|
VpGetBusInterface(
|
|
PFDO_EXTENSION FdoExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send a QueryInterface Irp to our parent to retrieve
|
|
the BUS_INTERFACE_STANDARD.
|
|
|
|
Returns:
|
|
|
|
NT_STATUS code
|
|
|
|
--*/
|
|
|
|
{
|
|
KEVENT Event;
|
|
PIRP QueryIrp = NULL;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PIO_STACK_LOCATION NextStack;
|
|
NTSTATUS Status;
|
|
|
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
|
|
|
QueryIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
|
|
FdoExtension->AttachedDeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&IoStatusBlock);
|
|
|
|
if (QueryIrp == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
QueryIrp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
NextStack = IoGetNextIrpStackLocation(QueryIrp);
|
|
|
|
//
|
|
// Set up for a QueryInterface Irp.
|
|
//
|
|
|
|
NextStack->MajorFunction = IRP_MJ_PNP;
|
|
NextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
|
|
NextStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
|
|
NextStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
|
NextStack->Parameters.QueryInterface.Version = 1;
|
|
NextStack->Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->BusInterface;
|
|
NextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|
|
|
FdoExtension->BusInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
|
FdoExtension->BusInterface.Version = 1;
|
|
|
|
Status = IoCallDriver(FdoExtension->AttachedDeviceObject, QueryIrp);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOLEAN
|
|
VideoPortCheckForDeviceExistence(
|
|
IN PVOID HwDeviceExtension,
|
|
IN USHORT VendorId,
|
|
IN USHORT DeviceId,
|
|
IN UCHAR RevisionId,
|
|
IN USHORT SubVendorId,
|
|
IN USHORT SubSystemId,
|
|
IN ULONG Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks for the existance of a given PCI device in the system.
|
|
|
|
Returns:
|
|
|
|
TRUE if the device is present,
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION FdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
BOOLEAN Result = FALSE;
|
|
|
|
if ((FdoExtension->Flags & LEGACY_DRIVER) == 0) {
|
|
|
|
KEVENT Event;
|
|
PIRP QueryIrp = NULL;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PIO_STACK_LOCATION NextStack;
|
|
NTSTATUS Status;
|
|
|
|
PCI_DEVICE_PRESENT_INTERFACE Interface;
|
|
|
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
|
|
|
QueryIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
|
|
FdoExtension->AttachedDeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&IoStatusBlock);
|
|
|
|
if (QueryIrp == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
QueryIrp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
NextStack = IoGetNextIrpStackLocation(QueryIrp);
|
|
|
|
//
|
|
// Set up for a QueryInterface Irp.
|
|
//
|
|
|
|
NextStack->MajorFunction = IRP_MJ_PNP;
|
|
NextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
|
|
NextStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE;
|
|
NextStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
|
|
NextStack->Parameters.QueryInterface.Version = 1;
|
|
NextStack->Parameters.QueryInterface.Interface = (PINTERFACE) &Interface;
|
|
NextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|
|
|
FdoExtension->BusInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
|
|
FdoExtension->BusInterface.Version = 1;
|
|
|
|
Status = IoCallDriver(FdoExtension->AttachedDeviceObject, QueryIrp);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// We were able to acquire the interface. Check for our device.
|
|
//
|
|
|
|
Interface.InterfaceReference(Interface.Context);
|
|
|
|
Result = Interface.IsDevicePresent(VendorId,
|
|
DeviceId,
|
|
RevisionId,
|
|
SubVendorId,
|
|
SubSystemId,
|
|
Flags);
|
|
|
|
Interface.InterfaceDereference(Interface.Context);
|
|
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
//
|
|
// Use these until I can make forwarders work.
|
|
//
|
|
|
|
LONG
|
|
FASTCALL
|
|
VideoPortInterlockedExchange(
|
|
IN OUT PLONG Target,
|
|
IN LONG Value
|
|
)
|
|
|
|
{
|
|
return InterlockedExchange(Target, Value);
|
|
}
|
|
|
|
LONG
|
|
FASTCALL
|
|
VideoPortInterlockedIncrement(
|
|
IN PLONG Addend
|
|
)
|
|
|
|
{
|
|
return InterlockedIncrement(Addend);
|
|
}
|
|
|
|
LONG
|
|
FASTCALL
|
|
VideoPortInterlockedDecrement(
|
|
IN PLONG Addend
|
|
)
|
|
|
|
{
|
|
return InterlockedDecrement(Addend);
|
|
}
|
|
|
|
VP_STATUS
|
|
VideoPortGetVgaStatus(
|
|
PVOID HwDeviceExtension,
|
|
OUT PULONG VgaStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortGetVgaStatus detect if the calling device is decoding
|
|
Vga IO address
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension
|
|
VgaStatus - Points to the the result
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if the function completes successfully.
|
|
|
|
ERROR_INVALID_FUNCTION if it is a non-PCI device
|
|
|
|
--*/
|
|
{
|
|
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
//
|
|
// We can not handle legacy devices
|
|
//
|
|
|
|
if (fdoExtension->AdapterInterfaceType != PCIBus) {
|
|
|
|
*VgaStatus = 0;
|
|
|
|
return ERROR_INVALID_FUNCTION;
|
|
}
|
|
else {
|
|
|
|
*VgaStatus = pVideoPortGetVgaStatusPci( HwDeviceExtension );
|
|
return (NO_ERROR);
|
|
|
|
}
|
|
}
|
|
|
|
#define VGA_STATUS_REGISTER1 0x3DA
|
|
|
|
ULONG
|
|
pVideoPortGetVgaStatusPci(
|
|
PVOID HwDeviceExtension
|
|
)
|
|
|
|
{
|
|
|
|
USHORT Command;
|
|
PCI_COMMON_CONFIG ConfigSpace;
|
|
PHYSICAL_ADDRESS PhysicalAddress;
|
|
PUCHAR BaseReg;
|
|
ULONG VgaEnable;
|
|
|
|
//
|
|
// assume VGA is disabled
|
|
//
|
|
|
|
VgaEnable = 0;
|
|
|
|
//
|
|
// Get the PCI config for this device
|
|
//
|
|
|
|
VideoPortGetBusData( HwDeviceExtension,
|
|
PCIConfiguration,
|
|
0,
|
|
&ConfigSpace,
|
|
0,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
|
|
|
|
if( !(ConfigSpace.Command & PCI_ENABLE_IO_SPACE) ) {
|
|
|
|
return VgaEnable;
|
|
|
|
}
|
|
|
|
if (((ConfigSpace.BaseClass == PCI_CLASS_PRE_20) &&
|
|
(ConfigSpace.SubClass == PCI_SUBCLASS_PRE_20_VGA)) ||
|
|
((ConfigSpace.BaseClass == PCI_CLASS_DISPLAY_CTLR) &&
|
|
(ConfigSpace.SubClass == PCI_SUBCLASS_VID_VGA_CTLR))) {
|
|
|
|
|
|
//
|
|
// Map the VGA registers we are going to use.
|
|
//
|
|
|
|
PhysicalAddress.HighPart = 0;
|
|
PhysicalAddress.LowPart = VGA_STATUS_REGISTER1;
|
|
|
|
BaseReg = VideoPortGetDeviceBase(HwDeviceExtension,
|
|
PhysicalAddress,
|
|
1,
|
|
VIDEO_MEMORY_SPACE_IO);
|
|
|
|
if (BaseReg) {
|
|
|
|
//
|
|
// If we got here the PCI config space for our device indicates
|
|
// we are the VGA, and we were able to map the VGA resources.
|
|
//
|
|
|
|
VgaEnable = DEVICE_VGA_ENABLED;
|
|
|
|
VideoPortFreeDeviceBase(HwDeviceExtension, BaseReg);
|
|
}
|
|
}
|
|
|
|
return VgaEnable;
|
|
}
|
|
|
|
VOID
|
|
pVideoPortDpcDispatcher(
|
|
IN PKDPC Dpc,
|
|
IN PVOID HwDeviceExtension,
|
|
IN PMINIPORT_DPC_ROUTINE DpcRoutine,
|
|
IN PVOID Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles DPCs and forwards them to the miniport callback
|
|
routine.
|
|
|
|
Arguments:
|
|
|
|
Dpc - The DPC which is executing.
|
|
|
|
HwDeviceExtension - The HwDeviceExtension for the device which scheduled
|
|
the DPC.
|
|
|
|
DpcRoutine - The callback in the miniport which needs to be called.
|
|
|
|
Context - The miniport supplied context.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DpcRoutine(HwDeviceExtension, Context);
|
|
}
|
|
|
|
BOOLEAN
|
|
VideoPortQueueDpc(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
|
|
IN PVOID Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allows a miniport driver to queue a DPC.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - The HwDeviceExtension for the miniport.
|
|
|
|
CallbackRoutine - The entry point within the miniport to call when the DPC
|
|
is scheduled.
|
|
|
|
Context - A miniport supplies context which will be passed to the
|
|
CallbackRoutine.
|
|
|
|
Returns:
|
|
|
|
TRUE if successful,
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
|
|
return KeInsertQueueDpc(&fdoExtension->Dpc, CallbackRoutine, Context);
|
|
}
|
|
|
|
ULONG
|
|
VpGetDeviceCount(
|
|
IN PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of started devices.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - The HwDeviceExtension for the miniport.
|
|
|
|
Returns:
|
|
|
|
The number of started devices.
|
|
|
|
--*/
|
|
|
|
{
|
|
return NumDevicesStarted;
|
|
}
|
|
|
|
VOID
|
|
pVpBugcheckCallback(
|
|
IN KBUGCHECK_CALLBACK_REASON Reason,
|
|
IN PKBUGCHECK_REASON_CALLBACK_RECORD Record,
|
|
IN OUT PVOID ReasonSpecificData,
|
|
IN ULONG ReasonSpecificDataLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This callback is called when a bugcheck occurs. It allows the
|
|
videoprt an opportunity to store data which can later be used
|
|
to help diagnose the bugcheck.
|
|
|
|
Arguments:
|
|
|
|
Reason - the reason we are being called
|
|
|
|
Record - a pointer to the bugcheck reason record we set up
|
|
|
|
ReasonSpecificData - pointer to KBUGCHECK_SECONDARY_DUMP_DATA
|
|
|
|
ReasonSpecificDataLength - the size of the reason specific data
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
This routine can be called at any time, and must not be pageable.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG BugcheckCode;
|
|
PKBUGCHECK_SECONDARY_DUMP_DATA DumpData
|
|
= (PKBUGCHECK_SECONDARY_DUMP_DATA)ReasonSpecificData;
|
|
|
|
//
|
|
// Only handle secondary dumps
|
|
//
|
|
|
|
if (Reason != KbCallbackSecondaryDumpData) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Grab the bugcheck code. We only handle EA currently.
|
|
//
|
|
|
|
BugcheckCode = *((PULONG)KiBugCheckData[0]);
|
|
|
|
if (BugcheckCode == 0xEA) {
|
|
pVpGeneralBugcheckHandler(DumpData);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
pVpGeneralBugcheckHandler(
|
|
PKBUGCHECK_SECONDARY_DUMP_DATA DumpData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls all of the hooked bugcheck callbacks,
|
|
and appends the data into the supplied buffer.
|
|
|
|
Arguments:
|
|
|
|
DumpData - pointer to the location in which to store the dump data
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
if (VpBugcheckDeviceObject != NULL) {
|
|
|
|
#if DBG
|
|
const char szDumpCanary[] = "kirgudu! barban bia!";
|
|
|
|
C_ASSERT((sizeof(szDumpCanary) + MAX_SECONDARY_DUMP_SIZE) <= PAGE_SIZE);
|
|
|
|
// XXX olegk - Must be removed for Longhorn
|
|
C_ASSERT(sizeof(szDumpCanary) <= BUGCHECK_DATA_SIZE_RESERVED);
|
|
|
|
char* pCanaryLocation = (char*)(VpBugcheckData) + MAX_SECONDARY_DUMP_SIZE -
|
|
sizeof(DUMP_BLOB_FILE_HEADER) - sizeof(DUMP_BLOB_HEADER); // remove it for Longhorn
|
|
#endif // DBG
|
|
|
|
//
|
|
// It is possible that the device object stored in VpBugcheckDeviceObject
|
|
// is actually an upper level filter. Therefore we can't assume it is
|
|
// actually our device object. Instead we'll have to get the lowest level
|
|
// device object, and scan our list of FDO's for the one that is attached.
|
|
//
|
|
|
|
PDEVICE_OBJECT pdo = VpBugcheckDeviceObject;
|
|
|
|
PFDO_EXTENSION FdoExtension = VpBugcheckDeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// Fill in the GUID, output buffer, and output buffer length
|
|
//
|
|
|
|
DumpData->OutBuffer = VpBugcheckData;
|
|
DumpData->OutBufferLength = FdoExtension->BugcheckDataSize;
|
|
|
|
#if DBG
|
|
strcpy(pCanaryLocation, szDumpCanary);
|
|
#endif // DBG
|
|
|
|
memcpy(&DumpData->Guid, &VpBugcheckGUID, sizeof(VpBugcheckGUID));
|
|
|
|
//
|
|
// Call the "hooked" reason callback entry point
|
|
//
|
|
|
|
if (FdoExtension->BugcheckCallback) {
|
|
|
|
FdoExtension->BugcheckCallback(
|
|
FdoExtension->HwDeviceExtension,
|
|
0xEA,
|
|
VpBugcheckData,
|
|
FdoExtension->BugcheckDataSize);
|
|
}
|
|
|
|
#if DBG
|
|
ASSERT(!strcmp(szDumpCanary, pCanaryLocation));
|
|
#endif // DBG
|
|
}
|
|
}
|
|
|
|
VOID
|
|
VpAcquireLock(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will acquire the global video port lock. This lock
|
|
protects global data structures which are shared across drivers.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Returns:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
KeWaitForSingleObject(
|
|
&VpGlobalLock,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
(PTIME)NULL);
|
|
}
|
|
|
|
VOID
|
|
VpReleaseLock(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will release the global video port lock. This lock
|
|
protects global data structures which are shared across drivers.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Returns:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
KeReleaseMutex(&VpGlobalLock, FALSE);
|
|
}
|
|
|
|
PVOID
|
|
VpAllocateNonPagedPoolPageAligned(
|
|
ULONG Size
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will allocate non-paged pool on a page alignment.
|
|
|
|
Arguments:
|
|
|
|
Size - The number of bytes of memory to allocate.
|
|
|
|
Returns:
|
|
|
|
A pointer to the allocated buffer.
|
|
|
|
--*/
|
|
|
|
{
|
|
PVOID Buffer;
|
|
|
|
if (Size < PAGE_SIZE) {
|
|
Size = PAGE_SIZE;
|
|
}
|
|
|
|
Buffer = ExAllocatePoolWithTag(NonPagedPool, Size, VP_TAG);
|
|
|
|
//
|
|
// Make sure the buffer is page aligned. In current builds,
|
|
// allocating at least 1 page from non-paged pool, will always
|
|
// result in a page aligned allocation.
|
|
//
|
|
// However, since this could change someday, verify that this
|
|
// remains true.
|
|
//
|
|
|
|
if ((ULONG_PTR)Buffer & (PAGE_SIZE - 1)) {
|
|
ExFreePool(Buffer);
|
|
Buffer = NULL;
|
|
}
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
VP_STATUS
|
|
VideoPortRegisterBugcheckCallback(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG BugcheckCode,
|
|
IN PVIDEO_BUGCHECK_CALLBACK Callback,
|
|
IN ULONG BugcheckDataSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allows a video miniport to register for a callback at
|
|
bugcheck time. The driver will then have an opportunity to store
|
|
data that can be used to help diagnose the bugcheck. The data is
|
|
appended to the dump file.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - a pointer to the device extension
|
|
|
|
BugcheckCode - allows you to specify the bugcheck code you want to
|
|
be notified for.
|
|
|
|
Callback - a pointer to the miniport supplied callback function
|
|
which will be invoked when a bugcheck occurs. The callback function
|
|
must be non-paged, and must not access pageable code or data.
|
|
|
|
BugcheckDataSize - The amount of data the miniport will want to add
|
|
to the minidump.
|
|
|
|
Returns:
|
|
|
|
A status code indicating success or failure.
|
|
|
|
Notes:
|
|
|
|
Currently only bugcheck EA's can be hooked.
|
|
|
|
Currently we limit the data size to 4k.
|
|
|
|
To unhook the callback, the miniport can specify NULL for the callback
|
|
or 0 for the DataSize.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
|
VP_STATUS Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
//
|
|
// For now let's only support hooking bugcheck EA.
|
|
//
|
|
|
|
if (BugcheckCode != 0xEA) {
|
|
|
|
pVideoDebugPrint((0, "Currently only bugcheck 0xEA can be hooked.\n"));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Force the data size to be a multiple of 16 bytes.
|
|
//
|
|
|
|
BugcheckDataSize = (BugcheckDataSize + 15) & ~15;
|
|
|
|
//
|
|
// The kernel support code only allows 4k per caller for minidumps.
|
|
//
|
|
|
|
if (BugcheckDataSize > MAX_SECONDARY_DUMP_SIZE) {
|
|
|
|
pVideoDebugPrint((0, "There is 4000 bytes limit on bugcheck data size.\n"));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Acquire global videoprt lock, because we will be modifiying
|
|
// global state.
|
|
//
|
|
|
|
VpAcquireLock();
|
|
|
|
//
|
|
// If the Callback is NULL, or the BugcheckDataSize is 0 then
|
|
// they are unregistering the callback.
|
|
//
|
|
|
|
if ((Callback == NULL) || (BugcheckDataSize == 0)) {
|
|
|
|
//
|
|
// Only unregister if they were registered!
|
|
//
|
|
|
|
if (fdoExtension->BugcheckCallback) {
|
|
|
|
fdoExtension->BugcheckCallback = NULL;
|
|
fdoExtension->BugcheckDataSize = 0;
|
|
}
|
|
|
|
Status = NO_ERROR;
|
|
|
|
} else {
|
|
|
|
if (VpBugcheckData == NULL) {
|
|
|
|
//
|
|
// Try to acquire a large enough buffer for the bugcheck data for
|
|
// this driver and all other drivers already registered
|
|
//
|
|
|
|
VpBugcheckData = VpAllocateNonPagedPoolPageAligned(PAGE_SIZE);
|
|
}
|
|
|
|
//
|
|
// If the allocation succeeded then register the bugcheck
|
|
// callback
|
|
//
|
|
|
|
if (VpBugcheckData) {
|
|
|
|
//
|
|
// Update the fdoExtension to indicate the callback is hooked.
|
|
//
|
|
|
|
fdoExtension->BugcheckCallback = Callback;
|
|
fdoExtension->BugcheckDataSize = BugcheckDataSize;
|
|
|
|
Status = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Release the global videoprt lock
|
|
//
|
|
|
|
VpReleaseLock();
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
FreeDumpFileDacl(
|
|
PACL pDacl
|
|
)
|
|
{
|
|
if (pDacl) ExFreePool(pDacl);
|
|
}
|
|
|
|
static
|
|
PACL
|
|
CreateDumpFileDacl(
|
|
VOID
|
|
)
|
|
{
|
|
ULONG ulDacLength = sizeof(ACL)
|
|
+ 2 * sizeof(ACCESS_ALLOWED_ACE)
|
|
- 2 * sizeof(ULONG)
|
|
+ RtlLengthSid(SeExports->SeLocalSystemSid)
|
|
+ RtlLengthSid(SeExports->SeCreatorOwnerSid);
|
|
|
|
PACL pDacl = (PACL)ExAllocatePoolWithTag(PagedPool, ulDacLength, VP_TAG);
|
|
|
|
if (pDacl &&
|
|
NT_SUCCESS(RtlCreateAcl(pDacl, ulDacLength, ACL_REVISION)) &&
|
|
NT_SUCCESS(RtlAddAccessAllowedAce(pDacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
SeExports->SeLocalSystemSid)) &&
|
|
NT_SUCCESS(RtlAddAccessAllowedAce(pDacl,
|
|
ACL_REVISION,
|
|
DELETE,
|
|
SeExports->SeCreatorOwnerSid)))
|
|
{
|
|
return pDacl;
|
|
}
|
|
|
|
FreeDumpFileDacl(pDacl);
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
BOOLEAN
|
|
InitDumpFileSid(
|
|
PSID pSid,
|
|
PACL pDacl
|
|
)
|
|
{
|
|
return (pSid &&
|
|
pDacl &&
|
|
NT_SUCCESS(RtlCreateSecurityDescriptor(pSid, SECURITY_DESCRIPTOR_REVISION)) &&
|
|
NT_SUCCESS(RtlSetDaclSecurityDescriptor(pSid, TRUE, pDacl,FALSE)));
|
|
}
|
|
|
|
VOID
|
|
pVpWriteFile(
|
|
PWSTR pwszFileName,
|
|
PVOID pvBuffer,
|
|
ULONG ulSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when we are trying to recover from a bugcheck
|
|
EA.
|
|
|
|
Arguments:
|
|
|
|
pwszFileName - name of dump file
|
|
pvBuffer - data to write
|
|
ulSize - size of the data to data
|
|
|
|
Returns:
|
|
|
|
none.
|
|
|
|
Notes:
|
|
|
|
This routine can be pagable because it will be called at passive level.
|
|
|
|
--*/
|
|
|
|
{
|
|
SECURITY_DESCRIPTOR Sid;
|
|
PACL pDacl = CreateDumpFileDacl();
|
|
|
|
if (InitDumpFileSid(&Sid, pDacl)) {
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE FileHandle;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
pwszFileName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
(HANDLE) NULL,
|
|
&Sid);
|
|
|
|
if (NT_SUCCESS(ZwCreateFile(&FileHandle,
|
|
FILE_GENERIC_WRITE,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_HIDDEN,
|
|
0, // exclusive
|
|
FILE_SUPERSEDE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT |
|
|
FILE_WRITE_THROUGH,
|
|
NULL,
|
|
0)))
|
|
{
|
|
ZwWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
pvBuffer,
|
|
ulSize,
|
|
NULL,
|
|
NULL);
|
|
|
|
//
|
|
// Close the file.
|
|
//
|
|
|
|
ZwClose(FileHandle);
|
|
}
|
|
}
|
|
|
|
FreeDumpFileDacl(pDacl);
|
|
}
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
VOID
|
|
VideoPortQuerySystemTime(
|
|
OUT PLARGE_INTEGER CurrentTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the current system time.
|
|
|
|
Arguments:
|
|
|
|
CurrentTime - Supplies a pointer to a variable that will receive the
|
|
current system time.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
KeQuerySystemTime(CurrentTime);
|
|
return;
|
|
}
|
|
|
|
#endif
|