NTSTATUS EXTERNAL HbtnAddDevice( __in PDRIVER_OBJECT DrvObj, __in PDEVICE_OBJECT DevObj ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION devext = NULL; PAGED_CODE (); TEnter(Func,("(DrvObj=%p,DevObj=%p)\n", DrvObj, DevObj)); UNREFERENCED_PARAMETER(DrvObj); devext = GET_MINIDRIVER_DEVICE_EXTENSION(DevObj); RtlZeroMemory(devext, sizeof(*devext)); devext->self = DevObj; devext->LowerDevObj = GET_NEXT_DEVICE_OBJECT(DevObj); IoInitializeRemoveLock(&devext->RemoveLock, HBTN_POOL_TAG, 0, 10); KeInitializeSpinLock(&devext->QueueLock); KeInitializeSpinLock(&devext->DataLock); InitializeListHead(&devext->PendingIrpList); IoCsqInitialize(&devext->IrpQueue, HbtnInsertIrp, HbtnRemoveIrp, HbtnPeekNextIrp, HbtnAcquireLock, HbtnReleaseLock, HbtnCompleteCancelledIrp); status = OemAddDevice(devext); if (NT_SUCCESS(status)) { DevObj->Flags &= ~DO_DEVICE_INITIALIZING; DevObj->Flags |= DO_POWER_PAGABLE; } TExit(Func,("=%x\n", status)); return status; } //HbtnAddDevice
NTSTATUS INTERNAL OemAddDevice( _In_ PDEVICE_EXTENSION devext ) { NTSTATUS status = STATUS_SUCCESS; CONNECT_DATA ConnectData = {0}; PAGED_CODE (); TEnter(Func,("(devext=%p)\n", devext)); ConnectData.ClassDeviceObject = devext->self; #pragma warning(disable:4152) //nonstandard extension, function/data pointer conversion ConnectData.ClassService = KbdPortCallback; #pragma warning(default:4152) status = SendSyncIoctl(devext, IOCTL_INTERNAL_KEYBOARD_CONNECT, &ConnectData, sizeof(ConnectData), NULL, 0); if (NT_SUCCESS(status)) { devext->dwfHBtn |= HBTNF_KBD_CONNECTED; } TExit(Func,("=%x\n", status)); return status; } //OemAddDevice
NTSTATUS INTERNAL ReadReport( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp, __out BOOLEAN *fSentDown ) { NTSTATUS status; PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); ULONG DataLen = irpsp->Parameters.DeviceIoControl.OutputBufferLength; TEnter(Func, ("(DevExt=%p,Irp=%p,IrpSp=%p)", DevExt, Irp, irpsp)); TAssert(Irp->UserBuffer != NULL); if (DataLen != sizeof(HID_INPUT_REPORT)) { status = STATUS_INVALID_BUFFER_SIZE; LogError(ERRLOG_INVALID_BUFFER_SIZE, status, UNIQUE_ERRID(0x60), NULL, NULL); TWarn(("Invalid input report size (len=%d,Expected=%d).", DataLen, sizeof(HID_INPUT_REPORT))); } else { status = OemReadReport(DevExt, Irp, fSentDown); } TExit(Func, ("=%x", status)); return status; } //ReadReport
NTSTATUS EXTERNAL DriverEntry( __in PDRIVER_OBJECT DrvObj, __in PUNICODE_STRING RegPath ) { NTSTATUS status = STATUS_SUCCESS; HID_MINIDRIVER_REGISTRATION hidMinidriverRegistration = {0}; TEnter(Func,("(DrvObj=%p,RegPath=%p)\n", DrvObj, RegPath)); gDriverObj = DrvObj; DrvObj->MajorFunction[IRP_MJ_CREATE] = DrvObj->MajorFunction[IRP_MJ_CLOSE] = HbtnCreateClose; DrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HbtnInternalIoctl; DrvObj->MajorFunction[IRP_MJ_PNP] = HbtnPnp; DrvObj->MajorFunction[IRP_MJ_POWER] = HbtnPower; DrvObj->DriverUnload = HbtnUnload; DrvObj->DriverExtension->AddDevice = HbtnAddDevice; // // Register with HIDCLASS.SYS module // RtlZeroMemory(&hidMinidriverRegistration, sizeof(hidMinidriverRegistration)); hidMinidriverRegistration.Revision = HID_REVISION; hidMinidriverRegistration.DriverObject = DrvObj; hidMinidriverRegistration.RegistryPath = RegPath; hidMinidriverRegistration.DeviceExtensionSize = sizeof(DEVICE_EXTENSION); hidMinidriverRegistration.DevicesArePolled = FALSE; status = HidRegisterMinidriver(&hidMinidriverRegistration); if (!NT_SUCCESS(status)) { LogError(ERRLOG_MINIDRV_REG_FAILED, status, UNIQUE_ERRID(0x10), NULL, NULL); TErr(("failed to register mini driver.\n")); } TExit(Func,("=%x\n", status)); return status; } //DriverEntry
VOID EXTERNAL HbtnUnload( __in PDRIVER_OBJECT DrvObj ) { PAGED_CODE(); TEnter(Func,("(DrvObj=%p)\n", DrvObj)); TAssert(DrvObj->DeviceObject == NULL); UNREFERENCED_PARAMETER(DrvObj); TExit(Func,("!\n")); return; } //HbtnUnload
NTSTATUS INTERNAL OemRemoveDevice( _In_ PDEVICE_EXTENSION devext, _In_ PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); TEnter(Func,("(devext=%p)\n", devext)); status = EnableKbdPort(devext, Irp, FALSE); TExit(Func,("=%x\n", status)); return status; } //OemRemoveDevice
NTSTATUS INTERNAL OemStartDevice( __in PDEVICE_EXTENSION devext, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); TEnter(Func,("(devext=%p,Irp=%p)\n", devext, Irp)); status = EnableKbdPort(devext, Irp, TRUE); TExit(Func,("=%x\n", status)); return status; } //OemStartDevice
NTSTATUS INTERNAL GetAttributes( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; UNREFERENCED_PARAMETER(DevExt); PAGED_CODE(); irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevExt=%p,Irp=%p,IrpSp=%p)\n", DevExt, Irp, irpsp)); if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DEVICE_ATTRIBUTES)) { status = STATUS_BUFFER_TOO_SMALL; LogError(ERRLOG_BUFFER_TOO_SMALL, status, UNIQUE_ERRID(0x90), NULL, NULL); TWarn(("output buffer too small (len=%d).\n", irpsp->Parameters.DeviceIoControl.OutputBufferLength)); } else { PHID_DEVICE_ATTRIBUTES DevAttrib; DevAttrib = (PHID_DEVICE_ATTRIBUTES)Irp->UserBuffer; DevAttrib->Size = sizeof(HID_DEVICE_ATTRIBUTES); DevAttrib->VendorID = OEM_VENDOR_ID; DevAttrib->ProductID = OEM_PRODUCT_ID; DevAttrib->VersionNumber = OEM_VERSION_NUM; Irp->IoStatus.Information = sizeof(HID_DEVICE_ATTRIBUTES); status = STATUS_SUCCESS; } TExit(Func,("=%x\n", status)); return status; } //GetAttributes
NTSTATUS INTERNAL GetReportDescriptor( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); #ifdef _DBG TEnter(Func, ("(DevExt=%p,Irp=%p,IrpSp=%p)", DevExt, Irp, irpsp)); #else UNREFERENCED_PARAMETER(DevExt); #endif PAGED_CODE (); if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < gdwcbReportDescriptor) { status = STATUS_BUFFER_TOO_SMALL; LogError(ERRLOG_BUFFER_TOO_SMALL, status, UNIQUE_ERRID(0x50), NULL, NULL); TWarn(("Output buffer too small (len=%d).", irpsp->Parameters.DeviceIoControl.OutputBufferLength)); } else { RtlCopyMemory(Irp->UserBuffer, gReportDescriptor, gdwcbReportDescriptor); Irp->IoStatus.Information = gdwcbReportDescriptor; status = STATUS_SUCCESS; } #ifdef _DBG TExit(Func, ("=%x", status)); #endif return status; } //GetReportDescriptor
NTSTATUS INTERNAL GetDeviceDescriptor( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; UNREFERENCED_PARAMETER(DevExt); PAGED_CODE (); irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevExt=%p,Irp=%p,IrpSp=%p)\n", DevExt, Irp, irpsp)); if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(gHidDescriptor)) { status = STATUS_BUFFER_TOO_SMALL; LogError(ERRLOG_BUFFER_TOO_SMALL, status, UNIQUE_ERRID(0x40), NULL, NULL); TWarn(("output buffer too small (len=%d).\n", irpsp->Parameters.DeviceIoControl.OutputBufferLength)); } else { RtlCopyMemory(Irp->UserBuffer, &gHidDescriptor, sizeof(gHidDescriptor)); Irp->IoStatus.Information = sizeof(gHidDescriptor); status = STATUS_SUCCESS; } TExit(Func,("=%x\n", status)); return status; } //GetDeviceDescriptor
NTSTATUS INTERNAL ReadReport( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevExt=%p,Irp=%p,IrpSp=%p)\n", DevExt, Irp, irpsp)); TAssert(Irp->UserBuffer != NULL); if (irpsp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(HID_INPUT_REPORT)) { status = STATUS_INVALID_BUFFER_SIZE; LogError(ERRLOG_INVALID_BUFFER_SIZE, status, UNIQUE_ERRID(0x60), NULL, NULL); TWarn(("invalid input report size (len=%d).\n", irpsp->Parameters.DeviceIoControl.OutputBufferLength)); } else { IoCsqInsertIrp(&DevExt->IrpQueue, Irp, NULL); status = STATUS_PENDING; } TExit(Func,("=%x\n", status)); return status; } //ReadReport
NTSTATUS EXTERNAL HbtnCreateClose( IN PDEVICE_OBJECT DevObject, IN PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; PAGED_CODE (); UNREFERENCED_PARAMETER(DevObject); irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevObject=%p,Irp=%p,IrpStack=%p,Major=%s)\n", DevObject, Irp, irpsp, LookupName(irpsp->MajorFunction, MajorIrpNames))); switch(irpsp->MajorFunction) { case IRP_MJ_CREATE: case IRP_MJ_CLOSE: Irp->IoStatus.Information = 0; break; default: status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); TExit(Func,("=%x\n", status)); return status; } //HbtnCreateClose
NTSTATUS EXTERNAL HbtnInternalIoctl( IN PDEVICE_OBJECT DevObj, IN PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION devext = GET_MINIDRIVER_DEVICE_EXTENSION(DevObj); PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevObj=%p,Irp=%p,IrpSp=%p,Ioctl=%s)\n", DevObj, Irp, irpsp, LookupName(irpsp->Parameters.DeviceIoControl.IoControlCode, HidIoctlNames))); Irp->IoStatus.Information = 0; status = IoAcquireRemoveLock(&devext->RemoveLock, Irp); if (!NT_SUCCESS(status)) { LogError(ERRLOG_DEVICE_REMOVED, status, UNIQUE_ERRID(0x10), NULL, NULL); TWarn(("received IRP after device was removed.\n")); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else if (!(devext->dwfHBtn & HBTNF_DEVICE_STARTED)) { IoReleaseRemoveLock(&devext->RemoveLock, Irp); status = STATUS_DEVICE_NOT_READY; LogError(ERRLOG_DEVICE_NOT_STARTED, status, UNIQUE_ERRID(0x20), NULL, NULL); TWarn(("digitizer is not started.\n")); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { switch(irpsp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: status = GetDeviceDescriptor(devext, Irp); break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: status = GetReportDescriptor(devext, Irp); break; case IOCTL_HID_READ_REPORT: status = ReadReport(devext, Irp); break; case IOCTL_HID_WRITE_REPORT: status = OemWriteReport(devext, Irp); break; case IOCTL_HID_GET_STRING: status = GetString(devext, Irp); break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: status = GetAttributes(devext, Irp); break; case IOCTL_HID_ACTIVATE_DEVICE: case IOCTL_HID_DEACTIVATE_DEVICE: status = STATUS_SUCCESS; break; default: status = STATUS_NOT_SUPPORTED; LogError(ERRLOG_NOT_SUPPORTED, status, UNIQUE_ERRID(0x30), NULL, NULL); TWarn(("unsupported (IOCTL=%x).\n", irpsp->Parameters.DeviceIoControl.IoControlCode)); break; } if (status != STATUS_PENDING) { IoReleaseRemoveLock(&devext->RemoveLock, Irp); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { IoMarkIrpPending(Irp); } } TExit(Func,("=%x\n", status)); return status; } //HbtnInternalIoctl
NTSTATUS INTERNAL GetString( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; PWSTR pwstrID = NULL; ULONG_PTR lenID = 0; ULONG_PTR ulpStringID = 0; UNREFERENCED_PARAMETER(DevExt); PAGED_CODE(); irpsp = IoGetCurrentIrpStackLocation(Irp); ulpStringID = (ULONG_PTR)(irpsp->Parameters.DeviceIoControl.Type3InputBuffer); TEnter(Func,("(DevExt=%p,Irp=%p,IrpSp=%p,StringID=%x)\n", DevExt, Irp, irpsp, (unsigned int)ulpStringID)); switch (0xFFFF & ulpStringID) { case HID_STRING_ID_IMANUFACTURER: pwstrID = gpwstrManufacturerID; break; case HID_STRING_ID_IPRODUCT: pwstrID = gpwstrProductID; break; case HID_STRING_ID_ISERIALNUMBER: pwstrID = gpwstrSerialNumber; break; default: pwstrID = NULL; break; } lenID = pwstrID? wcslen(pwstrID)*sizeof(WCHAR) + sizeof(UNICODE_NULL): 0; if (pwstrID == NULL) { status = STATUS_INVALID_PARAMETER; LogError(ERRLOG_INVALID_PARAMETER, status, UNIQUE_ERRID(0x70), NULL, NULL); TWarn(("invalid string ID (ID=%x).\n", (unsigned int)ulpStringID)); } else if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < lenID) { status = STATUS_BUFFER_TOO_SMALL; LogError(ERRLOG_BUFFER_TOO_SMALL, status, UNIQUE_ERRID(0x80), NULL, NULL); TWarn(("output buffer too small (len=%d,need=%d).\n", irpsp->Parameters.DeviceIoControl.OutputBufferLength, (LONG)lenID)); } else { RtlCopyMemory(Irp->UserBuffer, pwstrID, lenID); Irp->IoStatus.Information = lenID; status = STATUS_SUCCESS; } TExit(Func,("=%x (string=%S)\n", status, pwstrID? pwstrID: L"Null")); return status; } //GetString
VOID LogError( IN NTSTATUS ErrorCode, IN NTSTATUS NTStatus, IN ULONG UniqueID OPTIONAL, IN PCWSTR String1 OPTIONAL, IN PCWSTR String2 OPTIONAL ) { TEnter(Func, ("(ErrorCode=%x,NTStatus=%x,UniqueID=%x,Str1=%S,Str2=%S)", ErrorCode, NTStatus, UniqueID, String1? String1: L"", String2? String2: L"")); TAssert(gDriverObj != NULL); if (gDriverObj != NULL) { ULONG_PTR len1, len2, len; PIO_ERROR_LOG_PACKET ErrEntry; len1 = String1? (wcslen(String1) + 1)*sizeof(WCHAR): 0; len2 = String2? (wcslen(String2) + 1)*sizeof(WCHAR): 0; len = len1 + len2 + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData); len = max(len, sizeof(IO_ERROR_LOG_PACKET)); // Thoroughly check the value of len to prevent buffer underflows/overflows if ((len > 0) && (len <= 255) && (len1 <= len) && (len2 <= len)) { ErrEntry = IoAllocateErrorLogEntry(gDriverObj, (UCHAR)len); if (ErrEntry) { PUCHAR pbBuff = (PUCHAR)ErrEntry + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData); ErrEntry->NumberOfStrings = 0; if (len1 > 0) { ErrEntry->NumberOfStrings++; RtlCopyMemory(pbBuff, String1, len1); pbBuff += len1; } if (len2 > 0) { ErrEntry->NumberOfStrings++; RtlCopyMemory(pbBuff, String2, len2); pbBuff += len2; } ErrEntry->StringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData); ErrEntry->ErrorCode = ErrorCode; ErrEntry->FinalStatus = NTStatus; ErrEntry->UniqueErrorValue = UniqueID; IoWriteErrorLogEntry(ErrEntry); } else { TWarn(("Failed to allocate error log entry (len=%d).", (int)len)); } } else { TWarn(("Error log entry too big (len=%d).", (int)len)); } } TExit(Func, ("!")); return; } //LogError
VOID __cdecl LogDbgMsg( IN NTSTATUS ErrorCode, IN NTSTATUS NTStatus OPTIONAL, _In_z_ LPCSTR pszFormat, ... ) { #define MAX_ERRMSG_LEN ((ERROR_LOG_MAXIMUM_SIZE - \ FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)) \ /sizeof(WCHAR)) static char szErrMsg[MAX_ERRMSG_LEN] = {0}; TEnter(Func, ("(ErrorCode=%x,NTStatus=%x,Format=%s)", ErrorCode, NTStatus, pszFormat)); TAssert(gDriverObj != NULL); if (gDriverObj != NULL) { va_list arglist; NTSTATUS status; size_t iLen = 0; ULONG_PTR iTotalLen; PIO_ERROR_LOG_PACKET ErrEntry; va_start(arglist, pszFormat); status = RtlStringCchVPrintfA(szErrMsg, ARRAYSIZE(szErrMsg), pszFormat, arglist); va_end(arglist); if (NT_SUCCESS(status)) { status = RtlStringCchLengthA(szErrMsg, ARRAYSIZE(szErrMsg), &iLen); } if (NT_SUCCESS(status)) { iTotalLen = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + (iLen + 1)*sizeof(WCHAR); iTotalLen = max(iTotalLen, sizeof(IO_ERROR_LOG_PACKET)); ErrEntry = IoAllocateErrorLogEntry(gDriverObj, (UCHAR)iTotalLen); if (ErrEntry) { ErrEntry->NumberOfStrings = 1; ErrEntry->ErrorCode = ErrorCode; ErrEntry->StringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData); mbstowcs((WCHAR *)ErrEntry->DumpData, szErrMsg, iLen); ErrEntry->FinalStatus = NTStatus; IoWriteErrorLogEntry(ErrEntry); } else { TWarn(("Failed to allocate error log entry (len=%d).", (int)iTotalLen)); } if (ErrorCode == ERRLOG_DEBUG_INFORMATION) { TInfo(("%s", szErrMsg)); } else if (ErrorCode == ERRLOG_DEBUG_WARNING) { TWarn(("%s", szErrMsg)); } else if (ErrorCode == ERRLOG_DEBUG_ERROR) { TErr(("%s", szErrMsg)); } } } TExit(Func, ("!")); return; } //LogDbgMsg