windows-nt/Source/XPSP1/NT/drivers/wdm/input/hidclass/local.h
2020-09-26 16:20:57 +08:00

1027 lines
40 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
local.h
Abstract
Definitions that are private to the hid class driver code appear here.
Author:
Ervin P.
Environment:
Kernel mode only
Revision History:
--*/
typedef struct _HID_DESCRIPTOR *PHID_DESCRIPTOR;
typedef struct _HIDCLASS_COLLECTION *PHIDCLASS_COLLECTION;
typedef struct _HIDCLASS_DEVICE_EXTENSION *PHIDCLASS_DEVICE_EXTENSION;
typedef struct _HIDCLASS_DRIVER_EXTENSION *PHIDCLASS_DRIVER_EXTENSION;
typedef struct _HIDCLASS_FILE_EXTENSION *PHIDCLASS_FILE_EXTENSION;
typedef struct _HIDCLASS_PINGPONG *PHIDCLASS_PINGPONG;
typedef struct _HIDCLASS_REPORT *PHIDCLASS_REPORT;
typedef struct _FDO_EXTENSION *PFDO_EXTENSION;
typedef struct _PDO_EXTENSION *PPDO_EXTENSION;
#if DBG
#define LockFileExtension( f, i ) \
{ \
KeAcquireSpinLock( &(f)->ListSpinLock, (i) ); \
(f)->ListSpinLockTaken = TRUE; \
}
#define UnlockFileExtension(f, i) \
{ \
(f)->ListSpinLockTaken = FALSE; \
KeReleaseSpinLock( &(f)->ListSpinLock, (i) ); \
}
VOID DbgLogIntStart();
VOID DbgLogIntEnd();
#define DBGLOG_INTSTART() DbgLogIntStart();
#define DBGLOG_INTEND() DbgLogIntEnd();
VOID DbgTestGetDeviceString(PFDO_EXTENSION fdoExt);
VOID DbgTestGetIndexedString(PFDO_EXTENSION fdoExt);
#else
#define LockFileExtension(f, i) KeAcquireSpinLock(&(f)->ListSpinLock, (i));
#define UnlockFileExtension(f, i) KeReleaseSpinLock(&(f)->ListSpinLock, (i));
#define DBGLOG_INTSTART()
#define DBGLOG_INTEND()
#endif
#define HIDCLASS_POOL_TAG 'CdiH'
#define ALLOCATEPOOL(poolType, size) ExAllocatePoolWithTag((poolType), (size), HIDCLASS_POOL_TAG)
//
// On some busses, we can power down the bus, but not the system, in this case
// we still need to allow the device to wake said bus, therefore
// waitwake-supported should not rely on systemstate.
//
#define WAITWAKE_SUPPORTED(fdoExt) ((fdoExt)->deviceCapabilities.DeviceWake > PowerDeviceD0 && \
(fdoExt)->deviceCapabilities.SystemWake > PowerSystemWorking)
// #define WAITWAKE_ON(port) ((port)->WaitWakeIrp != 0)
#define REMOTEWAKE_ON(port) \
(InterlockedCompareExchangePointer(&(port)->remoteWakeIrp, NULL, NULL) != NULL)
BOOLEAN
HidpCheckRemoteWakeEnabled(
IN PPDO_EXTENSION PdoExt
);
#define SHOULD_SEND_WAITWAKE(pdoExt) (!(pdoExt)->MouseOrKeyboard && \
WAITWAKE_SUPPORTED(&(pdoExt)->deviceFdoExt->fdoExt) && \
!REMOTEWAKE_ON(pdoExt) && \
HidpCheckRemoteWakeEnabled(pdoExt))
/*
* String constants for use in compatible-id multi-string.
*/
// 0123456789 123456789 1234
#define HIDCLASS_COMPATIBLE_ID_STANDARD_NAME L"HID_DEVICE\0"
#define HIDCLASS_COMPATIBLE_ID_GENERIC_NAME L"HID_DEVICE_UP:%04x_U:%04x\0"
#define HIDCLASS_COMPATIBLE_ID_PAGE_OFFSET 14
#define HIDCLASS_COMPATIBLE_ID_USAGE_OFFSET 21
#define HIDCLASS_COMPATIBLE_ID_STANDARD_LENGTH 11
#define HIDCLASS_COMPATIBLE_ID_GENERIC_LENGTH 26
// 0123456789 123456789 123456
#define HIDCLASS_SYSTEM_KEYBOARD L"HID_DEVICE_SYSTEM_KEYBOARD\0"
#define HIDCLASS_SYSTEM_MOUSE L"HID_DEVICE_SYSTEM_MOUSE\0"
#define HIDCLASS_SYSTEM_GAMING_DEVICE L"HID_DEVICE_SYSTEM_GAME\0"
#define HIDCLASS_SYSTEM_CONTROL L"HID_DEVICE_SYSTEM_CONTROL\0"
#define HIDCLASS_SYSTEM_CONSUMER_DEVICE L"HID_DEVICE_SYSTEM_CONSUMER\0"
//
// String constant used to find out if selective suspend
// is supported on this device.
//
#define HIDCLASS_SELECTIVE_SUSPEND_ENABLED L"SelectiveSuspendEnabled\0"
#define HIDCLASS_SELECTIVE_SUSPEND_ON L"SelectiveSuspendOn\0"
#define HIDCLASS_REMOTE_WAKE_ENABLE L"RemoteWakeEnabled"
#define NO_STATUS 0x80000000 // this will never be a STATUS_xxx constant in NTSTATUS.H
#define HID_DEFAULT_IDLE_TIME 5 // in seconds
//
// Valid values for HIDCLASS_DEVICE_EXTENSION.state
//
enum deviceState {
DEVICE_STATE_INITIALIZED = 1,
DEVICE_STATE_STARTING,
DEVICE_STATE_START_SUCCESS,
DEVICE_STATE_START_FAILURE,
DEVICE_STATE_STOPPING,
DEVICE_STATE_STOPPED,
DEVICE_STATE_REMOVING,
DEVICE_STATE_REMOVED
};
enum collectionState {
COLLECTION_STATE_UNINITIALIZED = 1,
COLLECTION_STATE_INITIALIZED,
COLLECTION_STATE_RUNNING,
COLLECTION_STATE_STOPPING,
COLLECTION_STATE_STOPPED,
COLLECTION_STATE_REMOVING
};
//
// _HIDCLASS_DRIVER_EXTENSION contains per-minidriver extension information
// for the class driver. It is created upon a HidRegisterMinidriver() call.
//
typedef struct _HIDCLASS_DRIVER_EXTENSION {
//
// Pointer to the minidriver's driver object.
//
PDRIVER_OBJECT MinidriverObject;
//
// RegistryPath is a copy of the minidriver's RegistryPath that it
// received as a DriverEntry() parameter.
//
UNICODE_STRING RegistryPath;
//
// DeviceExtensionSize is the size of the minidriver's per-device
// extension.
//
ULONG DeviceExtensionSize;
//
// Dispatch routines for the minidriver. These are the only dispatch
// routines that the minidriver should ever care about, no others will
// be forwarded.
//
PDRIVER_DISPATCH MajorFunction[ IRP_MJ_MAXIMUM_FUNCTION + 1 ];
/*
* These are the minidriver's original entrypoints,
* to which we chain.
*/
PDRIVER_ADD_DEVICE AddDevice;
PDRIVER_UNLOAD DriverUnload;
//
// Number of pointers to this structure that we've handed out
//
LONG ReferenceCount;
//
// Linkage onto our global list of driver extensions
//
LIST_ENTRY ListEntry;
/*
* Either all or none of the devices driven by a given minidriver are polled.
*/
BOOLEAN DevicesArePolled;
#if DBG
ULONG Signature;
#endif
} HIDCLASS_DRIVER_EXTENSION;
#if DBG
#define HID_DRIVER_EXTENSION_SIG 'EdiH'
#endif
#define MIN_POLL_INTERVAL_MSEC 1
#define MAX_POLL_INTERVAL_MSEC 10000
#define DEFAULT_POLL_INTERVAL_MSEC 5
/*
* Device-specific flags
*/
// Nanao depends on a Win98G bug that allows GetFeature on input collection
#define DEVICE_FLAG_ALLOW_FEATURE_ON_NON_FEATURE_COLLECTION (1 << 0)
//
// HIDCLASS_COLLECTION is where we keep our per-collection information.
//
typedef struct _HIDCLASS_COLLECTION {
ULONG CollectionNumber;
ULONG CollectionIndex;
//
// NumOpens is a count of open handles against this collection.
//
ULONG NumOpens;
// Number of pending reads for all clients on this collection.
ULONG numPendingReads;
//
// FileExtensionList is the head of a list of file extensions, i.e.
// open instances against this collection.
//
LIST_ENTRY FileExtensionList;
KSPIN_LOCK FileExtensionListSpinLock;
/*
* For polled devices, we only read from the device
* once every poll interval. We queue read IRPs
* here until the poll timer expiration.
*
* Note: for a polled device, we keep a separate background
* loop for each collection. This way, queued-up read IRPs
* remain associated with the right collection.
* Also, this will keep the number of reads we do on each
* timer period roughly equal to the number of collections.
*/
ULONG PollInterval_msec;
KTIMER polledDeviceTimer;
KDPC polledDeviceTimerDPC;
LIST_ENTRY polledDeviceReadQueue;
KSPIN_LOCK polledDeviceReadQueueSpinLock;
/*
* We save old reports on polled devices for
* "opportunistic" readers who want to get a result right away.
* The polledDataIsStale flag indicates that the saved report
* is at least one poll interval old (so we should not use it).
*/
PUCHAR savedPolledReportBuf;
ULONG savedPolledReportLen;
BOOLEAN polledDataIsStale;
UNICODE_STRING SymbolicLinkName;
UNICODE_STRING SymbolicLinkName_SystemControl;
/*
* HID collection information descriptor for this collection.
*/
HID_COLLECTION_INFORMATION hidCollectionInfo;
PHIDP_PREPARSED_DATA phidDescriptor;
/*
* This buffer is used to "cook" a raw report when it's been received.
* This is only used for non-polled (interrupt) devices.
*/
PUCHAR cookedInterruptReportBuf;
/*
* This is an IRP that we queue and complete
* when a read report contains a power event.
*
* The powerEventIrp field retains an IRP
* so it needs a spinlock to synchronize cancellation.
*/
PIRP powerEventIrp;
KSPIN_LOCK powerEventSpinLock;
ULONG secureReadMode;
KSPIN_LOCK secureReadLock;
#if DBG
ULONG Signature;
#endif
} HIDCLASS_COLLECTION;
#if DBG
#define HIDCLASS_COLLECTION_SIG 'EccH'
#endif
//
// For HID devices that have at least one interrupt-style collection, we
// try to keep a set of "ping-pong" report-read IRPs pending in the minidriver
// in the event we get a report.
//
// HIDCLASS_PINGPONG contains a pointer to an IRP as well as an event
// and status block. Each device has a pointer to an array of these structures,
// the array size depending on the number of such IRPs we want to keep in
// motion.
//
// Right now the default number is 2.
//
#define MIN_PINGPONG_IRPS 2
//
// Flags to indicate whether read completed synchronously or asynchronously
//
#define PINGPONG_START_READ 0x01
#define PINGPONG_END_READ 0x02
#define PINGPONG_IMMEDIATE_READ 0x03
typedef struct _HIDCLASS_PINGPONG {
#define PINGPONG_SIG (ULONG)'gnoP'
ULONG sig;
//
// Read interlock value to protect us from running out of stack space
//
ULONG ReadInterlock;
PIRP irp;
PUCHAR reportBuffer;
LONG weAreCancelling;
KEVENT sentEvent; // When a read has been sent.
KEVENT pumpDoneEvent; // When the read loop is finally exitting.
PFDO_EXTENSION myFdoExt;
/*
* Timeout context for back-off algorithm applied to broken devices.
*/
KTIMER backoffTimer;
KDPC backoffTimerDPC;
LARGE_INTEGER backoffTimerPeriod; // in negative 100-nsec units
} HIDCLASS_PINGPONG;
#if DBG
#define HIDCLASS_REPORT_BUFFER_GUARD 'draG'
#endif
//
// All possible idle states.
//
#define IdleUninitialized 0x0
#define IdleDisabled 0x1
#define IdleWaiting 0x2
#define IdleIrpSent 0x3
#define IdleCallbackReceived 0x4
#define IdleComplete 0x5
/*
* Stores information about a Functional Device Object (FDO) which HIDCLASS attaches
* to the top of the Physical Device Object (PDO) that it get from the minidriver below.
*/
typedef struct _FDO_EXTENSION {
//
// Back pointer to the functional device object
//
PDEVICE_OBJECT fdo;
//
// HidDriverExtension is a pointer to our driver extension for the
// minidriver that gave us the PDO.
//
PHIDCLASS_DRIVER_EXTENSION driverExt;
//
// Hid descriptor that we get from the device.
//
HID_DESCRIPTOR hidDescriptor; // 9 bytes
//
// The attributes of this hid device.
//
HID_DEVICE_ATTRIBUTES hidDeviceAttributes; // 0x20 bytes
//
// Pointer to and length of the raw report descriptor.
//
PUCHAR rawReportDescription;
ULONG rawReportDescriptionLength;
//
// This device has one or more collections. We store the count and
// pointer to an array of our HIDCLASS_COLLECTION structures (one per
// collection) here.
//
PHIDCLASS_COLLECTION classCollectionArray;
/*
* This is initialized for us by HIDPARSE's HidP_GetCollectionDescription().
* It includes an array of HIDP_COLLECTION_DESC structs corresponding
* the classCollectionArray declared above.
*/
HIDP_DEVICE_DESC deviceDesc; // 0x30 bytes
BOOLEAN devDescInitialized;
//
// The maximum input size amongst ALL report types.
//
ULONG maxReportSize;
//
// For devices that have at least one interrupt collection, we keep
// a couple of ping-pong IRPs and associated structures.
// The ping-pong IRPs ferry data up from the USB hub.
//
ULONG numPingPongs;
PHIDCLASS_PINGPONG pingPongs;
//
// OpenCount represents the number of file objects aimed at this device
//
ULONG openCount;
/*
* This is the number of IRPs still outstanding in the minidriver.
*/
ULONG outstandingRequests;
enum deviceState prevState;
enum deviceState state;
UNICODE_STRING name;
/*
* deviceRelations contains an array of client PDO pointers.
*
* As the HID bus driver, HIDCLASS produces this data structure to report
* collection-PDOs to the system.
*/
PDEVICE_RELATIONS deviceRelations;
/*
* This is an array of device extensions for the collection-PDOs of this
* device-FDO.
*/
PHIDCLASS_DEVICE_EXTENSION *collectionPdoExtensions;
/*
* This includes a
* table mapping system power states to device power states.
*/
DEVICE_CAPABILITIES deviceCapabilities;
/*
* Track both current system and device power state
*/
SYSTEM_POWER_STATE systemPowerState;
DEVICE_POWER_STATE devicePowerState;
/*
* Wait Wake Irp sent to parent PDO
*/
PIRP waitWakeIrp;
KSPIN_LOCK waitWakeSpinLock;
BOOLEAN isWaitWakePending;
/*
* Queue of delayed requests due to the stack being in low power
*/
KSPIN_LOCK collectionPowerDelayedIrpQueueSpinLock;
LIST_ENTRY collectionPowerDelayedIrpQueue;
ULONG numPendingPowerDelayedIrps;
BOOLEAN isOutputOnlyDevice;
//
// Selective suspend idling context.
//
HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO idleCallbackInfo;
LONG idleState;
PULONG idleTimeoutValue;
KSPIN_LOCK idleNotificationSpinLock;
PIRP idleNotificationRequest;
BOOLEAN idleCancelling;
BOOLEAN idleEnabledInRegistry;
BOOLEAN idleEnabled;
KSPIN_LOCK idleSpinLock;
KEVENT idleDoneEvent; // When the idle notification irp has been cancelled successfully.
LONG numIdlePdos;
/*
* This is a list of WaitWake IRPs sent to the collection-PDOs
* on this device, which we just save and complete when the
* base device's WaitWake IRP completes.
*/
LIST_ENTRY collectionWaitWakeIrpQueue;
KSPIN_LOCK collectionWaitWakeIrpQueueSpinLock;
struct _FDO_EXTENSION *nextFdoExt;
/*
* Device-specific flags (DEVICE_FLAG_xxx).
*/
ULONG deviceSpecificFlags;
/*
* This is our storage space for the systemState IRP that we need to hold
* on to and complete in DevicePowerRequestCompletion.
*/
PIRP currentSystemStateIrp;
/*
* Unique number assigned to identify this HID bus.
*/
ULONG BusNumber;
//
// WMI Information
//
WMILIB_CONTEXT WmiLibInfo;
#if DBG
WCHAR dbgDriverKeyName[64];
#endif
} FDO_EXTENSION;
/*
* Stores information about a Physical Device Object (PDO) which HIDCLASS creates
* for each HID device-collection.
*/
typedef struct _PDO_EXTENSION {
enum collectionState prevState;
enum collectionState state;
ULONG collectionNum;
ULONG collectionIndex;
//
// A remove lock to keep track of outstanding I/Os to prevent the device
// object from leaving before such time as all I/O has been completed.
//
IO_REMOVE_LOCK removeLock;
// represents a collection on the HID "bus"
PDEVICE_OBJECT pdo;
PUNICODE_STRING name;
/*
* This is a back-pointer to the original FDO's extension.
*/
PHIDCLASS_DEVICE_EXTENSION deviceFdoExt;
/*
* Track both current system and device power state
*/
SYSTEM_POWER_STATE systemPowerState;
DEVICE_POWER_STATE devicePowerState;
BOOLEAN remoteWakeEnabled;
KSPIN_LOCK remoteWakeSpinLock;
PIRP remoteWakeIrp;
PIRP waitWakeIrp;
/*
* The status change function that was registered thru query interface
* NOTE: Can currently only register one.
*/
PHID_STATUS_CHANGE StatusChangeFn;
PVOID StatusChangeContext;
/*
* Access protection information.
* We count the number of opens for read and write on the collection.
* We also count the number of opens which RESTRICT future
* read/write opens on the collection.
*
* Note that desired access is independent of restriction.
* A client may, for example, do an open-for-read-only but
* (by not setting the FILE_SHARE_WRITE bit)
* restrict other clients from doing an open-for-write.
*/
ULONG openCount;
ULONG opensForRead;
ULONG opensForWrite;
ULONG restrictionsForRead;
ULONG restrictionsForWrite;
ULONG restrictionsForAnyOpen;
BOOLEAN MouseOrKeyboard;
//
// WMI Information
//
WMILIB_CONTEXT WmiLibInfo;
} PDO_EXTENSION;
/*
* This contains info about either a device FDO or a device-collection PDO.
* Some of the same functions process both, so we need one structure.
*/
typedef struct _HIDCLASS_DEVICE_EXTENSION {
/*
* This is the public part of a HID FDO device extension, and
* must be the first entry in this structure.
*/
HID_DEVICE_EXTENSION hidExt; // size== 0x0C.
/*
* Determines whether this is a device extension for a device-FDO or a
* device-collection-PDO; this resolves the following union.
*/
BOOLEAN isClientPdo;
/*
* Include this signature for both debug and retail --
* kenray's debug extensions look for this.
*/
#define HID_DEVICE_EXTENSION_SIG 'EddH'
ULONG Signature;
union {
FDO_EXTENSION fdoExt;
PDO_EXTENSION pdoExt;
};
} HIDCLASS_DEVICE_EXTENSION;
//
// HIDCLASS_FILE_EXTENSION is private data we keep per file object.
//
typedef struct _HIDCLASS_FILE_EXTENSION {
//
// CollectionNumber is the ordinal of the collection in the device
//
ULONG CollectionNumber;
PFDO_EXTENSION fdoExt;
//
// PendingIrpList is a list of READ IRPs currently waiting to be satisfied.
//
LIST_ENTRY PendingIrpList;
//
// ReportList is a list of reports waiting to be read on this handle.
//
LIST_ENTRY ReportList;
//
// FileList provides a way to link all of a collection's
// file extensions together.
//
LIST_ENTRY FileList;
//
// Both PendingIrpList and ReportList are protected by the same spinlock,
// ListSpinLock.
//
KSPIN_LOCK ListSpinLock;
//
// MaximumInputReportAge is only applicable for polled collections.
// It represents the maximum acceptable input report age for this handle.
// There is a value in the HIDCLASS_COLLECTION,
// CurrentMaximumInputReportAge, that represents the current minimum value
// of all of the file extensions open against the collection.
//
LARGE_INTEGER MaximumInputReportAge;
//
// CurrentInputReportQueueSize is the current size of the report input
// queue.
//
ULONG CurrentInputReportQueueSize;
/*
* This is the maximum number of reports that will be queued for the file extension.
* This starts at a default value and can be adjusted (within a fixed range) by an IOCTL.
*/
ULONG MaximumInputReportQueueSize;
#define MIN_INPUT_REPORT_QUEUE_SIZE MIN_PINGPONG_IRPS
#define MAX_INPUT_REPORT_QUEUE_SIZE (MIN_INPUT_REPORT_QUEUE_SIZE*256)
#define DEFAULT_INPUT_REPORT_QUEUE_SIZE (MIN_INPUT_REPORT_QUEUE_SIZE*16)
//
// Back pointer to the file object that this extension is for
//
PFILE_OBJECT FileObject;
/*
* File-attributes passed in irpSp->Parameters.Create.FileAttributes
* when this open was made.
*/
USHORT FileAttributes;
ACCESS_MASK accessMask;
USHORT shareMask;
//
// Closing is set when this file object is closing and will be removed
// shortly. Don't queue any more reports or IRPs to this object
// when this flag is set.
//
BOOLEAN Closing;
//
// Security has been checked.
//
BOOLEAN SecurityCheck;
//
// DWORD allignment
//
BOOLEAN Reserved [2];
/*
* This flag indicates that this client does irregular, opportunistic
* reads on the device, which is a polled device.
* Instead of waiting for the background timer-driven read loop,
* this client should have his reads completed immediately.
*/
BOOLEAN isOpportunisticPolledDeviceReader;
ULONG nowCompletingIrpForOpportunisticReader;
/*
* haveReadPrivilege TRUE indicates that the client has full
* permissions on the device, including read.
*/
BOOLEAN haveReadPrivilege;
//
// Memphis Blue Screen info
//
BLUESCREEN BlueScreenData;
BOOLEAN isSecureOpen;
ULONG SecureReadMode;
/*
* If a read fails, some clients reissue the read on the same thread.
* If this happens repeatedly, we can run out of stack space.
* So we keep track of the depth
*/
#define INSIDE_READCOMPLETE_MAX 4
ULONG insideReadCompleteCount;
#if DBG
BOOLEAN ListSpinLockTaken;
ULONG dbgNumReportsDroppedSinceLastRead;
ULONG Signature;
#endif
} HIDCLASS_FILE_EXTENSION;
#if DBG
#define HIDCLASS_FILE_EXTENSION_SIG 'efcH'
#endif
typedef struct {
#define ASYNC_COMPLETE_CONTEXT_SIG 'cnsA'
ULONG sig;
WORK_QUEUE_ITEM workItem;
PIRP irp;
PDEVICE_OBJECT devObj;
} ASYNC_COMPLETE_CONTEXT;
//
// HIDCLASS_REPORT is the structure we use to track a report returned from
// the minidriver.
//
typedef struct _HIDCLASS_REPORT {
//
// ListEntry queues this report onto a file extension.
//
LIST_ENTRY ListEntry;
ULONG reportLength;
//
// UnparsedReport is a data area for the unparsed report data as returned
// from the minidriver. The lengths of all input reports for a given
// class are the same, so we don't need to store the length in each
// report.
//
UCHAR UnparsedReport[];
} HIDCLASS_REPORT;
typedef struct _HIDCLASS_WORK_ITEM_DATA {
PIRP Irp;
PDO_EXTENSION *PdoExt;
PIO_WORKITEM Item;
BOOLEAN RemoteWakeState;
} HIDCLASS_WORK_ITEM_DATA, *PHIDCLASS_WORK_ITEM_DATA;
//
// Internal shared function prototypes
//
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS HidpAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
VOID HidpDriverUnload(IN struct _DRIVER_OBJECT *minidriverObject);
NTSTATUS HidpCallDriver(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
NTSTATUS HidpCallDriverSynchronous(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
NTSTATUS HidpCopyInputReportToUser(IN PHIDCLASS_FILE_EXTENSION fdoExtension, IN PUCHAR ReportData, IN OUT PULONG UserBufferLen, OUT PUCHAR UserBuffer);
NTSTATUS HidpCreateSymbolicLink(IN PDO_EXTENSION *pdoExtension, IN ULONG collectionNum, IN BOOLEAN Create, IN PDEVICE_OBJECT Pdo);
NTSTATUS HidpCreateClientPDOs(PHIDCLASS_DEVICE_EXTENSION hidClassExtension);
ULONG HidpSetMaxReportSize(IN FDO_EXTENSION *fdoExtension);
VOID EnqueueInterruptReport(PHIDCLASS_FILE_EXTENSION fileExtension, PHIDCLASS_REPORT report);
PHIDCLASS_REPORT DequeueInterruptReport(PHIDCLASS_FILE_EXTENSION fileExtension, LONG maxLen);
VOID HidpDestroyFileExtension(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION FileExtension);
VOID HidpFlushReportQueue(IN PHIDCLASS_FILE_EXTENSION FileExtension);
NTSTATUS HidpGetCollectionDescriptor(IN FDO_EXTENSION *fdoExtension, IN ULONG collectionId, IN PVOID Buffer, IN OUT PULONG BufferSize);
NTSTATUS HidpGetCollectionInformation(IN FDO_EXTENSION *fdoExtension, IN ULONG collectionNumber, IN PVOID Buffer, IN OUT PULONG BufferSize);
NTSTATUS HidpGetDeviceDescriptor(FDO_EXTENSION *fdoExtension);
BOOLEAN HidpStartIdleTimeout(FDO_EXTENSION *fdoExt, BOOLEAN DeviceStart);
VOID HidpCancelIdleNotification(FDO_EXTENSION *fdoExt, BOOLEAN removing);
VOID HidpIdleTimeWorker(PDEVICE_OBJECT DeviceObject, PIO_WORKITEM Item);
VOID HidpIdleNotificationCallback(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension);
NTSTATUS HidpRegisterDeviceForIdleDetection(PDEVICE_OBJECT DeviceObject, ULONG IdleTime, PULONG *);
VOID HidpSetDeviceBusy(FDO_EXTENSION *fdoExt);
NTSTATUS HidpCheckIdleState(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension,PIRP Irp);
NTSTATUS HidpGetRawDeviceDescriptor(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, OUT PULONG RawDeviceDescriptorLength, OUT PUCHAR *RawDeviceDescriptor);
NTSTATUS HidpInitializePingPongIrps(FDO_EXTENSION *fdoExtension);
NTSTATUS HidpReallocPingPongIrps(FDO_EXTENSION *fdoExtension, ULONG newNumBufs);
NTSTATUS HidpIrpMajorPnpComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS HidpMajorHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS HidpParseAndBuildLinks(FDO_EXTENSION *fdoExtension);
NTSTATUS HidpFdoPowerCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
BOOLEAN EnqueueDriverExt(PHIDCLASS_DRIVER_EXTENSION driverExt);
PHIDCLASS_DRIVER_EXTENSION RefDriverExt(IN PDRIVER_OBJECT MinidriverObject);
PHIDCLASS_DRIVER_EXTENSION DerefDriverExt(IN PDRIVER_OBJECT MinidriverObject);
NTSTATUS HidpStartAllPingPongs(FDO_EXTENSION *fdoExtension);
ULONG HidiGetClassCollectionOrdinal(IN PHIDCLASS_COLLECTION ClassCollection);
PHIDP_COLLECTION_DESC HidiGetHidCollectionByClassCollection(IN PHIDCLASS_COLLECTION ClassCollection);
PHIDP_REPORT_IDS GetReportIdentifier(FDO_EXTENSION *fdoExtension, ULONG reportId);
PHIDP_COLLECTION_DESC GetCollectionDesc(FDO_EXTENSION *fdoExtension, ULONG collectionId);
PHIDCLASS_COLLECTION GetHidclassCollection(FDO_EXTENSION *fdoExtension, ULONG collectionId);
//NTSTATUS HidpGetSetFeature(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp, IN ULONG controlCode, OUT BOOLEAN *sentIrp);
NTSTATUS HidpGetSetReport(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp, IN ULONG controlCode, OUT BOOLEAN *sentIrp);
NTSTATUS HidpGetDeviceString(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp, IN ULONG stringId, IN ULONG languageId);
NTSTATUS HidpGetPhysicalDescriptor(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorRead(IN PHIDCLASS_DEVICE_EXTENSION, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorCreate(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorWrite(IN PHIDCLASS_DEVICE_EXTENSION, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpPdoPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpFdoPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorPower(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorClose(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorDeviceControl(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorINTERNALDeviceControl(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorClose(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpIrpMajorDefault(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpInterruptReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS HidpQueryDeviceRelations(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
NTSTATUS HidpQueryCollectionCapabilities(PDO_EXTENSION *pdoExt, IN OUT PIRP Irp);
NTSTATUS HidpQueryIdForClientPdo(IN PHIDCLASS_DEVICE_EXTENSION hidClassExtension, IN OUT PIRP Irp);
NTSTATUS HidpQueryInterface(IN PHIDCLASS_DEVICE_EXTENSION hidClassExtension, IN OUT PIRP Irp);
PVOID MemDup(POOL_TYPE PoolType, PVOID dataPtr, ULONG length);
BOOLEAN AllClientPDOsInitialized(FDO_EXTENSION *fdoExtension, BOOLEAN initialized);
BOOLEAN AnyClientPDOsInitialized(FDO_EXTENSION *fdoExtension, BOOLEAN initialized);
NTSTATUS ClientPdoCompletion(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
BOOLEAN HidpDeleteDeviceObjects(FDO_EXTENSION *fdoExt);
VOID HidpCancelReadIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID CancelAllPingPongIrps(FDO_EXTENSION *fdoExt);
VOID HidpCleanUpFdo(FDO_EXTENSION *fdoExt);
NTSTATUS HidpRemoveDevice(FDO_EXTENSION *fdoExt, IN PIRP Irp);
VOID HidpRemoveCollection(FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt, IN PIRP Irp);
VOID HidpDestroyCollection(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION Collection);
VOID CollectionPowerRequestCompletion(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
VOID DevicePowerRequestCompletion(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
NTSTATUS HidpQueryCapsCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS HidpQueryDeviceCapabilities(IN PDEVICE_OBJECT PdoDeviceObject, IN PDEVICE_CAPABILITIES DeviceCapabilities);
VOID DestroyPingPongs(FDO_EXTENSION *fdoExt);
VOID CheckReportPowerEvent(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION collection, PUCHAR report, ULONG reportLen);
BOOLEAN StartPollingLoop(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION hidCollection, BOOLEAN freshQueue);
VOID StopPollingLoop(PHIDCLASS_COLLECTION hidCollection, BOOLEAN flushQueue);
BOOLEAN ReadPolledDevice(PDO_EXTENSION *pdoExt, BOOLEAN isTimerDrivenRead);
VOID PolledReadCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID EnqueueFdoExt(FDO_EXTENSION *fdoExt);
VOID DequeueFdoExt(FDO_EXTENSION *fdoExt);
NTSTATUS AllocDeviceResources(FDO_EXTENSION *fdoExt);
VOID FreeDeviceResources(FDO_EXTENSION *fdoExt);
NTSTATUS AllocCollectionResources(FDO_EXTENSION *fdoExt, ULONG collectionNum);
VOID FreeCollectionResources(FDO_EXTENSION *fdoExt, ULONG collectionNum);
NTSTATUS InitializeCollection(FDO_EXTENSION *fdoExt, ULONG collectionIndex);
NTSTATUS HidpStartCollectionPDO(FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt, PIRP Irp);
NTSTATUS HidpStartDevice(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
PWCHAR SubstituteBusNames(PWCHAR oldIDs, FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt);
PWSTR BuildCompatibleID(PHIDCLASS_DEVICE_EXTENSION hidClassExtension);
PUNICODE_STRING MakeClientPDOName(PUNICODE_STRING fdoName, ULONG collectionId);
VOID HidpPingpongBackoffTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
BOOLEAN WStrCompareN(PWCHAR str1, PWCHAR str2, ULONG maxChars);
NTSTATUS SubmitWaitWakeIrp(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension);
BOOLEAN HidpIsWaitWakePending(FDO_EXTENSION *fdoExt, BOOLEAN setIfNotPending);
NTSTATUS HidpWaitWakeComplete(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
NTSTATUS HidpGetIndexedString(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp, IN ULONG stringIndex, IN ULONG languageId);
VOID CompleteAllPendingReadsForCollection(PHIDCLASS_COLLECTION Collection);
VOID CompleteAllPendingReadsForFileExtension(PHIDCLASS_COLLECTION Collection, PHIDCLASS_FILE_EXTENSION fileExtension);
VOID CompleteAllPendingReadsForDevice(FDO_EXTENSION *fdoExt);
BOOLEAN MyPrivilegeCheck(PIRP Irp);
NTSTATUS QueuePowerEventIrp(PHIDCLASS_COLLECTION hidCollection, PIRP Irp);
VOID PowerEventCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS HidpPolledReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS HidpPolledReadComplete_TimerDriven(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
VOID CollectionWaitWakeIrpCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID CompleteAllCollectionWaitWakeIrps(FDO_EXTENSION *fdoExt, NTSTATUS status);
VOID PowerDelayedCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS EnqueuePowerDelayedIrp(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
PIRP DequeuePowerDelayedIrp(FDO_EXTENSION *fdoExt);
ULONG DequeueAllPdoPowerDelayedIrps(PDO_EXTENSION *pdoExt, PLIST_ENTRY dequeue);
VOID ReadDeviceFlagsFromRegistry(FDO_EXTENSION *fdoExt, PDEVICE_OBJECT pdo);
LONG WStrNCmpI(PWCHAR s1, PWCHAR s2, ULONG n);
ULONG LAtoX(PWCHAR wHexString);
ULONG WStrNCpy(PWCHAR dest, PWCHAR src, ULONG n);
NTSTATUS OpenSubkey(OUT PHANDLE Handle, IN HANDLE BaseHandle, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess);
void HidpNumberToString(PWCHAR String, USHORT Number, USHORT stringLen);
NTSTATUS GetHIDRawReportDescriptor(FDO_EXTENSION *fdoExt, PIRP irp, ULONG descriptorLen);
VOID WorkItemCallback_CompleteIrpAsynchronously(PVOID context);
NTSTATUS EnqueueInterruptReadIrp(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION fileExtension, PIRP Irp);
PIRP DequeueInterruptReadIrp(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION fileExtension);
NTSTATUS EnqueuePolledReadIrp(PHIDCLASS_COLLECTION collection, PIRP Irp);
PIRP DequeuePolledReadSystemIrp(PHIDCLASS_COLLECTION collection);
PIRP DequeuePolledReadIrp(PHIDCLASS_COLLECTION collection);
NTSTATUS HidpProcessInterruptReport(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION FileExtension, PUCHAR Report, ULONG ReportLength, PIRP *irpToComplete);
VOID HidpFreePowerEventIrp(PHIDCLASS_COLLECTION Collection);
NTSTATUS HidpGetMsGenreDescriptor(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp);
NTSTATUS DllUnload(VOID);
NTSTATUS DllInitialize (PUNICODE_STRING RegistryPath);
VOID HidpPowerUpPdos(IN PFDO_EXTENSION fdoExt);
NTSTATUS HidpDelayedPowerPoRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
NTSTATUS HidpIrpMajorSystemControl(PHIDCLASS_DEVICE_EXTENSION DeviceObject, PIRP Irp);
NTSTATUS HidpSetWmiDataItem(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG DataItemId, ULONG BufferSize, PUCHAR Buffer);
NTSTATUS HidpSetWmiDataBlock(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG BufferSize, PUCHAR Buffer);
NTSTATUS HidpQueryWmiDataBlock( PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG InstanceCount, OUT PULONG InstanceLengthArray, ULONG BufferAvail, PUCHAR Buffer);
NTSTATUS HidpQueryWmiRegInfo( PDEVICE_OBJECT DeviceObject, ULONG *RegFlags, PUNICODE_STRING InstanceName, PUNICODE_STRING *RegistryPath, PUNICODE_STRING MofResourceName, PDEVICE_OBJECT *Pdo);
BOOLEAN HidpCreateRemoteWakeIrp (PDO_EXTENSION *PdoExt);
void HidpCreateRemoteWakeIrpWorker (PDEVICE_OBJECT DeviceObject, PHIDCLASS_WORK_ITEM_DATA ItemData);
NTSTATUS HidpToggleRemoteWake(PDO_EXTENSION *PdoExt, BOOLEAN RemoteWakeState);
#if DBG
VOID InitFdoExtDebugInfo(PHIDCLASS_DEVICE_EXTENSION hidclassExt);
#endif
extern ULONG HidpNextHidNumber;
extern FDO_EXTENSION *allFdoExtensions;
extern KSPIN_LOCK allFdoExtensionsSpinLock;
PVOID
HidpGetSystemAddressForMdlSafe(PMDL MdlAddress);