/*++ Copyright (c) Microsoft Corporation ModuleName: MxGeneralUm.h Abstract: User mode implementation for general OS functions defined in MxGeneral.h Author: Revision History: --*/ #pragma once #define MAKE_MX_FUNC_NAME(x) x #define REMOVE_LOCK_RELEASE_TIMEOUT_IN_SECONDS 45 typedef VOID THREADPOOL_WAIT_CALLBACK ( __inout PTP_CALLBACK_INSTANCE Instance, __inout_opt PVOID Context, __inout PTP_WAIT Wait, __in TP_WAIT_RESULT WaitResult ); typedef THREADPOOL_WAIT_CALLBACK MdInterruptServiceRoutineType, *MdInterruptServiceRoutine; typedef BOOLEAN InterruptSynchronizeRoutine ( __in PVOID SynchronizeContext ); typedef InterruptSynchronizeRoutine MdInterruptSynchronizeRoutineType, *MdInterruptSynchronizeRoutine; typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT; typedef VOID CALLBACK_FUNCTION( __in PVOID CallbackContext, __in_opt PVOID Argument1, __in_opt PVOID Argument2 ); typedef CALLBACK_FUNCTION MdCallbackFunctionType, *MdCallbackFunction; // // Define PnP notification event categories // typedef enum _IO_NOTIFICATION_EVENT_CATEGORY { EventCategoryReserved, EventCategoryHardwareProfileChange, EventCategoryDeviceInterfaceChange, EventCategoryTargetDeviceChange } IO_NOTIFICATION_EVENT_CATEGORY; #include "MxGeneral.h" __inline BOOLEAN Mx::IsUM( ) { return TRUE; } __inline BOOLEAN Mx::IsKM( ) { return FALSE; } __inline MxThread Mx::MxGetCurrentThread( ) { // // We can't use GetCurrentThread as it returns a pseudo handle // which would have same numeric value for different threads // We could use DuplicateHandle to get real handle but that has the // following problems: // 1) It returns different handle values for the same thread // if called again without closing handle. // 2) Makes the caller call CloseHandle making it inconvenient to // call this function just to get an identifier for the thread // 3) More expensive than GetCurrentThreadId // // Since framework uses the thread only for comparison, logging // purposes GetCurrentThreadId works well. // It is cast to PVOID to match the pointer type PKTHREAD otherwise // trace functions complain of data type mismatch // return (PVOID) ::GetCurrentThreadId(); } __inline MdEThread Mx::GetCurrentEThread( ) { // // See comments in MxGetCurrentThread. // return (PVOID) MxGetCurrentThread(); } __inline NTSTATUS Mx::MxTerminateCurrentThread( __in NTSTATUS Status ) { #pragma prefast(suppress:__WARNING_USINGTERMINATETHREAD, "TerminateThread is the intent."); if (!TerminateThread(::GetCurrentThread(), HRESULT_FROM_NT(Status))) { DWORD err = GetLastError(); return WinErrorToNtStatus(err); } return STATUS_SUCCESS; } __inline KIRQL Mx::MxGetCurrentIrql( ) { return PASSIVE_LEVEL; } __inline VOID #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations."); Mx::MxRaiseIrql( __in KIRQL NewIrql, __out PKIRQL OldIrql ) { UNREFERENCED_PARAMETER(NewIrql); UNREFERENCED_PARAMETER(OldIrql); DO_NOTHING(); } __inline VOID #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations."); Mx::MxLowerIrql( __in KIRQL NewIrql ) { UNREFERENCED_PARAMETER(NewIrql); DO_NOTHING(); } __inline VOID Mx::MxQueryTickCount( __out PLARGE_INTEGER TickCount ) { TickCount->QuadPart = GetTickCount(); } __inline ULONG Mx::MxQueryTimeIncrement( ) { // // The way to get absolute time is TickCount * TimeIncrement. // In UM, TickCount is expressed in miliseconds, so this // conversion ensures that absolute time is expressed // in 100ns units as it is in KM. // return 1000 * 10; } __inline VOID Mx::MxDbgBreakPoint( ) { DebugBreak(); } __inline VOID Mx::MxAssert( __in BOOLEAN Condition ) { if (!Condition) { DebugBreak(); } } __inline VOID Mx::MxAssertMsg( __in LPSTR Message, __in BOOLEAN Condition ) { UNREFERENCED_PARAMETER(Message); if (!Condition) { DebugBreak(); } } __inline VOID #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "Can't apply kernel mode annotations."); Mx::MxEnterCriticalRegion( ) { // DO_NOTHING(); } __inline VOID #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "Can't apply kernel mode annotations."); Mx::MxLeaveCriticalRegion( ) { // DO_NOTHING(); } __inline VOID Mx::MxDelayExecutionThread( __in KPROCESSOR_MODE WaitMode, __in BOOLEAN Alertable, __in PLARGE_INTEGER Interval ) { UNREFERENCED_PARAMETER(WaitMode); ASSERTMSG("Interval must be relative\n", Interval->QuadPart <= 0); LARGE_INTEGER intervalMillisecond; // // This function uses KeDelayExecutionThread's contract, where relative // intervals are negative numbers expressed in 100ns units. We must // flip the sign and convert to ms units before calling SleepEx. // intervalMillisecond.QuadPart = -1 * Interval->QuadPart; intervalMillisecond.QuadPart /= 10 * 1000; SleepEx((DWORD)intervalMillisecond.QuadPart, Alertable); } __inline PVOID Mx::MxGetSystemRoutineAddress( __in MxFuncName FuncName ) /*++ Description: This function is meant to be called only by mode agnostic code System routine is assumed to be in ntdll.dll. This is because system routines (Rtl*) that can be used both in kernel mode as well as user mode reside in ntdll.dll. Kernel32.dll contains the user mode only Win32 API. Arguments: MxFuncName FuncName - Return Value: NTSTATUS Status code. --*/ { HMODULE hMod; hMod = GetModuleHandleW(L"ntdll.dll"); return GetProcAddress(hMod, FuncName); } __inline VOID Mx::MxReferenceObject( __in PVOID Object ) { UNREFERENCED_PARAMETER(Object); // DO_NOTHING(); } __inline VOID Mx::MxDereferenceObject( __in PVOID Object ) { UNREFERENCED_PARAMETER(Object); // DO_NOTHING(); } __inline VOID Mx::MxInitializeRemoveLock( __in MdRemoveLock Lock, __in ULONG AllocateTag, __in ULONG MaxLockedMinutes, __in ULONG HighWatermark ) { UNREFERENCED_PARAMETER(AllocateTag); UNREFERENCED_PARAMETER(MaxLockedMinutes); UNREFERENCED_PARAMETER(HighWatermark); ZeroMemory(Lock, sizeof(*Lock)); Lock->IoCount = 1; Lock->Removed = FALSE; Lock->RemoveEvent = NULL; Lock->ReleaseRemLockAndWaitStatus = (DWORD)-1; } __inline NTSTATUS Mx::MxAcquireRemoveLock( __in MdRemoveLock RemoveLock, __in_opt PVOID Tag ) { UNREFERENCED_PARAMETER(Tag); LONG lockValue; NTSTATUS status; lockValue = InterlockedIncrement(&RemoveLock->IoCount); ASSERT(lockValue > 0); if (! RemoveLock->Removed) { return STATUS_SUCCESS; } else { if (0 == InterlockedDecrement(&RemoveLock->IoCount)) { if (! SetEvent(RemoveLock->RemoveEvent)) { Mx::MxBugCheckEx(WDF_VIOLATION, 0, 0, 0, 0); } } status = STATUS_DELETE_PENDING; } return status; } __inline VOID Mx::MxReleaseRemoveLock( __in MdRemoveLock RemoveLock, __in PVOID Tag ) { UNREFERENCED_PARAMETER(Tag); LONG lockValue; lockValue = InterlockedDecrement(&RemoveLock->IoCount); ASSERT(0 <= lockValue); if (0 == lockValue) { ASSERT (RemoveLock->Removed); // // The device needs to be removed. Signal the remove event // that it's safe to go ahead. // if (! SetEvent(RemoveLock->RemoveEvent)) { Mx::MxBugCheckEx(WDF_VIOLATION, 0, 0, 0, 0); } } } __inline VOID Mx::MxReleaseRemoveLockAndWait( __in MdRemoveLock RemoveLock, __in PVOID Tag ) { UNREFERENCED_PARAMETER(Tag); LONG ioCount; DWORD retVal = ERROR_SUCCESS; RemoveLock->Removed = TRUE; ioCount = InterlockedDecrement (&RemoveLock->IoCount); ASSERT(0 < ioCount); if (0 < InterlockedDecrement (&RemoveLock->IoCount)) { retVal = WaitForSingleObject(RemoveLock->RemoveEvent, REMOVE_LOCK_RELEASE_TIMEOUT_IN_SECONDS*1000); ASSERT(retVal == WAIT_OBJECT_0); } // This only serves as a debugging aid. RemoveLock->ReleaseRemLockAndWaitStatus = retVal; } __inline BOOLEAN Mx::MxHasEnoughRemainingThreadStack( VOID ) { // // Thread stack is not so scarce in UM so return TRUE always // return TRUE; } __inline VOID #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations."); Mx::ReleaseCancelSpinLock( __in KIRQL Irql ) { UNREFERENCED_PARAMETER(Irql); // // UMDF Host doesn't have cancel spinlock equivalent concept so do nothing. // DO_NOTHING(); } __inline NTSTATUS Mx::CreateCallback( __out PCALLBACK_OBJECT *CallbackObject, __in POBJECT_ATTRIBUTES ObjectAttributes, __in BOOLEAN Create, __in BOOLEAN AllowMultipleCallbacks ) { UNREFERENCED_PARAMETER(CallbackObject); UNREFERENCED_PARAMETER(ObjectAttributes); UNREFERENCED_PARAMETER(Create); UNREFERENCED_PARAMETER(AllowMultipleCallbacks); return STATUS_UNSUCCESSFUL; } __inline PVOID Mx::RegisterCallback( __in PCALLBACK_OBJECT CallbackObject, __in MdCallbackFunction CallbackFunction, __in PVOID CallbackContext ) { UNREFERENCED_PARAMETER(CallbackObject); UNREFERENCED_PARAMETER(CallbackFunction); UNREFERENCED_PARAMETER(CallbackContext); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline VOID Mx::UnregisterCallback( __in PVOID CbRegistration ) { UNREFERENCED_PARAMETER(CbRegistration); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxUnlockPages( __in PMDL Mdl ) { UNREFERENCED_PARAMETER(Mdl); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline PVOID Mx::MxGetSystemAddressForMdlSafe( __inout PMDL Mdl, __in ULONG Priority ) { UNREFERENCED_PARAMETER(Mdl); UNREFERENCED_PARAMETER(Priority); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline VOID Mx::MxBuildMdlForNonPagedPool( __inout PMDL Mdl ) { UNREFERENCED_PARAMETER(Mdl); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline PVOID Mx::MxGetDriverObjectExtension( __in MdDriverObject DriverObject, __in PVOID ClientIdentificationAddress ) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(ClientIdentificationAddress); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline NTSTATUS Mx::MxAllocateDriverObjectExtension( _In_ MdDriverObject DriverObject, _In_ PVOID ClientIdentificationAddress, _In_ ULONG DriverObjectExtensionSize, // When successful, this always allocates already-aliased memory. _Post_ _At_(*DriverObjectExtension, _When_(return==0, __drv_aliasesMem __drv_allocatesMem(Mem) _Post_notnull_)) _When_(return == 0, _Outptr_result_bytebuffer_(DriverObjectExtensionSize)) PVOID *DriverObjectExtension ) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(ClientIdentificationAddress); UNREFERENCED_PARAMETER(DriverObjectExtensionSize); UNREFERENCED_PARAMETER(DriverObjectExtension); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_UNSUCCESSFUL; } __inline MdDeviceObject Mx::MxGetAttachedDeviceReference( __in MdDeviceObject DriverObject ) { UNREFERENCED_PARAMETER(DriverObject); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline VOID Mx::MxDeleteSymbolicLink( __in PUNICODE_STRING Value ) { UNREFERENCED_PARAMETER(Value); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxDeleteNPagedLookasideList( _In_ PNPAGED_LOOKASIDE_LIST LookasideList ) { UNREFERENCED_PARAMETER(LookasideList); } __inline VOID Mx::MxDeletePagedLookasideList( _In_ PPAGED_LOOKASIDE_LIST LookasideList ) { UNREFERENCED_PARAMETER(LookasideList); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxInitializeNPagedLookasideList( _Out_ PNPAGED_LOOKASIDE_LIST Lookaside, _In_opt_ PALLOCATE_FUNCTION Allocate, _In_opt_ PFREE_FUNCTION Free, _In_ ULONG Flags, _In_ SIZE_T Size, _In_ ULONG Tag, _In_ USHORT Depth ) { UNREFERENCED_PARAMETER(Lookaside); UNREFERENCED_PARAMETER(Allocate); UNREFERENCED_PARAMETER(Free); UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(Size); UNREFERENCED_PARAMETER(Tag); UNREFERENCED_PARAMETER(Depth); //ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxInitializePagedLookasideList( _Out_ PPAGED_LOOKASIDE_LIST Lookaside, _In_opt_ PALLOCATE_FUNCTION Allocate, _In_opt_ PFREE_FUNCTION Free, _In_ ULONG Flags, _In_ SIZE_T Size, _In_ ULONG Tag, _In_ USHORT Depth ) { UNREFERENCED_PARAMETER(Lookaside); UNREFERENCED_PARAMETER(Allocate); UNREFERENCED_PARAMETER(Free); UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(Size); UNREFERENCED_PARAMETER(Tag); UNREFERENCED_PARAMETER(Depth); //ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxDeleteDevice( _In_ MdDeviceObject Device ) { UNREFERENCED_PARAMETER(Device); // // Host's device stack object holds the only reference to the host devices. // The infrastructure controls the device object's lifetime. // DO_NOTHING(); } __inline NTSTATUS Mx::MxCreateDeviceSecure( _In_ MdDriverObject DriverObject, _In_ ULONG DeviceExtensionSize, _In_opt_ PUNICODE_STRING DeviceName, _In_ DEVICE_TYPE DeviceType, _In_ ULONG DeviceCharacteristics, _In_ BOOLEAN Exclusive, _In_ PCUNICODE_STRING DefaultSDDLString, _In_opt_ LPCGUID DeviceClassGuid, _Out_opt_ MdDeviceObject *DeviceObject ) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(DeviceExtensionSize); UNREFERENCED_PARAMETER(DeviceName); UNREFERENCED_PARAMETER(DeviceType); UNREFERENCED_PARAMETER(Exclusive); UNREFERENCED_PARAMETER(DeviceCharacteristics); UNREFERENCED_PARAMETER(DefaultSDDLString); UNREFERENCED_PARAMETER(DeviceClassGuid); UNREFERENCED_PARAMETER(DeviceObject); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_SUCCESS; } __inline MdDeviceObject Mx::MxAttachDeviceToDeviceStack( _In_ MdDeviceObject SourceDevice, _In_ MdDeviceObject TargetDevice ) { UNREFERENCED_PARAMETER(SourceDevice); UNREFERENCED_PARAMETER(TargetDevice); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline NTSTATUS Mx::MxCreateDevice( _In_ MdDriverObject DriverObject, _In_ ULONG DeviceExtensionSize, _In_opt_ PUNICODE_STRING DeviceName, _In_ DEVICE_TYPE DeviceType, _In_ ULONG DeviceCharacteristics, _In_ BOOLEAN Exclusive, _Out_opt_ MdDeviceObject *DeviceObject ) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(DeviceExtensionSize); UNREFERENCED_PARAMETER(DeviceName); UNREFERENCED_PARAMETER(DeviceType); UNREFERENCED_PARAMETER(DeviceCharacteristics); UNREFERENCED_PARAMETER(Exclusive); UNREFERENCED_PARAMETER(DeviceObject); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_SUCCESS; } __inline NTSTATUS Mx::MxCreateSymbolicLink( _In_ PUNICODE_STRING SymbolicLinkName, _In_ PUNICODE_STRING DeviceName ) { UNREFERENCED_PARAMETER(SymbolicLinkName); UNREFERENCED_PARAMETER(DeviceName); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline VOID Mx::MxFlushQueuedDpcs( ) { // // Not supported for UMDF // } __inline NTSTATUS Mx::MxOpenKey( _In_ PHANDLE KeyHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes ) { UNREFERENCED_PARAMETER(KeyHandle); UNREFERENCED_PARAMETER(DesiredAccess); UNREFERENCED_PARAMETER(ObjectAttributes); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxSetDeviceInterfaceState( _In_ PUNICODE_STRING SymbolicLinkName, _In_ BOOLEAN Enable ) { UNREFERENCED_PARAMETER(SymbolicLinkName); UNREFERENCED_PARAMETER(Enable); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxRegisterDeviceInterface( _In_ PDEVICE_OBJECT PhysicalDeviceObject, _In_ const GUID *InterfaceClassGuid, _In_opt_ PUNICODE_STRING ReferenceString, _Out_ PUNICODE_STRING SymbolicLinkName ) { UNREFERENCED_PARAMETER(PhysicalDeviceObject); UNREFERENCED_PARAMETER(InterfaceClassGuid); UNREFERENCED_PARAMETER(ReferenceString); UNREFERENCED_PARAMETER(SymbolicLinkName); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxDeleteKey( _In_ HANDLE KeyHandle ) { UNREFERENCED_PARAMETER(KeyHandle); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline VOID Mx::MxInitializeMdl( _In_ PMDL MemoryDescriptorList, _In_ PVOID BaseVa, _In_ SIZE_T Length ) { UNREFERENCED_PARAMETER(MemoryDescriptorList); UNREFERENCED_PARAMETER(BaseVa); UNREFERENCED_PARAMETER(Length); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline PVOID Mx::MxGetMdlVirtualAddress( _In_ PMDL Mdl ) { UNREFERENCED_PARAMETER(Mdl); ASSERTMSG("Not implemented for UMDF\n", FALSE); return NULL; } __inline VOID Mx::MxBuildPartialMdl( _In_ PMDL SourceMdl, _Inout_ PMDL TargetMdl, _In_ PVOID VirtualAddress, _In_ ULONG Length ) { UNREFERENCED_PARAMETER(SourceMdl); UNREFERENCED_PARAMETER(TargetMdl); UNREFERENCED_PARAMETER(VirtualAddress); UNREFERENCED_PARAMETER(Length); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline VOID Mx::MxQuerySystemTime( _Out_ PLARGE_INTEGER CurrentTime ) { UNREFERENCED_PARAMETER(CurrentTime); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline NTSTATUS Mx::MxSetValueKey( _In_ HANDLE KeyHandle, _In_ PUNICODE_STRING ValueName, _In_opt_ ULONG TitleIndex, _In_ ULONG Type, _In_opt_ PVOID Data, _In_ ULONG DataSize ) { UNREFERENCED_PARAMETER(KeyHandle); UNREFERENCED_PARAMETER(ValueName); UNREFERENCED_PARAMETER(TitleIndex); UNREFERENCED_PARAMETER(Type); UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(DataSize); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxQueryValueKey( _In_ HANDLE KeyHandle, _In_ PUNICODE_STRING ValueName, _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, _Out_opt_ PVOID KeyValueInformation, _In_ ULONG Length, _Out_ PULONG ResultLength ) { UNREFERENCED_PARAMETER(KeyHandle); UNREFERENCED_PARAMETER(ValueName); UNREFERENCED_PARAMETER(KeyValueInformationClass); UNREFERENCED_PARAMETER(KeyValueInformation); UNREFERENCED_PARAMETER(Length); UNREFERENCED_PARAMETER(ResultLength); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxUnRegisterPlugPlayNotification( __in __drv_freesMem(Pool) PVOID NotificationEntry ) { UNREFERENCED_PARAMETER(NotificationEntry); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxReferenceObjectByHandle( __in HANDLE Handle, __in ACCESS_MASK DesiredAccess, __in_opt POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __out PVOID *Object, __out_opt POBJECT_HANDLE_INFORMATION HandleInformation ) { UNREFERENCED_PARAMETER(Handle); UNREFERENCED_PARAMETER(DesiredAccess); UNREFERENCED_PARAMETER(ObjectType); UNREFERENCED_PARAMETER(AccessMode); UNREFERENCED_PARAMETER(Object); UNREFERENCED_PARAMETER(HandleInformation); ASSERTMSG("Not implemented for UMDF\n", FALSE); return STATUS_NOT_IMPLEMENTED; } __inline NTSTATUS Mx::MxClose( __in HANDLE Handle ) { CloseHandle(Handle); return STATUS_SUCCESS; } __inline KIRQL Mx::MxAcquireInterruptSpinLock( _Inout_ PKINTERRUPT Interrupt ) { UNREFERENCED_PARAMETER(Interrupt); ASSERTMSG("Not implemented for UMDF\n", FALSE); return PASSIVE_LEVEL; } __inline VOID Mx::MxReleaseInterruptSpinLock( _Inout_ PKINTERRUPT Interrupt, _In_ KIRQL OldIrql ) { UNREFERENCED_PARAMETER(Interrupt); UNREFERENCED_PARAMETER(OldIrql); ASSERTMSG("Not implemented for UMDF\n", FALSE); } __inline BOOLEAN Mx::MxInsertQueueDpc( __inout PRKDPC Dpc, __in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2 ) { UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); ASSERTMSG("Not implemented for UMDF\n", FALSE); return FALSE; }