mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 06:53:00 +00:00
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9
Licensed under MIT
This commit is contained in:
parent
545df81502
commit
8a978a179f
475 changed files with 285099 additions and 0 deletions
289
sdk/lib/drivers/wdf/shared/support/um/fxdeviceinterfaceum.cpp
Normal file
289
sdk/lib/drivers/wdf/shared/support/um/fxdeviceinterfaceum.cpp
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDeviceInterfaceUM.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the device interface object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
User mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxDeviceInterfaceUM.tmh"
|
||||
}
|
||||
|
||||
FxDeviceInterface::FxDeviceInterface(
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Constructor for the object. Initializes all fields
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
RtlZeroMemory(&m_InterfaceClassGUID, sizeof(m_InterfaceClassGUID));
|
||||
|
||||
RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName));
|
||||
RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
|
||||
|
||||
m_Entry.Next = NULL;
|
||||
|
||||
m_State = FALSE;
|
||||
}
|
||||
|
||||
FxDeviceInterface::~FxDeviceInterface()
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Destructor for FxDeviceInterface. Cleans up any allocations previously
|
||||
allocated.
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
// the device interface should be off now
|
||||
ASSERT(m_State == FALSE);
|
||||
|
||||
// should no longer be in any list
|
||||
ASSERT(m_Entry.Next == NULL);
|
||||
|
||||
if (m_ReferenceString.Buffer != NULL) {
|
||||
FxPoolFree(m_ReferenceString.Buffer);
|
||||
RtlZeroMemory(&m_ReferenceString, sizeof(m_ReferenceString));
|
||||
}
|
||||
|
||||
if (m_SymbolicLinkName.Buffer != NULL) {
|
||||
MxMemory::MxFreePool(m_SymbolicLinkName.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxDeviceInterface::Initialize(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in CONST GUID* InterfaceGUID,
|
||||
__in_opt PCUNICODE_STRING ReferenceString
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Initializes the object with the interface GUID and optional reference string
|
||||
|
||||
Arguments:
|
||||
InterfaceGUID - GUID describing the interface
|
||||
|
||||
ReferenceString - string used to differentiate between 2 interfaces on the
|
||||
same PDO
|
||||
|
||||
Return Value:
|
||||
STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
|
||||
|
||||
--*/
|
||||
{
|
||||
RtlCopyMemory(&m_InterfaceClassGUID, InterfaceGUID, sizeof(GUID));
|
||||
|
||||
if (ReferenceString != NULL) {
|
||||
return FxDuplicateUnicodeString(FxDriverGlobals,
|
||||
ReferenceString,
|
||||
&m_ReferenceString);
|
||||
}
|
||||
else {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
FxDeviceInterface::SetState(
|
||||
__in BOOLEAN State
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Sets the state of the device interface
|
||||
|
||||
Arguments:
|
||||
State - the state to set
|
||||
|
||||
|
||||
Return Value:
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr;
|
||||
NTSTATUS status;
|
||||
IWudfDeviceStack *pDeviceStack;
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Get the IWudfDeviceStack interface
|
||||
//
|
||||
pDeviceStack = m_Device->GetDeviceStackInterface();
|
||||
|
||||
//
|
||||
// Enable the interface
|
||||
//
|
||||
hr = pDeviceStack->SetDeviceInterfaceState(&this->m_InterfaceClassGUID,
|
||||
this->m_ReferenceString.Buffer,
|
||||
State);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
m_State = State;
|
||||
}
|
||||
else {
|
||||
status = FxDevice::NtStatusFromHr(pDeviceStack, hr);
|
||||
DoTraceLevelMessage(
|
||||
FxDevice::GetFxDevice(m_Device)->GetDriverGlobals(),
|
||||
TRACE_LEVEL_WARNING, TRACINGPNP,
|
||||
"Failed to %s device interface %!STATUS!",
|
||||
(State ? "enable" : "disable"), status);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxDeviceInterface::Register(
|
||||
__in MdDeviceObject DeviceObject
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Registers the device interface for a given PDO
|
||||
|
||||
Arguments:
|
||||
DeviceObject - FDO for the device stack in case of UM, and PDO for
|
||||
in case of KM.
|
||||
|
||||
Return Value:
|
||||
returned by IWudfDeviceStack::CreateDeviceInterface
|
||||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr;
|
||||
NTSTATUS status;
|
||||
IWudfDeviceStack *pDeviceStack;
|
||||
|
||||
m_Device = DeviceObject;
|
||||
|
||||
//
|
||||
// Get the IWudfDeviceStack interface
|
||||
//
|
||||
pDeviceStack = m_Device->GetDeviceStackInterface();
|
||||
|
||||
hr = pDeviceStack->CreateDeviceInterface(&m_InterfaceClassGUID,
|
||||
m_ReferenceString.Buffer);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
status = FxDevice::NtStatusFromHr(pDeviceStack, hr);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxDeviceInterface::Register(
|
||||
_In_ FxDevice* Device
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// For UMDF, PDO is already known so no reason to defer registration.
|
||||
// Also, note that Register takes fdo as parameter for UMDF.
|
||||
//
|
||||
status = Register(Device->GetDeviceObject());
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxDeviceInterface::GetSymbolicLinkName(
|
||||
_In_ FxString* LinkString
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PCWSTR symLink = NULL;
|
||||
|
||||
if (m_SymbolicLinkName.Buffer == NULL) {
|
||||
IWudfDeviceStack *pDeviceStack;
|
||||
IWudfDeviceStack2 *pDeviceStack2;
|
||||
|
||||
//
|
||||
// Get the IWudfDeviceStack interface
|
||||
//
|
||||
pDeviceStack = m_Device->GetDeviceStackInterface();
|
||||
HRESULT hrQI;
|
||||
HRESULT hr;
|
||||
|
||||
hrQI = pDeviceStack->QueryInterface(IID_IWudfDeviceStack2,
|
||||
(PVOID*)&pDeviceStack2);
|
||||
FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pDeviceStack2));
|
||||
pDeviceStack->Release();
|
||||
|
||||
//
|
||||
// Get the symbolic link
|
||||
//
|
||||
hr = pDeviceStack2->GetInterfaceSymbolicLink(&m_InterfaceClassGUID,
|
||||
m_ReferenceString.Buffer,
|
||||
&symLink);
|
||||
if (FAILED(hr)) {
|
||||
status = FxDevice::GetFxDevice(m_Device)->NtStatusFromHr(hr);
|
||||
}
|
||||
else {
|
||||
RtlInitUnicodeString(&m_SymbolicLinkName, symLink);
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Attempt a copy
|
||||
//
|
||||
status = LinkString->Assign(&m_SymbolicLinkName);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
302
sdk/lib/drivers/wdf/shared/support/um/fxregkeyum.cpp
Normal file
302
sdk/lib/drivers/wdf/shared/support/um/fxregkeyum.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxRegKey.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
user mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
//#define UNICODE
|
||||
//#define _UNICODE
|
||||
#include <Winreg.h>
|
||||
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxRegKeyUM.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
FxRegKey::FxRegKey(
|
||||
PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
) :
|
||||
FxPagedObject(FX_TYPE_REG_KEY, sizeof(FxRegKey), FxDriverGlobals),
|
||||
m_Key(NULL),
|
||||
m_Globals(FxDriverGlobals),
|
||||
m_CanCloseHandle(TRUE)
|
||||
{
|
||||
}
|
||||
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::~FxRegKey()
|
||||
{
|
||||
if (m_Key != NULL) {
|
||||
if (m_CanCloseHandle == TRUE) {
|
||||
RegCloseKey((HKEY)m_Key);
|
||||
}
|
||||
m_Key = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_Close(
|
||||
__in HANDLE Key
|
||||
)
|
||||
{
|
||||
DWORD err = RegCloseKey((HKEY)Key);
|
||||
|
||||
if (ERROR_SUCCESS == err) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return WinErrorToNtStatus(err);
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_Create(
|
||||
__in_opt HANDLE ParentKey,
|
||||
__in PCUNICODE_STRING KeyName,
|
||||
__out HANDLE* NewKey,
|
||||
__in ACCESS_MASK DesiredAccess,
|
||||
__in ULONG CreateOptions,
|
||||
__out_opt PULONG CreateDisposition
|
||||
)
|
||||
{
|
||||
HKEY parentKey;
|
||||
|
||||
if (NULL == ParentKey)
|
||||
{
|
||||
parentKey = HKEY_LOCAL_MACHINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentKey = (HKEY) ParentKey;
|
||||
}
|
||||
|
||||
DWORD err = RegCreateKeyEx(parentKey,
|
||||
KeyName->Buffer,
|
||||
0,
|
||||
NULL,
|
||||
CreateOptions,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
(PHKEY)NewKey,
|
||||
CreateDisposition);
|
||||
|
||||
if (ERROR_SUCCESS == err) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return WinErrorToNtStatus(err);
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_OpenKey(
|
||||
__in_opt HANDLE ParentKey,
|
||||
__in PCUNICODE_STRING KeyName,
|
||||
__out HANDLE* Key,
|
||||
__in ACCESS_MASK DesiredAccess
|
||||
)
|
||||
{
|
||||
HKEY parentKey;
|
||||
|
||||
if (NULL == ParentKey)
|
||||
{
|
||||
parentKey = HKEY_LOCAL_MACHINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentKey = (HKEY) ParentKey;
|
||||
}
|
||||
|
||||
DWORD err = RegOpenKeyEx(parentKey,
|
||||
KeyName->Buffer,
|
||||
0,
|
||||
DesiredAccess,
|
||||
(PHKEY)Key);
|
||||
|
||||
if (ERROR_SUCCESS == err) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return WinErrorToNtStatus(err);
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_SetValue(
|
||||
_In_ HANDLE Key,
|
||||
_In_ PCUNICODE_STRING ValueName,
|
||||
_In_ ULONG ValueType,
|
||||
_In_reads_bytes_(ValueLength) PVOID Value,
|
||||
_In_ ULONG ValueLength
|
||||
)
|
||||
{
|
||||
DWORD err;
|
||||
|
||||
err = RegSetValueEx((HKEY)Key,
|
||||
ValueName->Buffer,
|
||||
0,
|
||||
ValueType,
|
||||
(BYTE*)Value,
|
||||
ValueLength);
|
||||
if (ERROR_SUCCESS == err) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return WinErrorToNtStatus(err);
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_QueryValue(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in HANDLE Key,
|
||||
__in PCUNICODE_STRING ValueName,
|
||||
__in ULONG ValueLength,
|
||||
__out_bcount_opt(ValueLength) PVOID Value,
|
||||
__out_opt PULONG ValueLengthQueried,
|
||||
__out_opt PULONG ValueType
|
||||
)
|
||||
{
|
||||
DWORD err;
|
||||
NTSTATUS status;
|
||||
ULONG length;
|
||||
|
||||
UNREFERENCED_PARAMETER(FxDriverGlobals);
|
||||
ASSERT(Key != HKEY_PERFORMANCE_DATA);
|
||||
|
||||
length = ValueLength;
|
||||
|
||||
err = RegQueryValueEx((HKEY)Key,
|
||||
ValueName->Buffer,
|
||||
NULL,
|
||||
ValueType,
|
||||
(LPBYTE)Value,
|
||||
&length);
|
||||
|
||||
if (ValueLengthQueried != NULL) {
|
||||
*ValueLengthQueried = length;
|
||||
}
|
||||
|
||||
//
|
||||
// Please see the comment in FxRegKeyKm.cpp FxRegKey::_QueryValue about
|
||||
// the call to ZwQueryValueKey.
|
||||
//
|
||||
// If the user supplies a NULL data buffer, RegQueryValueEx will return
|
||||
// ERROR_SUCCESS. However, in order to satisfy UMDF-KMDF DDI parity as well
|
||||
// as internal mode-agnostic code, we must overwrite RegQueryValueEx's
|
||||
// return value of ERROR_SUCCESS (STATUS_SUCCESS) with STATUS_BUFFER_OVERFLOW.
|
||||
//
|
||||
// Other return values are overwritten because WinErrorToNtStatus does not map
|
||||
// all Win32 error codes that RegQueryValueEx returns to the same NTSTATUS
|
||||
// values that ZwQueryValueKey would return in the KM implementation of
|
||||
// FxRegKey::_QueryValue.
|
||||
//
|
||||
if (err == ERROR_SUCCESS) {
|
||||
if (Value != NULL) {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
}
|
||||
else if (err == ERROR_MORE_DATA) {
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else if (err == ERROR_FILE_NOT_FOUND) {
|
||||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
else {
|
||||
status = WinErrorToNtStatus(err);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
FxRegKey::_QueryULong(
|
||||
__in HANDLE Key,
|
||||
__in PCUNICODE_STRING ValueName,
|
||||
__out PULONG Value
|
||||
)
|
||||
{
|
||||
DWORD err;
|
||||
NTSTATUS status;
|
||||
ULONG length, type;
|
||||
|
||||
ASSERT(Key != HKEY_PERFORMANCE_DATA);
|
||||
|
||||
type = REG_DWORD;
|
||||
length = sizeof(ULONG);
|
||||
|
||||
err = RegQueryValueEx((HKEY)Key,
|
||||
ValueName->Buffer,
|
||||
NULL,
|
||||
&type,
|
||||
(LPBYTE)Value,
|
||||
&length);
|
||||
|
||||
if ((err == ERROR_SUCCESS || err == ERROR_MORE_DATA) &&
|
||||
type != REG_DWORD) {
|
||||
|
||||
ASSERT(FALSE);
|
||||
|
||||
status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
else {
|
||||
if (ERROR_SUCCESS == err) {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
status = WinErrorToNtStatus(err);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
#pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
|
||||
NTSTATUS
|
||||
FxRegKey::_QueryQuadWord(
|
||||
__in HANDLE Key,
|
||||
__in PCUNICODE_STRING ValueName,
|
||||
__out PLARGE_INTEGER Value
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Key);
|
||||
UNREFERENCED_PARAMETER(ValueName);
|
||||
UNREFERENCED_PARAMETER(Value);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
103
sdk/lib/drivers/wdf/shared/support/um/fxrequestbufferum.cpp
Normal file
103
sdk/lib/drivers/wdf/shared/support/um/fxrequestbufferum.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
FxRequestBufferUm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements a memory union object
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
User mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxRequestBufferUm.tmh"
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxRequestBuffer::GetOrAllocateMdl(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__deref_out_opt PMDL* Mdl,
|
||||
__inout PMDL* MdlToFree,
|
||||
__inout PBOOLEAN UnlockWhenFreed,
|
||||
__in LOCK_OPERATION Operation,
|
||||
__in BOOLEAN ReuseMdl,
|
||||
__inout_opt size_t* SizeOfMdl
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This function attempts to reuse the passed-in MDL (if any) or allocates
|
||||
a new MDL if reuse flag isn't passed-in or if the existing MDL isn't
|
||||
big enough.
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
FxDriverGlobals - Driver globals
|
||||
|
||||
Mdl - on return it contains the MDL allocated/reused
|
||||
|
||||
MdlToFree - pointer to any MDL
|
||||
* to be reused, if the size is <= current size, or
|
||||
* freed and set to newly allocated MDL
|
||||
|
||||
UnlockWhenFreed - whether to unlock pages when freeing MDL
|
||||
(if FALSE, MDL may represent just MDL buffer but the pages
|
||||
might have already been unlocked)
|
||||
|
||||
Operation - Operation to pass to MmLockPages
|
||||
|
||||
ReuseMdl - whether to reuse *MdlToFree
|
||||
Please note that this can be FALSE even when MDL is supplied
|
||||
|
||||
SizeOfMdl - on input contains size of *MdlToFree,
|
||||
on return contains size of *Mdl
|
||||
|
||||
Remarks:
|
||||
|
||||
*MdlToFree is modified only when this function frees the passed in MDL
|
||||
Otherwise it leaves it untouched. Caller is responsible for storing
|
||||
properly initialized value and/or freeing what's stored in the value.
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(FxDriverGlobals);
|
||||
UNREFERENCED_PARAMETER(Mdl);
|
||||
UNREFERENCED_PARAMETER(MdlToFree);
|
||||
UNREFERENCED_PARAMETER(UnlockWhenFreed);
|
||||
UNREFERENCED_PARAMETER(Operation);
|
||||
UNREFERENCED_PARAMETER(ReuseMdl);
|
||||
UNREFERENCED_PARAMETER(SizeOfMdl);
|
||||
|
||||
UfxVerifierTrapNotImpl();
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxRequestBuffer::SetMemory(
|
||||
__in IFxMemory* Memory,
|
||||
__in PWDFMEMORY_OFFSET Offsets
|
||||
)
|
||||
{
|
||||
DataType = FxRequestBufferMemory;
|
||||
u.Memory.Memory = Memory;
|
||||
u.Memory.Offsets = Offsets;
|
||||
}
|
||||
|
788
sdk/lib/drivers/wdf/shared/support/um/fxresourcecollectionum.cpp
Normal file
788
sdk/lib/drivers/wdf/shared/support/um/fxresourcecollectionum.cpp
Normal file
|
@ -0,0 +1,788 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxResourceCollection.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements a base object for derived collection classes and
|
||||
the derived collection classes.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
User mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
#include <intsafe.h>
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
// Tracing support
|
||||
extern "C" {
|
||||
#include "FxResourceCollectionUm.tmh"
|
||||
}
|
||||
#endif
|
||||
|
||||
FxCmResList::~FxCmResList()
|
||||
{
|
||||
DeleteRegisterResourceTable();
|
||||
DeletePortResourceTable();
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxCmResList::BuildRegisterResourceTable(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG count;
|
||||
ULONG i, index;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
|
||||
ULONG numRegisterDesc;
|
||||
BOOLEAN locked = FALSE;
|
||||
NTSTATUS status;
|
||||
|
||||
count = GetCount();
|
||||
numRegisterDesc = 0;
|
||||
|
||||
//
|
||||
// count number of register descriptors
|
||||
//
|
||||
for (i = 0; i < count; i++) {
|
||||
desc = GetDescriptor(i);
|
||||
if (desc == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Resource Descriptor not found %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (desc->Type == CmResourceTypeMemory ||
|
||||
desc->Type == CmResourceTypeMemoryLarge) {
|
||||
numRegisterDesc++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numRegisterDesc == 0) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate table
|
||||
//
|
||||
LockResourceTable();
|
||||
locked = TRUE;
|
||||
|
||||
status = FxRegisterResourceInfo::_CreateAndInit(
|
||||
GetDriverGlobals(),
|
||||
numRegisterDesc,
|
||||
&m_RegisterResourceTable
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Failed to allocate memory for resource table"
|
||||
" %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
m_RegisterResourceTableSizeCe = numRegisterDesc;
|
||||
|
||||
//
|
||||
// Populate table
|
||||
//
|
||||
index = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
desc = GetDescriptor(i);
|
||||
if (desc == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Resource Descriptor not found %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (desc->Type == CmResourceTypeMemory ||
|
||||
desc->Type == CmResourceTypeMemoryLarge) {
|
||||
SIZE_T len;
|
||||
PHYSICAL_ADDRESS pa;
|
||||
|
||||
//
|
||||
// This will populate Length and StartPa
|
||||
//
|
||||
len = GetResourceLength(desc, &pa);
|
||||
if (len) {
|
||||
m_RegisterResourceTable[index].SetPhysicalAddress(pa, len);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (m_RegisterResourceTable != NULL) {
|
||||
delete [] m_RegisterResourceTable;
|
||||
m_RegisterResourceTable = NULL;
|
||||
m_RegisterResourceTableSizeCe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
UnlockResourceTable();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxCmResList::BuildPortResourceTable(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG count;
|
||||
ULONG i, index;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
|
||||
ULONG numPortDesc;
|
||||
BOOLEAN locked = FALSE;
|
||||
NTSTATUS status;
|
||||
|
||||
count = GetCount();
|
||||
numPortDesc = 0;
|
||||
|
||||
//
|
||||
// count number of register descriptors
|
||||
//
|
||||
for (i = 0; i < count; i++) {
|
||||
desc = GetDescriptor(i);
|
||||
if (desc == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Resource Descriptor not found %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (desc->Type == CmResourceTypePort) {
|
||||
numPortDesc++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numPortDesc == 0) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate table
|
||||
//
|
||||
LockResourceTable();
|
||||
locked = TRUE;
|
||||
|
||||
status = FxPortResourceInfo::_CreateAndInit(
|
||||
GetDriverGlobals(),
|
||||
numPortDesc,
|
||||
&m_PortResourceTable
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Failed to allocate memory for resource table"
|
||||
" %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
m_PortResourceTableSizeCe = numPortDesc;
|
||||
|
||||
//
|
||||
// Populate table
|
||||
//
|
||||
index = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
desc = GetDescriptor(i);
|
||||
if (desc == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Resource Descriptor not found %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (desc->Type == CmResourceTypePort) {
|
||||
SIZE_T len;
|
||||
PHYSICAL_ADDRESS pa;
|
||||
|
||||
//
|
||||
// This will populate Length, StartPa and EndPa
|
||||
//
|
||||
len = GetResourceLength(desc, &pa);
|
||||
if (len) {
|
||||
m_PortResourceTable[index].SetPhysicalAddress(pa, len);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (m_PortResourceTable != NULL) {
|
||||
delete [] m_PortResourceTable;
|
||||
m_PortResourceTable = NULL;
|
||||
m_PortResourceTableSizeCe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
UnlockResourceTable();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
FxCmResList::UpdateRegisterResourceEntryLocked(
|
||||
__in FxRegisterResourceInfo* Entry,
|
||||
__in PVOID SystemMappedAddress,
|
||||
__in SIZE_T NumberOfBytes,
|
||||
__in PVOID UsermodeMappedAddress
|
||||
)
|
||||
{
|
||||
Entry->SetMappedAddress(SystemMappedAddress, NumberOfBytes, UsermodeMappedAddress);
|
||||
}
|
||||
|
||||
VOID
|
||||
FxCmResList::ClearRegisterResourceEntryLocked(
|
||||
__in FxRegisterResourceInfo* Entry
|
||||
)
|
||||
{
|
||||
Entry->ClearMappedAddress();
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::ValidateRegisterPhysicalAddressRange (
|
||||
__in PHYSICAL_ADDRESS PhysicalAddress,
|
||||
__in SIZE_T Size,
|
||||
__out FxRegisterResourceInfo** TableEntry
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks whether the physical address range is part of the resources
|
||||
assigned to the device by pnp manager. It also returns the table entry
|
||||
corresponding to the physical address range from register resource table.
|
||||
|
||||
Arguments:
|
||||
|
||||
PhysicalAddress - Supplies physical address to validate
|
||||
|
||||
Size - Supplies size of address range in bytes.
|
||||
|
||||
TableEntry - Supplies a pointer to store the table entry that corresponds to
|
||||
this physical address.
|
||||
|
||||
Return Value:
|
||||
|
||||
HRESULT
|
||||
|
||||
S_OK if physical address is one assigned by pnp manager to this device.
|
||||
E_INAVLIDARG otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
HRESULT hr;
|
||||
ULONGLONG driverStartPa, driverEndPa, systemStartPa, systemEndPa;
|
||||
ULONGLONG tmp;
|
||||
FxRegisterResourceInfo* entry = NULL;
|
||||
|
||||
*TableEntry = NULL;
|
||||
|
||||
//
|
||||
// Physical address is of LONGLONG type (signed) we need to cast it to
|
||||
// ULONGLONG for comparision because in a LONGLONG comprison, the
|
||||
// result is different when highest bit is set vs when it is not set.
|
||||
//
|
||||
driverStartPa = PhysicalAddress.QuadPart;
|
||||
|
||||
//
|
||||
// driverEndPa = driverStartPa + Size - 1;
|
||||
//
|
||||
hr = ULongLongAdd(driverStartPa, Size, &tmp);
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
|
||||
"when computing register address range", SUCCEEDED(hr)),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
driverEndPa = tmp - 1;
|
||||
|
||||
//
|
||||
// We allow one physical address range mapping only. The base address and
|
||||
// length can be flexible within the assigned range.
|
||||
//
|
||||
for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
|
||||
entry = &m_RegisterResourceTable[i];
|
||||
|
||||
//
|
||||
// No need to do int overflow safe additon here since start address and
|
||||
// length are assigned by pnp manager. Note that we don't store endPa in
|
||||
// resource table the way we do for SystemVa is because endPa is not
|
||||
// needed in hot path so can be computed using length.
|
||||
//
|
||||
systemStartPa = entry->m_StartPa.QuadPart;
|
||||
systemEndPa = systemStartPa + entry->m_Length - 1;
|
||||
|
||||
if (driverStartPa >= systemStartPa &&
|
||||
driverEndPa <= systemEndPa) {
|
||||
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Attempt to do multiple "
|
||||
"mapping of same resource, or multiple mapping in same resource"
|
||||
" range",
|
||||
(entry->m_StartSystemVa == NULL)), GetDriverGlobals()->Public.DriverName);
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NULL(entry->m_EndSystemVa),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NULL(entry->m_StartUsermodeVa),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, CHECK("Mapped length not zero",
|
||||
(entry->m_MappedLength == 0)), GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
*TableEntry = entry;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::ValidateAndClearMapping(
|
||||
__in PVOID Address,
|
||||
__in SIZE_T Length
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks whether the mapped system base address and size is part
|
||||
of the resources assigned to the device by pnp manager. If so it clears the
|
||||
system and usermode address mapping from the table.
|
||||
|
||||
Arguments:
|
||||
|
||||
Address - Supplies system base address to validate
|
||||
|
||||
Size - Supplies size of address range in bytes.
|
||||
|
||||
Return Value:
|
||||
|
||||
HRESULT
|
||||
|
||||
S_OK if system address is one mapped to a register resource.
|
||||
E_INAVLIDARG otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
ULONG i;
|
||||
FxRegisterResourceInfo* entry = NULL;
|
||||
|
||||
LockResourceTable();
|
||||
|
||||
for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
|
||||
entry = &m_RegisterResourceTable[i];
|
||||
|
||||
if (NULL != entry->m_StartSystemVa &&
|
||||
Address == entry->m_StartSystemVa &&
|
||||
Length == entry->m_MappedLength) {
|
||||
//
|
||||
// there is a valid mapping. clear it.
|
||||
//
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NOT_NULL(entry->m_EndSystemVa),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
ClearRegisterResourceEntryLocked(entry);
|
||||
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UnlockResourceTable();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::ValidateRegisterSystemBaseAddress (
|
||||
__in PVOID Address,
|
||||
__out PVOID* UsermodeBaseAddress
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks whether the mapped system base address and size is part
|
||||
of the resources assigned to the device by pnp manager. If so, it returns
|
||||
corresponding user-mode mapped base address. It is applicable
|
||||
only when registers are mapped to user-mode.
|
||||
|
||||
Arguments:
|
||||
|
||||
Address - Supplies system base address to validate
|
||||
|
||||
Return Value:
|
||||
|
||||
HRESULT
|
||||
|
||||
S_OK if system address is one mapped to a register resource.
|
||||
E_INAVLIDARG otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
FxRegisterResourceInfo* entry = NULL;
|
||||
|
||||
LockResourceTable();
|
||||
for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
|
||||
entry = &m_RegisterResourceTable[i];
|
||||
|
||||
if (Address == entry->m_StartSystemVa) {
|
||||
|
||||
FX_VERIFY_WITH_NAME(INTERNAL, CHECK_NOT_NULL(entry->m_StartUsermodeVa),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
*UsermodeBaseAddress = entry->m_StartUsermodeVa;
|
||||
|
||||
UnlockResourceTable();
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
UnlockResourceTable();
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::ValidateRegisterSystemAddressRange (
|
||||
__in PVOID SystemAddress,
|
||||
__in SIZE_T Length,
|
||||
__out_opt PVOID* UsermodeAddress
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks whether given system mapped address and length is within
|
||||
one of the assigned resource ranges. Optionally, tt computes the usermode
|
||||
address corresponding to the system address.
|
||||
|
||||
Arguments:
|
||||
|
||||
Address - Supplies register address to validate
|
||||
|
||||
Size - Supplies size of address range in bytes.
|
||||
|
||||
UsermodeAddress - returns usermode address corresponding to system address
|
||||
|
||||
Return Value:
|
||||
|
||||
HRESULT
|
||||
|
||||
S_OK if system address range is valid.
|
||||
E_INAVLIDARG otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
FxRegisterResourceInfo* entry = NULL;
|
||||
SIZE_T offset = 0;
|
||||
ULONG i;
|
||||
PVOID start = NULL;
|
||||
PVOID end = NULL;
|
||||
ULONG_PTR tmp;
|
||||
|
||||
//
|
||||
// compute system address range to look for
|
||||
//
|
||||
start = SystemAddress;
|
||||
|
||||
//
|
||||
// Use interger overflow safe functions
|
||||
// end = ((PUCHAR)SystemAddress) + Length - 1;
|
||||
//
|
||||
hr = ULongPtrAdd((ULONG_PTR) start, Length, &tmp);
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
|
||||
"when computing register address range", SUCCEEDED(hr)),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
end = (PVOID)(tmp - 1);
|
||||
|
||||
//
|
||||
// check if range is in the register resource table
|
||||
//
|
||||
hr = E_INVALIDARG;
|
||||
for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
|
||||
entry = &m_RegisterResourceTable[i];
|
||||
|
||||
if (start >= entry->m_StartSystemVa &&
|
||||
end <= entry->m_EndSystemVa) {
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// compute the corresponding usermode address
|
||||
//
|
||||
if (SUCCEEDED(hr) && UsermodeAddress != NULL) {
|
||||
offset = ((PUCHAR)SystemAddress) - ((PUCHAR)entry->m_StartSystemVa);
|
||||
*UsermodeAddress = ((PUCHAR)entry->m_StartUsermodeVa) + offset;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
SIZE_T
|
||||
FxCmResList::GetResourceLength(
|
||||
__in PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
|
||||
__out_opt PHYSICAL_ADDRESS* Start
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine decodes the length from a CmPartialResourceDescriptor
|
||||
describing a memory resource.
|
||||
|
||||
Arguments:
|
||||
|
||||
Descriptor - Supplies resource descriptor from which to decode length
|
||||
|
||||
Start - Supplies optional buffer into which start address will be stored.
|
||||
|
||||
Return Value:
|
||||
|
||||
Decoded Length
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONGLONG length;
|
||||
|
||||
length = 0;
|
||||
|
||||
ASSERT((Descriptor->Type == CmResourceTypeMemory) ||
|
||||
(Descriptor->Type == CmResourceTypeMemoryLarge) ||
|
||||
(Descriptor->Type == CmResourceTypePort));
|
||||
|
||||
//
|
||||
// If it is not large memory resource than length is in u.Memory.Length.
|
||||
// For large memory resource, the length is given by different fields in
|
||||
// CM_PARTIAL_RESOURCE_DESCRIPTOR structure.
|
||||
//
|
||||
if ((Descriptor->Type == CmResourceTypeMemory) ||
|
||||
(Descriptor->Type == CmResourceTypePort)) {
|
||||
length = Descriptor->u.Memory.Length;
|
||||
|
||||
} else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_40) {
|
||||
length = (((ULONGLONG)Descriptor->u.Memory40.Length40) << 8);
|
||||
|
||||
} else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_48) {
|
||||
length = (((ULONGLONG)Descriptor->u.Memory48.Length48) << 16);
|
||||
|
||||
} else if (Descriptor->Flags & CM_RESOURCE_MEMORY_LARGE_64) {
|
||||
length = (((ULONGLONG)Descriptor->u.Memory64.Length64) << 32);
|
||||
|
||||
} else {
|
||||
//
|
||||
// It should not be possible to get here.
|
||||
//
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
if (Start != NULL) {
|
||||
*Start = Descriptor->u.Generic.Start;
|
||||
}
|
||||
|
||||
//
|
||||
// large memory descriptor is only supported on 64-bit so the casting
|
||||
// below is ok.
|
||||
//
|
||||
return (SIZE_T) length;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::MapIoSpaceWorker(
|
||||
__in PHYSICAL_ADDRESS PhysicalAddress,
|
||||
__in SIZE_T NumberOfBytes,
|
||||
__in MEMORY_CACHING_TYPE CacheType,
|
||||
__deref_out VOID** PseudoBaseAddress
|
||||
)
|
||||
{
|
||||
IWudfDeviceStack *deviceStack;
|
||||
PVOID systemAddress;
|
||||
PVOID usermodeAddress;
|
||||
HRESULT hr;
|
||||
FxRegisterResourceInfo* resEntry;
|
||||
|
||||
//
|
||||
// check if this physical resource is among the assigned resources.
|
||||
// If it is, retrieve the table entry corresponding to to register res.
|
||||
//
|
||||
LockResourceTable();
|
||||
|
||||
hr = ValidateRegisterPhysicalAddressRange(PhysicalAddress,
|
||||
NumberOfBytes,
|
||||
&resEntry);
|
||||
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO),
|
||||
CHECK("Invalid physical address or number of bytes provided",
|
||||
(SUCCEEDED(hr))), GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
*PseudoBaseAddress = NULL;
|
||||
|
||||
//
|
||||
// Call host
|
||||
//
|
||||
deviceStack = GetDevice()->GetDeviceStack();
|
||||
systemAddress = NULL;
|
||||
usermodeAddress = NULL;
|
||||
|
||||
if(GetDevice()->AreRegistersMappedToUsermode()) {
|
||||
hr = deviceStack->MapIoSpace(PhysicalAddress,
|
||||
NumberOfBytes,
|
||||
CacheType,
|
||||
&systemAddress,
|
||||
&usermodeAddress);
|
||||
}
|
||||
else {
|
||||
hr = deviceStack->MapIoSpace(PhysicalAddress,
|
||||
NumberOfBytes,
|
||||
CacheType,
|
||||
&systemAddress,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
//
|
||||
// update the mapped resource list entry and add it to list
|
||||
//
|
||||
UpdateRegisterResourceEntryLocked(resEntry,
|
||||
systemAddress,
|
||||
NumberOfBytes,
|
||||
usermodeAddress);
|
||||
|
||||
//
|
||||
// Convert system address to pseudo (opaque) base address
|
||||
//
|
||||
*PseudoBaseAddress = GetDevice()->GetPseudoAddressFromSystemAddress(
|
||||
systemAddress
|
||||
);
|
||||
}
|
||||
|
||||
UnlockResourceTable();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxCmResList::ValidateResourceUnmap(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
FxRegisterResourceInfo* entry = NULL;
|
||||
|
||||
//
|
||||
// make sure driver has unmapped its resources. No need to
|
||||
// acquire the resource validation table lock as this is called in
|
||||
// ReleaseHardware pnp callback and cannot race with another framework
|
||||
// pnp callback that updates this table (PrepareHardware) so no invalid
|
||||
// access. If a driver thread unmaps after ReleaseHardware return then also
|
||||
// it will be a valid access of table entry.
|
||||
//
|
||||
|
||||
for (i = 0; i < m_RegisterResourceTableSizeCe; i++) {
|
||||
entry = &m_RegisterResourceTable[i];
|
||||
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Driver did not unmap its "
|
||||
"register resources", (entry->m_StartSystemVa == NULL)), GetDriverGlobals()->Public.DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FxCmResList::ValidatePortAddressRange(
|
||||
__in PVOID Address,
|
||||
__in SIZE_T Length
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
HRESULT hr;
|
||||
ULONGLONG driverStartPa, driverEndPa, systemStartPa, systemEndPa;
|
||||
ULONGLONG tmp;
|
||||
FxPortResourceInfo* entry = NULL;
|
||||
|
||||
driverStartPa = (ULONGLONG)Address;
|
||||
|
||||
//
|
||||
// driverEndPa = driverStartPa + Length - 1;
|
||||
//
|
||||
hr = ULongLongAdd(driverStartPa, Length, &tmp);
|
||||
FX_VERIFY_WITH_NAME(DRIVER(BadArgument, TODO), CHECK("Integer overflow occurred"
|
||||
"when computing port address range", SUCCEEDED(hr)),
|
||||
GetDriverGlobals()->Public.DriverName);
|
||||
|
||||
driverEndPa = tmp - 1;
|
||||
|
||||
for (i = 0; i < m_PortResourceTableSizeCe; i++) {
|
||||
entry = &m_PortResourceTable[i];
|
||||
|
||||
systemStartPa = entry->m_StartPa.QuadPart;
|
||||
systemEndPa = entry->m_EndPa.QuadPart;
|
||||
|
||||
if (driverStartPa >= systemStartPa &&
|
||||
driverEndPa <= systemEndPa) {
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxCmResList::CheckForConnectionResources(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG i;
|
||||
ULONG count;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
count = GetCount();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pDescriptor = GetDescriptor(i);
|
||||
if (pDescriptor == NULL) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Resource Descriptor not found %!STATUS!", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pDescriptor->Type == CmResourceTypeConnection) {
|
||||
m_HasConnectionResources = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
44
sdk/lib/drivers/wdf/shared/support/um/fxsupportpchum.hpp
Normal file
44
sdk/lib/drivers/wdf/shared/support/um/fxsupportpchum.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
fxsupportpchum.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in fx\support
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
User mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_SUPPORT_PCH_UM_HPP__
|
||||
#define __FX_SUPPORT_PCH_UM_HPP__
|
||||
|
||||
extern "C" {
|
||||
#include "mx.h"
|
||||
}
|
||||
|
||||
#include "fxmin.hpp"
|
||||
|
||||
#include "FxPagedObject.hpp"
|
||||
#include "FxRegKey.hpp"
|
||||
#include "FxCollection.hpp"
|
||||
#include "FxString.hpp"
|
||||
#include "StringUtil.hpp"
|
||||
|
||||
#include "FxDeviceText.hpp"
|
||||
|
||||
#include <WdfResource.h>
|
||||
#include <FxResource.hpp>
|
||||
|
||||
|
||||
#endif // __FX_SUPPORT_PCH_UM_HPP__
|
426
sdk/lib/drivers/wdf/shared/support/um/fxtelemetryum.cpp
Normal file
426
sdk/lib/drivers/wdf/shared/support/um/fxtelemetryum.cpp
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxTelemetryUm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements a telemetry methods.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
User mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxsupportpch.hpp"
|
||||
#include "DriverFrameworks-UserMode-UmEvents.h"
|
||||
#include "FxldrUm.h"
|
||||
#include <winmeta.h>
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <telemetry\MicrosoftTelemetry.h>
|
||||
#include <rpc.h>
|
||||
#include <rpcndr.h>
|
||||
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxTelemetryUm.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 8ad60765-a021-4494-8594-9346970cf50f */
|
||||
TRACELOGGING_DEFINE_PROVIDER(g_TelemetryProvider,
|
||||
UMDF_FX_TRACE_LOGGING_PROVIDER_NAME,
|
||||
(0x8ad60765, 0xa021, 0x4494, 0x85, 0x94, 0x93, 0x46, 0x97, 0x0c, 0xf5, 0x0f),
|
||||
TraceLoggingOptionMicrosoftTelemetry());
|
||||
|
||||
VOID
|
||||
AllocAndInitializeTelemetryContext(
|
||||
_In_ PFX_TELEMETRY_CONTEXT* TelemetryContext
|
||||
)
|
||||
{
|
||||
PFX_TELEMETRY_CONTEXT context = NULL;
|
||||
RPC_STATUS status;
|
||||
|
||||
context = (PFX_TELEMETRY_CONTEXT)MxMemory::MxAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(FX_TELEMETRY_CONTEXT),
|
||||
FX_TAG);
|
||||
if (NULL == context) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = UuidCreate(&(context->DriverSessionGUID));
|
||||
if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
|
||||
MxMemory::MxFreePool(context);
|
||||
context = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
context->DoOnceFlagsBitmap = 0;
|
||||
exit:
|
||||
*TelemetryContext = context;
|
||||
}
|
||||
|
||||
VOID
|
||||
RegisterTelemetryProvider(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EventRegisterMicrosoft_Windows_DriverFrameworks_UserMode();
|
||||
|
||||
TraceLoggingRegister(g_TelemetryProvider);
|
||||
}
|
||||
|
||||
VOID
|
||||
UnregisterTelemetryProvider(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EventUnregisterMicrosoft_Windows_DriverFrameworks_UserMode();
|
||||
|
||||
TraceLoggingUnregister(g_TelemetryProvider);
|
||||
}
|
||||
|
||||
VOID
|
||||
LogDeviceStartTelemetryEvent(
|
||||
_In_ PFX_DRIVER_GLOBALS Globals,
|
||||
_In_opt_ FxDevice* Fdo
|
||||
)
|
||||
{
|
||||
// If provider is not enabled we're done.
|
||||
if (FALSE == FX_TELEMETRY_ENABLED(g_TelemetryProvider, Globals)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If we already fired an event during PnP start we are done. This avoids
|
||||
// repeatedly firing events during PnP rebalance.
|
||||
//
|
||||
if (InterlockedBitTestAndSet(
|
||||
&Globals->TelemetryContext->DoOnceFlagsBitmap,
|
||||
DeviceStartEventBit) == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// log the DriverInfo stream.
|
||||
//
|
||||
LogDriverInfoStream(Globals, Fdo);
|
||||
}
|
||||
|
||||
VOID
|
||||
LogDriverInfoStream(
|
||||
_In_ PFX_DRIVER_GLOBALS DriverGlobals,
|
||||
_In_ FxDevice* Fdo
|
||||
)
|
||||
{
|
||||
LONG error = ERROR_SUCCESS;
|
||||
PWCHAR str = NULL;
|
||||
UFxTelemetryDriverInfo driverInfo = {0};
|
||||
LPCWSTR hardwareIds = NULL;
|
||||
LPCWSTR setupClass = NULL;
|
||||
LPCWSTR busEnum = NULL;
|
||||
LPCWSTR manufacturer = NULL;
|
||||
UMDF_DRIVER_REGSITRY_INFO devRegInfo = {0};
|
||||
PCWSTR groupId = NULL;
|
||||
IWudfDeviceStack* devStack = NULL;
|
||||
|
||||
if (Fdo == NULL) {
|
||||
//
|
||||
// Telemetry events are logged during DriverEntry as well to capture non-pnp
|
||||
// and class extension (which are non-pnp drivers) driver info. Although
|
||||
// current UMDF datapoint doesn't have a separate flag for non-pnp driver,
|
||||
// we still want to log the driver name and its properies if available.
|
||||
//
|
||||
devStack = DriverGlobals->Driver->GetDriverObject()->WudfDevStack;
|
||||
if (devStack != NULL) {
|
||||
devStack->GetPdoProperties(&hardwareIds,
|
||||
&setupClass,
|
||||
&busEnum,
|
||||
&manufacturer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
devStack = Fdo->GetDeviceStack();
|
||||
devStack->GetPdoProperties(&hardwareIds,
|
||||
&setupClass,
|
||||
&busEnum,
|
||||
&manufacturer);
|
||||
|
||||
Fdo->RetrieveDeviceInfoRegistrySettings(&groupId, &devRegInfo);
|
||||
}
|
||||
|
||||
//
|
||||
// Log Driver info
|
||||
//
|
||||
if (Fdo != NULL) {
|
||||
GetDriverInfo(Fdo, &devRegInfo, &driverInfo);
|
||||
}
|
||||
|
||||
UMDF_CENSUS_EVT_WRITE_DEVICE_START(g_TelemetryProvider,
|
||||
DriverGlobals,
|
||||
driverInfo,
|
||||
setupClass,
|
||||
busEnum,
|
||||
hardwareIds,
|
||||
manufacturer);
|
||||
|
||||
if (groupId != NULL) {
|
||||
delete [] groupId;
|
||||
groupId = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
GetDriverInfo(
|
||||
_In_ FxDevice* Fdo,
|
||||
_In_ PUMDF_DRIVER_REGSITRY_INFO RegInfo,
|
||||
_Out_ UFxTelemetryDriverInfo* DriverInfo
|
||||
)
|
||||
{
|
||||
FxPkgPnp* pnpPkg;
|
||||
USHORT devInfo = 0;
|
||||
WDF_DEVICE_IO_TYPE readWritePreference;
|
||||
WDF_DEVICE_IO_TYPE ioControlPreference;
|
||||
UMDF_DRIVER_REGSITRY_INFO devRegInfo = {0};
|
||||
PWSTR groupId = NULL;
|
||||
|
||||
pnpPkg = (FxPkgPnp*)Fdo->GetFdoPkg();
|
||||
devInfo = Fdo->GetDeviceTelemetryInfoFlags();
|
||||
Fdo->GetDeviceStackIoType(&readWritePreference, &ioControlPreference);
|
||||
|
||||
DriverInfo->bitmap.IsFilter = Fdo->IsFilter();
|
||||
DriverInfo->bitmap.IsPowerPolicyOwner = pnpPkg->IsPowerPolicyOwner();
|
||||
DriverInfo->bitmap.IsS0IdleWakeFromS0Enabled = pnpPkg->IsS0IdleWakeFromS0Enabled();
|
||||
DriverInfo->bitmap.IsS0IdleUsbSSEnabled = pnpPkg->IsS0IdleUsbSSEnabled();
|
||||
DriverInfo->bitmap.IsS0IdleSystemManaged = pnpPkg->IsS0IdleSystemManaged();
|
||||
DriverInfo->bitmap.IsSxWakeEnabled = pnpPkg->IsSxWakeEnabled();
|
||||
DriverInfo->bitmap.IsUsingLevelTriggeredLineInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoLineBasedLevelTriggeredInterrupt);
|
||||
DriverInfo->bitmap.IsUsingEdgeTriggeredLineInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoLineBasedEdgeTriggeredInterrupt);
|
||||
DriverInfo->bitmap.IsUsingMsiXOrSingleMsi22Interrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoMsiXOrSingleMsi22Interrupt);
|
||||
DriverInfo->bitmap.IsUsingMsi22MultiMessageInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoMsi22MultiMessageInterrupt);
|
||||
DriverInfo->bitmap.IsUsingMultipleInterrupt = pnpPkg->HasMultipleInterrupts();
|
||||
DriverInfo->bitmap.IsDirectHardwareAccessAllowed = Fdo->IsDirectHardwareAccessAllowed();
|
||||
DriverInfo->bitmap.IsUsingUserModemappingAccessMode = Fdo->AreRegistersMappedToUsermode();
|
||||
DriverInfo->bitmap.IsKernelModeClientAllowed = RegInfo->IsKernelModeClientAllowed;
|
||||
DriverInfo->bitmap.IsNullFileObjectAllowed = RegInfo->IsNullFileObjectAllowed;
|
||||
DriverInfo->bitmap.IsPoolingDisabled = RegInfo->IsHostProcessSharingDisabled;
|
||||
DriverInfo->bitmap.IsMethodNeitherActionCopy = RegInfo->IsMethodNeitherActionCopy;
|
||||
DriverInfo->bitmap.IsUsingDirectIoForReadWrite = (readWritePreference == WdfDeviceIoDirect);
|
||||
DriverInfo->bitmap.IsUsingDirectIoForIoctl = (ioControlPreference == WdfDeviceIoDirect);
|
||||
DriverInfo->bitmap.IsUsingDriverWppRecorder = Fdo->GetDriver()->IsDriverObjectFlagSet(DriverObjectUmFlagsLoggingEnabled);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
GetImageName(
|
||||
_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
_Out_ PUNICODE_STRING ImageName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrieve the ImageName value from the named Service registry key.
|
||||
|
||||
Caller is responsible for freeing the buffer allocated in ImageName::Buffer.
|
||||
|
||||
Arguments:
|
||||
DriverGlobals - pointer to FX_DRIVER_GLOBALS
|
||||
|
||||
ImageeName - Pointer to a UNICODE_STRING which will receive the image name
|
||||
upon a return value of NT_SUCCESS()
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
FxAutoRegKey hKey;
|
||||
DECLARE_CONST_UNICODE_STRING(valueName, L"ImagePath");
|
||||
UNICODE_STRING imagePath = {0};
|
||||
UNICODE_STRING imageName = {0};
|
||||
PKEY_VALUE_PARTIAL_INFORMATION value = NULL;
|
||||
USHORT size;
|
||||
ULONG length, type;
|
||||
PVOID dataBuffer;
|
||||
|
||||
type = REG_SZ;
|
||||
length = 0;
|
||||
|
||||
ASSERT(ImageName != NULL);
|
||||
RtlZeroMemory(ImageName, sizeof(UNICODE_STRING));
|
||||
|
||||
//
|
||||
// Open driver's Service base key
|
||||
//
|
||||
status = FxRegKey::_OpenKey(NULL,
|
||||
FxDriverGlobals->Driver->GetRegistryPathUnicodeString(),
|
||||
&hKey.m_Key,
|
||||
KEY_READ);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"Unable to open driver's service key, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Find out how big a buffer we need to allocate if the value is present
|
||||
//
|
||||
status = FxRegKey::_QueryValue(FxDriverGlobals,
|
||||
hKey.m_Key,
|
||||
&valueName,
|
||||
length,
|
||||
NULL,
|
||||
&length,
|
||||
&type);
|
||||
|
||||
//
|
||||
// We expect the list to be bigger then a standard partial, so if it is
|
||||
// not, just bail now.
|
||||
//
|
||||
if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// Pool can be paged b/c we are running at PASSIVE_LEVEL and we are going
|
||||
// to free it at the end of this function.
|
||||
//
|
||||
dataBuffer = FxPoolAllocate(FxDriverGlobals, PagedPool, length);
|
||||
if (dataBuffer == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"Failed to allocate memory for image path string, %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Requery now that we have a big enough buffer
|
||||
//
|
||||
status = FxRegKey::_QueryValue(FxDriverGlobals,
|
||||
hKey.m_Key,
|
||||
&valueName,
|
||||
length,
|
||||
dataBuffer,
|
||||
&length,
|
||||
&type);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"Failed to get Image name from service key, %!STATUS!",
|
||||
status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify that the data from the registry is a valid string.
|
||||
//
|
||||
if (type != REG_SZ && type != REG_EXPAND_SZ) {
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (length == 0 || length > USHORT_MAX) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// string must be NULL-terminated
|
||||
//
|
||||
PWCHAR str = (PWCHAR) dataBuffer;
|
||||
if (str[(length/sizeof(WCHAR)) - 1] != UNICODE_NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"ERROR: string not terminated with NULL, %!status!\n",
|
||||
status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&imagePath, (PCWSTR) dataBuffer);
|
||||
|
||||
//
|
||||
// Now read the "ImagePath" and extract just the driver filename as a new
|
||||
// unicode string.
|
||||
//
|
||||
GetNameFromPath(&imagePath, &imageName);
|
||||
|
||||
if (imageName.Length == 0x0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"ERROR: GetNameFromPath could not find a name, %!status!\n",
|
||||
status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for interger overflow for length before we allocate memory
|
||||
// size = path->Length + sizeof(UNICODE_NULL);
|
||||
// len is used below to compute the string size including the NULL, so
|
||||
// compute len to include the terminating NULL.
|
||||
//
|
||||
status = RtlUShortAdd(imageName.Length, sizeof(UNICODE_NULL), &size);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"ERROR: size computation failed, %!status!\n", status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate a buffer to hold Unicode string + null char.
|
||||
//
|
||||
ImageName->Buffer = (PWCH) FxPoolAllocate(FxDriverGlobals, PagedPool, size);
|
||||
|
||||
if (ImageName->Buffer == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"ERROR: ExAllocatePoolWithTag failed, %!status!\n", status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
RtlZeroMemory(ImageName->Buffer, size);
|
||||
ImageName->Length = 0x0;
|
||||
ImageName->MaximumLength = size;
|
||||
|
||||
HRESULT hr = StringCbCopy(ImageName->Buffer, size, imageName.Buffer);
|
||||
if (FAILED(hr)) {
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
||||
"ERROR: failed to copy string buffer, HRESULT 0x%x, %!status!\n",
|
||||
hr, status);
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
//
|
||||
// The copy cannot fail since we setup the buffer to hold enough space for
|
||||
// the contents of the ImagePath value.
|
||||
//
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
|
||||
cleanUp:
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (ImageName->Buffer != NULL) {
|
||||
FxPoolFree(ImageName->Buffer);
|
||||
RtlInitUnicodeString(ImageName, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataBuffer != NULL) {
|
||||
FxPoolFree(dataBuffer);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
838
sdk/lib/drivers/wdf/shared/support/um/tracingum.cpp
Normal file
838
sdk/lib/drivers/wdf/shared/support/um/tracingum.cpp
Normal file
|
@ -0,0 +1,838 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
Tracing.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements tracing for the driver frameworks
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
#include "fxldrum.h"
|
||||
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "TracingUM.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <initguid.h>
|
||||
#include "fxIFR.h" // shared struct between IFR and debug ext.
|
||||
#include "fxIFRKm.h" // kernel mode only IFR definitions
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxTraceInitialize(
|
||||
VOID
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine initializes the frameworks tracing.
|
||||
|
||||
It must be called early on in the frameworks DriverEntry
|
||||
initialization.
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS code
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Initialize the tracing package.
|
||||
//
|
||||
WPP_INIT_TRACING(NULL, NULL);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
TraceUninitialize(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This routine uninitializes the frameworks tracing. It must be called just
|
||||
before DriverUnload
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
WPP_CLEANUP(NULL);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiQueryTraceInformation(
|
||||
__in TRACE_INFORMATION_CLASS /* TraceInformationClass */,
|
||||
__out_bcount(TraceInformationLength) PVOID /* TraceInformation */,
|
||||
__in ULONG /* TraceInformationLength */,
|
||||
__out_opt PULONG /* RequiredLength */,
|
||||
__in_opt PVOID /* Buffer */
|
||||
)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiTraceMessage(
|
||||
__in TRACEHANDLE LoggerHandle,
|
||||
__in ULONG MessageFlags,
|
||||
__in LPGUID MessageGuid,
|
||||
__in USHORT MessageNumber,
|
||||
...
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
va_list va;
|
||||
va_start(va, MessageNumber);
|
||||
//
|
||||
// UMDF is supported only on XP and newer OS so no need to support w2k
|
||||
// tracing (which requires using a different tracing api, see kmdf impl)
|
||||
//
|
||||
#pragma prefast(suppress:__WARNING_BUFFER_OVERFLOW, "Recommneded by EndClean");
|
||||
status = TraceMessageVa(LoggerHandle,
|
||||
MessageFlags,
|
||||
MessageGuid,
|
||||
MessageNumber,
|
||||
va);
|
||||
|
||||
va_end(va);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Subcomponents for the In-Flight Recorder follow.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ULONG
|
||||
FxIFRGetSize(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PCUNICODE_STRING RegistryPath
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Checks to see if the service has overriden the default number of pages that
|
||||
are in the IFR.
|
||||
|
||||
Arguments:
|
||||
RegistryPath - path to the service
|
||||
|
||||
Return Value:
|
||||
The size of the IFR to create in bytes (not pages!)
|
||||
|
||||
--*/
|
||||
{
|
||||
FxAutoRegKey service, parameters;
|
||||
NTSTATUS status;
|
||||
ULONG numPages;
|
||||
|
||||
//
|
||||
// This is the value used in case of any error while retrieving 'LogPages'
|
||||
// from the registry.
|
||||
//
|
||||
numPages = FxIFRMinLogPages;
|
||||
|
||||
//
|
||||
// External representation of the IFR is the "log", so use tha term when
|
||||
// overriding the size via the registry.
|
||||
//
|
||||
DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
|
||||
DECLARE_CONST_UNICODE_STRING(valueName, L"LogPages");
|
||||
|
||||
//
|
||||
// UMDF may not provide this registry path
|
||||
//
|
||||
if (NULL == RegistryPath) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
status = FxRegKey::_OpenKey(NULL,
|
||||
(PCUNICODE_STRING)RegistryPath,
|
||||
&service.m_Key,
|
||||
KEY_READ);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
status = FxRegKey::_OpenKey(service.m_Key,
|
||||
(PCUNICODE_STRING)¶metersPath,
|
||||
¶meters.m_Key,
|
||||
KEY_READ);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
status = FxRegKey::_QueryULong(parameters.m_Key, &valueName, &numPages);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
if (numPages == 0) {
|
||||
numPages = FxIFRMinLogPages;
|
||||
}
|
||||
|
||||
defaultValues:
|
||||
//
|
||||
// This behavior is different from KMDF. KMDF would allocate Average page count (5)
|
||||
// if Verifier is on otherwise 1 page if the request is large.
|
||||
// Since for UMDF the memory is coming from WudfRd, which does not know about verifier
|
||||
// we will give it max pages here.
|
||||
//
|
||||
if (numPages > FxIFRMaxLogPages) {
|
||||
numPages = FxIFRMaxLogPages;
|
||||
}
|
||||
|
||||
return numPages * PAGE_SIZE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIFRStart(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PCUNICODE_STRING RegistryPath,
|
||||
__in MdDriverObject DriverObject
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine initialize the In-Flight Recorder (IFR).
|
||||
|
||||
The default log size is set by WDF_IFR_LOG_SIZE and currently
|
||||
is 4096 (one x86 page).
|
||||
This routine should be called very early in driver initialization
|
||||
to allow the capture of all significant events.
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
PWDF_IFR_HEADER pHeader;
|
||||
ULONG pageCount;
|
||||
ULONG sizeCb;
|
||||
HRESULT hr;
|
||||
IWudfDeviceStack2 *pDeviceStack2;
|
||||
PDRIVER_OBJECT_UM umDriverObject;
|
||||
PWCHAR serviceName;
|
||||
size_t bufferLengthCch;
|
||||
ULONG allocatedBufferLengthCb;
|
||||
LONG i;
|
||||
|
||||
//
|
||||
// Return early if IFR is disabled.
|
||||
//
|
||||
if (FxLibraryGlobals.IfrDisabled) {
|
||||
ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
WDFCASSERT(FxIFRRecordSignature == WDF_IFR_RECORD_SIGNATURE);
|
||||
|
||||
if (FxDriverGlobals == NULL || FxDriverGlobals->WdfLogHeader != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// It is safe to use StringCchLength here as WudfHost makes sure that this
|
||||
// RegistryPath is null terminated
|
||||
//
|
||||
hr = StringCchLength(RegistryPath->Buffer,
|
||||
RegistryPath->MaximumLength/sizeof(WCHAR),
|
||||
&bufferLengthCch);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Lets find the last '\' that will mark the begining of the service name
|
||||
//
|
||||
for (i = (ULONG)bufferLengthCch - 1;
|
||||
i >= 0 && RegistryPath->Buffer[i] != '\\';
|
||||
i--);
|
||||
|
||||
//
|
||||
// We did not find the service name
|
||||
//
|
||||
if (i < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
serviceName = &RegistryPath->Buffer[i+1];
|
||||
|
||||
sizeCb = FxIFRGetSize(FxDriverGlobals, RegistryPath);
|
||||
pageCount = sizeCb / PAGE_SIZE;
|
||||
|
||||
//
|
||||
// Get the IWudfDeviceStack interface
|
||||
//
|
||||
umDriverObject = (PDRIVER_OBJECT_UM)DriverObject;
|
||||
|
||||
pDeviceStack2 = (IWudfDeviceStack2 *)umDriverObject->WudfDevStack;
|
||||
|
||||
if(pDeviceStack2 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
allocatedBufferLengthCb = 0;
|
||||
hr = pDeviceStack2->AllocateIfrMemory(serviceName,
|
||||
pageCount,
|
||||
FALSE,
|
||||
TRUE,
|
||||
(PVOID *)&pHeader,
|
||||
&allocatedBufferLengthCb);
|
||||
|
||||
if (pHeader == NULL || allocatedBufferLengthCb <= sizeof(WDF_IFR_HEADER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the header.
|
||||
// Base will be where the IFR records are placed.
|
||||
// WPP_ThisDir_CTLGUID_FrameworksTraceGuid
|
||||
//
|
||||
RtlCopyMemory(&pHeader->Guid, (PVOID) &WdfTraceGuid, sizeof(GUID));
|
||||
|
||||
pHeader->Base = (PUCHAR) &pHeader[1];
|
||||
pHeader->Size = allocatedBufferLengthCb - sizeof(WDF_IFR_HEADER);
|
||||
|
||||
pHeader->Offset.u.s.Current = 0;
|
||||
pHeader->Offset.u.s.Previous = 0;
|
||||
pHeader->SequenceNumberPointer = &(DriverObject->IfrSequenceNumber);
|
||||
|
||||
StringCchCopyA(pHeader->DriverName, WDF_IFR_HEADER_NAME_LEN, FxDriverGlobals->Public.DriverName);
|
||||
|
||||
FxDriverGlobals->WdfLogHeader = pHeader;
|
||||
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"FxIFR logging started" );
|
||||
|
||||
if (sizeCb > FxIFRMinLogSize) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER,
|
||||
"FxIFR has been started with a size override: size 0x%x bytes, "
|
||||
"# Pages %d. An extended IFR size may not be written to a minidump!",
|
||||
sizeCb, sizeCb/PAGE_SIZE);
|
||||
}
|
||||
|
||||
if (sizeCb != allocatedBufferLengthCb) {
|
||||
ASSERTMSG("FxIFR requested buffer size could not be allocated",FALSE);
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDRIVER,
|
||||
"FxIFR requested an allocation of size 0x%x bytes, "
|
||||
"Allocated memory was of size 0x%x bytes",
|
||||
sizeCb, allocatedBufferLengthCb);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIFRStop(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine stops the In-Flight Recorder (IFR).
|
||||
|
||||
For UMDF FxIFRStop is no longer required as WudfRd manages the buffer's lifetime
|
||||
The buffer is kept alive till WudfRd unloads to aid in debugging in cases of
|
||||
WudfHost crash or in dumps with WudfHost paged out or not captured
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(FxDriverGlobals);
|
||||
|
||||
//
|
||||
// Uncomment the code below if you add any logic to this function.
|
||||
//
|
||||
// if (FxLibraryGlobals.IfrDisabled) {
|
||||
// ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIFR(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in UCHAR MessageLevel,
|
||||
__in ULONG MessageFlags,
|
||||
__in LPGUID MessageGuid,
|
||||
__in USHORT MessageNumber,
|
||||
...
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is the main In-Flight Recorder (IFR) routine.
|
||||
|
||||
It captures a WPP message to the IFR log.
|
||||
The IFR is always running, e.g. not WPP logger is necessary
|
||||
to start logging.
|
||||
|
||||
Arguments:
|
||||
|
||||
MessageLevel - The WPP message level for this event
|
||||
MessageFlags - The WPP message flags for this event (see trace GUID)
|
||||
MessageGuid - The tracewpp generated guid for module emitting this event.
|
||||
MessageNumber - The tracewpp generated message number within
|
||||
the emitting module.
|
||||
... - Variable arguments associates with the emitted message.
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
size_t size;
|
||||
PWDF_IFR_RECORD record;
|
||||
|
||||
UNREFERENCED_PARAMETER( MessageLevel );
|
||||
|
||||
//
|
||||
// Return early if IFR is disabled.
|
||||
//
|
||||
if (FxLibraryGlobals.IfrDisabled) {
|
||||
ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ( FxDriverGlobals->WdfLogHeader == NULL) {
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UNREFERENCED_PARAMETER( MessageFlags );
|
||||
|
||||
|
||||
//
|
||||
// Determine the number bytes to follow header
|
||||
//
|
||||
size = 0; // For Count of Bytes
|
||||
|
||||
//
|
||||
// Determine how much log space is needed for this
|
||||
// trace record's data.
|
||||
//
|
||||
{
|
||||
va_list ap;
|
||||
size_t argLen;
|
||||
|
||||
va_start(ap, MessageNumber);
|
||||
#pragma prefast(suppress: __WARNING_BUFFER_OVERFLOW, "Recommneded by EndClean");
|
||||
while ((va_arg(ap, PVOID)) != NULL) {
|
||||
|
||||
argLen = va_arg(ap, size_t);
|
||||
|
||||
if (argLen > 0) {
|
||||
|
||||
if (argLen > FxIFRMaxMessageSize) {
|
||||
goto drop_message;
|
||||
}
|
||||
size += (USHORT) argLen;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
//
|
||||
// NOTE: The final size must be 32-bit (ULONG) aligned.
|
||||
// This is necessary for IA64 to prevent Alignment Faults.
|
||||
//
|
||||
size += (size % sizeof(ULONG)) ? sizeof(ULONG) - (size % sizeof(ULONG)) : 0;
|
||||
|
||||
if (size > FxIFRMaxMessageSize) {
|
||||
goto drop_message;
|
||||
}
|
||||
}
|
||||
|
||||
size += sizeof(WDF_IFR_RECORD);
|
||||
|
||||
//
|
||||
// Allocate log space of the calculated size
|
||||
//
|
||||
{
|
||||
PWDF_IFR_HEADER header;
|
||||
WDF_IFR_OFFSET offsetRet;
|
||||
WDF_IFR_OFFSET offsetCur;
|
||||
WDF_IFR_OFFSET offsetNew;
|
||||
USHORT usSize = (USHORT) size; // for a prefast artifact.
|
||||
|
||||
header = (PWDF_IFR_HEADER) FxDriverGlobals->WdfLogHeader;
|
||||
ASSERT(header->Size < FxIFRMaxLogSize); // size doesn't include header.
|
||||
ASSERT(header->Size >= header->Offset.u.s.Current);
|
||||
ASSERT(header->Size >= header->Offset.u.s.Previous);
|
||||
|
||||
offsetRet.u.AsLONG = header->Offset.u.AsLONG;
|
||||
offsetNew.u.AsLONG = offsetRet.u.s.Current;
|
||||
|
||||
do {
|
||||
offsetCur.u.AsLONG = offsetRet.u.AsLONG;
|
||||
|
||||
if (&header->Base[header->Size] < &header->Base[offsetCur.u.s.Current+size]) {
|
||||
|
||||
offsetNew.u.s.Current = 0;
|
||||
offsetNew.u.s.Previous = offsetRet.u.s.Previous;
|
||||
|
||||
offsetRet.u.AsLONG =
|
||||
InterlockedCompareExchange( &header->Offset.u.AsLONG,
|
||||
offsetNew.u.AsLONG,
|
||||
offsetCur.u.AsLONG );
|
||||
|
||||
if (offsetCur.u.AsLONG != offsetRet.u.AsLONG) {
|
||||
continue;
|
||||
} else {
|
||||
offsetNew.u.s.Current = offsetCur.u.s.Current + usSize;
|
||||
offsetNew.u.s.Previous = offsetRet.u.s.Current;
|
||||
}
|
||||
} else {
|
||||
|
||||
offsetNew.u.s.Current = offsetCur.u.s.Current + usSize;
|
||||
offsetNew.u.s.Previous = offsetCur.u.s.Current;
|
||||
}
|
||||
|
||||
offsetRet.u.AsLONG =
|
||||
InterlockedCompareExchange( &header->Offset.u.AsLONG,
|
||||
offsetNew.u.AsLONG,
|
||||
offsetCur.u.AsLONG );
|
||||
|
||||
} while (offsetCur.u.AsLONG != offsetRet.u.AsLONG);
|
||||
|
||||
record = (PWDF_IFR_RECORD) &header->Base[offsetRet.u.s.Current];
|
||||
|
||||
// RtlZeroMemory( record, sizeof(WDF_IFR_RECORD) );
|
||||
|
||||
//
|
||||
// Build record (fill all fields!)
|
||||
//
|
||||
record->Signature = FxIFRRecordSignature;
|
||||
record->Length = (USHORT) size;
|
||||
record->PrevOffset = (USHORT) offsetRet.u.s.Previous;
|
||||
record->MessageNumber = MessageNumber;
|
||||
record->Sequence = InterlockedIncrement(header->SequenceNumberPointer);
|
||||
record->MessageGuid = *MessageGuid;
|
||||
}
|
||||
|
||||
//
|
||||
// Move variable part of data into log.
|
||||
//
|
||||
{
|
||||
va_list ap;
|
||||
size_t argLen;
|
||||
PVOID source;
|
||||
PUCHAR argsData;
|
||||
|
||||
argsData = (UCHAR*) &record[1];
|
||||
|
||||
va_start(ap, MessageNumber);
|
||||
#pragma prefast(suppress: __WARNING_BUFFER_OVERFLOW, "Recommneded by EndClean");
|
||||
while ((source = va_arg(ap, PVOID)) != NULL) {
|
||||
|
||||
argLen = va_arg(ap, size_t);
|
||||
|
||||
if (argLen > 0) {
|
||||
|
||||
RtlCopyMemory( argsData, source, argLen );
|
||||
argsData += argLen;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
{
|
||||
//
|
||||
// Increment sequence number to indicate dropped message
|
||||
//
|
||||
drop_message:
|
||||
PWDF_IFR_HEADER header;
|
||||
header = (PWDF_IFR_HEADER) FxDriverGlobals->WdfLogHeader;
|
||||
InterlockedIncrement(header->SequenceNumberPointer);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue