/*++ 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);